Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions doc/source/fmpz_factor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,35 @@ A separate ``int`` field holds the sign, which may be `-1`, `0` or `1`.
https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf


Utility
--------------------------------------------------------------------------------

.. function:: void fmpz_factor_sort(fmpz_factor_t factor)

Sorts ``factor`` in-place such that the factors are in ascending order.

Arithmetic
--------------------------------------------------------------------------------

.. function:: void _fmpz_factor_mul(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)

Sets ``factor`` to the factored representation of `a \times b` assuming ``a`` and ``b``
are sorted.

.. function:: void fmpz_factor_mul(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)

Sets ``factor`` to the factored representation of `a \times b` by first sorting ``a`` and ``b``.

.. function:: void _fmpz_factor_gcd(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)

Sets ``factor`` to the factored representation of `\gcd(a, b)` assuming ``a`` and ``b``
are sorted.

.. function:: void fmpz_factor_gcd(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)

Sets ``factor`` to the factored representation of `\gcd(a, b)` by first sorting ``a`` and ``b``.


Input and output
--------------------------------------------------------------------------------

Expand Down
10 changes: 10 additions & 0 deletions src/fmpz_factor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ void _fmpz_factor_append_ui(fmpz_factor_t factor, ulong p, ulong exp);

void _fmpz_factor_concat(fmpz_factor_t factor1, fmpz_factor_t factor2, ulong exp);

void fmpz_factor_sort(fmpz_factor_t factor);

/* Arithmetic ****************************************************************/

void _fmpz_factor_mul(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b);
void fmpz_factor_gcd(fmpz_factor_t factor, fmpz_factor_t a, fmpz_factor_t b);

void _fmpz_factor_gcd(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b);
void fmpz_factor_mul(fmpz_factor_t factor, fmpz_factor_t a, fmpz_factor_t b);

/* I/O ***********************************************************************/

#ifdef FLINT_HAVE_FILE
Expand Down
59 changes: 59 additions & 0 deletions src/fmpz_factor/gcd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright (C) 2025 Mael Hostettler

This file is part of FLINT.

FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "fmpz.h"
#include "fmpz_factor.h"

void
_fmpz_factor_gcd(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)
{
slong i, j;
ulong num_len;
int cmp;

num_len = FLINT_MIN(a->num, b->num);
_fmpz_factor_fit_length(factor, num_len);
factor->sign = 1;
factor->num = 0;

i = 0;
j = 0;
factor->num = 0;

while ((i < a->num) && (j < b->num))
{
cmp = fmpz_cmp(a->p + i, b->p + j);
if (cmp < 0) // a[i] < b[i]
{
i++;
}
else if (cmp > 0) // b[i] < a[i]
{
j++;
}
else // b[i] = a[i]
{
fmpz_set(factor->p + factor->num, a->p + i);
factor->exp[factor->num] = FLINT_MIN(a->exp[i], b->exp[j]);
factor->num++;
i++;
j++;
}
}
}

void fmpz_factor_gcd(fmpz_factor_t factor, fmpz_factor_t a, fmpz_factor_t b)
{
fmpz_factor_sort(a);
fmpz_factor_sort(b);

_fmpz_factor_gcd(factor, a, b);
}
78 changes: 78 additions & 0 deletions src/fmpz_factor/mul.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Copyright (C) 2025 Mael Hostettler

This file is part of FLINT.

FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "fmpz.h"
#include "fmpz_factor.h"

void
_fmpz_factor_mul(fmpz_factor_t factor, const fmpz_factor_t a, const fmpz_factor_t b)
{
slong i, j;
int cmp;

_fmpz_factor_fit_length(factor, a->num + b->num);
factor->sign = a->sign * b->sign;

i = 0;
j = 0;
factor->num = 0;

while ((i < a->num) && (j < b->num))
{
cmp = fmpz_cmp(a->p + i, b->p + j);
if (cmp < 0) // a[i] < b[i]
{
fmpz_set(factor->p + factor->num, a->p + i);
factor->exp[factor->num] = a->exp[i];
factor->num++;
i++;
}
else if (cmp > 0) // b[i] < a[i]
{
fmpz_set(factor->p + factor->num, b->p + j);
factor->exp[factor->num] = b->exp[j];
factor->num++;
j++;
}
else // b[i] = a[i]
{
fmpz_set(factor->p + factor->num, a->p + i);
factor->exp[factor->num] = a->exp[i] + b->exp[j];
factor->num++;
i++;
j++;
}
}

while (i < a->num)
{
fmpz_set(factor->p + factor->num, a->p + i);
factor->exp[factor->num] = a->exp[i];
factor->num++;
i++;
}

while (j < b->num)
{
fmpz_set(factor->p + factor->num, b->p + j);
factor->exp[factor->num] = b->exp[j];
factor->num++;
j++;
}
}

void fmpz_factor_mul(fmpz_factor_t factor, fmpz_factor_t a, fmpz_factor_t b)
{
fmpz_factor_sort(a);
fmpz_factor_sort(b);

_fmpz_factor_mul(factor, a, b);
}
43 changes: 43 additions & 0 deletions src/fmpz_factor/sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Copyright (C) 2025 Mael Hostettler

This file is part of FLINT.

FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/
#include "fmpz.h"
#include "fmpz_factor.h"

// Tiny implem of quick sort, qsort is not usable because we also want to permute exp
// and qsort_r / qsort_s have portability issues
static void _fmpz_factor_sort_part(fmpz* p, ulong* exp, slong n)
{
slong i, j;
if (n <= 1) return;

fmpz_swap(p + n / 2, p + n - 1);
FLINT_SWAP(ulong, exp[n / 2], exp[n - 1]);
for (i = 0, j = 0; i < n - 1; i++)
{
if (fmpz_cmp(p + i, p + n - 1) < 0)
{
fmpz_swap(p + i, p + j);
FLINT_SWAP(ulong, exp[i], exp[j]);
j++;
}
}
fmpz_swap(p + j, p + n - 1);
FLINT_SWAP(ulong, exp[j], exp[n - 1]);

_fmpz_factor_sort_part(p, exp, j);
_fmpz_factor_sort_part(p + j + 1, exp + j + 1, n - j - 1);
}

void
fmpz_factor_sort(fmpz_factor_t factor)
{
_fmpz_factor_sort_part(factor->p, factor->exp, factor->num);
}
9 changes: 7 additions & 2 deletions src/fmpz_factor/test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include "t-pollard_brent.c"
#include "t-pollard_brent_single.c"
#include "t-refine.c"

#include "t-sort.c"
#include "t-mul.c"
#include "t-gcd.c"
/* Array of test functions ***************************************************/

test_struct tests[] =
Expand All @@ -35,7 +37,10 @@ test_struct tests[] =
TEST_FUNCTION(fmpz_factor_trial),
TEST_FUNCTION(fmpz_factor_pollard_brent),
TEST_FUNCTION(fmpz_factor_pollard_brent_single),
TEST_FUNCTION(fmpz_factor_refine)
TEST_FUNCTION(fmpz_factor_refine),
TEST_FUNCTION(fmpz_factor_sort),
TEST_FUNCTION(fmpz_factor_mul),
TEST_FUNCTION(fmpz_factor_gcd)
};

/* main function *************************************************************/
Expand Down
65 changes: 65 additions & 0 deletions src/fmpz_factor/test/t-gcd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright (C) 2025 Mael Hostettler

This file is part of FLINT.

FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "test_helpers.h"
#include "fmpz.h"
#include "fmpz_factor.h"

TEST_FUNCTION_START(fmpz_factor_gcd, state)
{
slong i, b;
fmpz_t x, y;
fmpz_factor_t fx, fy, fz;

fmpz_init(x);
fmpz_init(y);
fmpz_factor_init(fx);
fmpz_factor_init(fy);
fmpz_factor_init(fz);

for (i = 0; i < 1000 * flint_test_multiplier(); i++)
{
b = n_randint(state, 1000000);
if (n_randint(state, 2))
b = -b;
fmpz_set_si(x, b);

b = n_randint(state, 1000000);
if (n_randint(state, 2))
b = -b;
fmpz_set_si(y, b);

fmpz_factor(fx, x);
fmpz_factor(fy, y);

fmpz_factor_gcd(fz, fx, fy);

fmpz_gcd(x, x, y);
fmpz_factor_expand(y, fz);

if (fmpz_cmp(x, y) != 0)
{
flint_printf("FAIL (factor gcd)\n");
fmpz_print(x); flint_printf(" ");
fmpz_print(y); flint_printf("\n");
fflush(stdout);
flint_abort();
}
}

fmpz_clear(x);
fmpz_clear(y);
fmpz_factor_clear(fx);
fmpz_factor_clear(fy);
fmpz_factor_clear(fz);

TEST_FUNCTION_END(state);
}
65 changes: 65 additions & 0 deletions src/fmpz_factor/test/t-mul.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright (C) 2025 Mael Hostettler

This file is part of FLINT.

FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "test_helpers.h"
#include "fmpz.h"
#include "fmpz_factor.h"

TEST_FUNCTION_START(fmpz_factor_mul, state)
{
slong i, b;
fmpz_t x, y;
fmpz_factor_t fx, fy, fz;

fmpz_init(x);
fmpz_init(y);
fmpz_factor_init(fx);
fmpz_factor_init(fy);
fmpz_factor_init(fz);

for (i = 0; i < 1000 * flint_test_multiplier(); i++)
{
b = n_randint(state, 1000000);
if (n_randint(state, 2))
b = -b;
fmpz_set_si(x, b);

b = n_randint(state, 1000000);
if (n_randint(state, 2))
b = -b;
fmpz_set_si(y, b);

fmpz_factor(fx, x);
fmpz_factor(fy, y);

fmpz_factor_mul(fz, fx, fy);

fmpz_mul(x, x, y);
fmpz_factor_expand(y, fz);

if (fmpz_cmp(x, y) != 0)
{
flint_printf("FAIL (factor mul)\n");
fmpz_print(x); flint_printf(" ");
fmpz_print(y); flint_printf("\n");
fflush(stdout);
flint_abort();
}
}

fmpz_clear(x);
fmpz_clear(y);
fmpz_factor_clear(fx);
fmpz_factor_clear(fy);
fmpz_factor_clear(fz);

TEST_FUNCTION_END(state);
}
Loading
Loading