Skip to content
Merged
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
3 changes: 3 additions & 0 deletions dev/check_examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ then
echo "PASS"
exit 0

elif test "$1" = "minimal_irreducibles";
then
echo "minimal_irreducibles....SKIPPED"
elif test "$1" = "multi_crt";
then
echo "multi_crt....SKIPPED"
Expand Down
13 changes: 12 additions & 1 deletion doc/source/fq_nmod.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,25 @@ Context Management

Initialises the context for prime `p` and extension degree `d`,
with name ``var`` for the generator. By default, it will try
use a Conway polynomial; if one is not available, a random
use a Conway polynomial; if one is not available, a minimal weight
irreducible polynomial will be used.

Assumes that `p` is a prime.

Assumes that the string ``var`` is a null-terminated string
of length at least one.

.. function:: fq_nmod_ctx_init_minimal_weight_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var)

Initialises the context for prime `p` and extension degree `d`,
with name ``var`` for the generator, choosing a modulus polynomial
with minimal number of nonzero terms for efficient arithmetic.

Assumes that `p` is a prime.

Assumes that the string ``var`` is a null-terminated string
of length at least one.

.. function:: int _fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char * var)

Attempts to initialise the context for prime `p` and extension
Expand Down
50 changes: 37 additions & 13 deletions doc/source/nmod_poly.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,47 @@ Randomization

Generates a random polynomial with length up to ``len``.

.. function:: void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random irreducible polynomial with length up to ``len``.

.. function:: void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic polynomial with length ``len``.

.. function:: void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic trinomial of length ``len``.

.. function:: void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic pentomial of length ``len``.

Construction of irreducible polynomials
--------------------------------------------------------------------------------

The following functions assume a prime modulus.

.. function:: void nmod_poly_minimal_irreducible(nmod_poly_t res, ulong n)

Generates a monic irreducible polynomial of degree ``n`` with minimal
weight (minimal number of nonzero terms). We generate a binomial
if possible, otherwise a trinomial, etc.
It is conjectured that one never needs more than a pentanomial
modulo `p = 2` and a tetranomial modulo `p > 2`.

More specifically, this function returns the first among all minimal-weight
polynomials in the following ordering.
Firstly, for trinomials, `x^n + a x^k + b` comes before
its monic reversal `x^n + a' x^{n-k} + b'` if `k < n - k`.
Secondly, writing
`f = x^n + a_1 x^{k_1} + a_2 x^{k_2} + \ldots + a_t x^{k_t}`
with `n > k_1 > k_2 \ldots > k_t`, we order tuples
`(a_1, \ldots, a_{t}, k_1, \ldots, k_t)` lexicographically.
We thus favor polynomials with smaller coefficients
(all 1 if possible), and secondly with smaller degrees for the
middle terms.

.. function:: void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random irreducible polynomial with length up to ``len``.

.. function:: void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic irreducible polynomial with length ``len``.
Expand All @@ -239,11 +272,6 @@ Randomization
Generates a random monic irreducible primitive polynomial with
length ``len``.


.. function:: void nmod_poly_randtest_trinomial(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic trinomial of length ``len``.

.. function:: int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts)

Attempts to set ``poly`` to a monic irreducible trinomial of
Expand All @@ -253,10 +281,6 @@ Randomization
trinomials until an irreducible one is found. Returns `1` if one
is found and `0` otherwise.

.. function:: void nmod_poly_randtest_pentomial(nmod_poly_t poly, flint_rand_t state, slong len)

Generates a random monic pentomial of length ``len``.

.. function:: int nmod_poly_randtest_pentomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts)

Attempts to set ``poly`` to a monic irreducible pentomial of
Expand Down
103 changes: 103 additions & 0 deletions examples/minimal_irreducibles.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
Generate irreducible polynomial of minimal weight over GF(p)
for degrees nmin <= n <= nmax.

This file is public domain. Author: Fredrik Johansson.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "flint/thread_support.h"
#include "flint/ulong_extras.h"
#include "flint/nmod_poly.h"
#include "flint/nmod_poly_factor.h"
#include "flint/profiler.h"

typedef struct
{
nmod_poly_struct * f;
ulong nstart;
}
workinfo_t;

void
worker(slong i, void * work)
{
nmod_poly_struct * f = ((workinfo_t *) work)->f;
ulong nstart = ((workinfo_t *) work)->nstart;
nmod_poly_minimal_irreducible(f + i, nstart + i);
}

int
main(int argc, char * argv[])
{
slong i;
int num_threads = 1;
ulong p, n, na, nb, nmin, nmax;
slong batch_size;
workinfo_t work;

if (argc < 4)
{
flint_printf("usage: minimal_irreducibles [-threads t] p nmin nmax\n");
return 1;
}

p = 0;
nmin = 0;
nmax = 0;

for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-threads"))
{
num_threads = atoi(argv[i+1]);
flint_set_num_threads(num_threads);
i++;
}
else if (i == argc - 3)
p = atol(argv[i]);
else if (i == argc - 2)
nmin = atol(argv[i]);
else if (i == argc - 1)
nmax = atol(argv[i]);
}

flint_printf("p = %wu, nmin = %wu, nmax = %wu\n", p, nmin, nmax);

if (!n_is_prime(p))
flint_throw(FLINT_ERROR, "p = %wu is not prime\n", p);

if (num_threads == 1)
batch_size = 1;
else
batch_size = FLINT_MIN(10 * num_threads, nmax - nmin + 1);
work.f = flint_malloc(sizeof(nmod_poly_struct) * batch_size);
for (i = 0; i < batch_size; i++)
nmod_poly_init(work.f + i, p);

TIMEIT_ONCE_START
na = nmin;
while (1)
{
work.nstart = na;
nb = FLINT_MIN(na + batch_size - 1, nmax);
flint_parallel_do(worker, &work, nb - na + 1, 0, 0);
for (n = na; n <= nb; n++)
flint_printf("%{nmod_poly}\n", work.f + n - na);
na = nb + 1;
if (na > nmax)
break;
}
TIMEIT_ONCE_STOP
SHOW_MEMORY_USAGE

for (i = 0; i < batch_size; i++)
nmod_poly_clear(work.f + i);
flint_free(work.f);

flint_cleanup_master();
return 0;
}

1 change: 1 addition & 0 deletions src/fq_nmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
void fq_nmod_ctx_init_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var);
int _fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var);
void fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var);
void fq_nmod_ctx_init_minimal_weight_ui(fq_nmod_ctx_t ctx, ulong prime, slong deg, const char * var);
void fq_nmod_ctx_init_modulus(fq_nmod_ctx_t ctx, const nmod_poly_t modulus, const char * var);

void fq_nmod_ctx_init_randtest(fq_nmod_ctx_t ctx, flint_rand_t state, int type);
Expand Down
28 changes: 13 additions & 15 deletions src/fq_nmod/ctx_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,27 @@ void fq_nmod_ctx_init_conway_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char
ctx->is_conway = 1;
}

void fq_nmod_ctx_init_minimal_weight_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char *var)
{
nmod_poly_t poly;

ctx->is_conway = 0;

nmod_poly_init2(poly, p, d + 1);
nmod_poly_minimal_irreducible(poly, d);
fq_nmod_ctx_init_modulus(ctx, poly, var);
nmod_poly_clear(poly);
}

void fq_nmod_ctx_init_ui(fq_nmod_ctx_t ctx, ulong p, slong d, const char *var)
{
if (_fq_nmod_ctx_init_conway_ui(ctx, p, d, var))
{
ctx->is_conway = 1;
return;
}
else
{
flint_rand_t state;
nmod_poly_t poly;

ctx->is_conway = 0;

flint_rand_init(state);

nmod_poly_init2(poly, p, d + 1);
nmod_poly_randtest_sparse_irreducible(poly, state, d + 1);

fq_nmod_ctx_init_modulus(ctx, poly, var);

nmod_poly_clear(poly);
flint_rand_clear(state);
fq_nmod_ctx_init_minimal_weight_ui(ctx, p, d, var);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/nmod_poly.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ void nmod_poly_randtest_not_zero(nmod_poly_t poly, flint_rand_t state, slong len
} while (nmod_poly_is_zero(poly));
}

/* Construction of irreducibles *********************************************/

void nmod_poly_minimal_irreducible(nmod_poly_t res, ulong n);

void nmod_poly_randtest_irreducible(nmod_poly_t poly, flint_rand_t state, slong len);

void nmod_poly_randtest_monic(nmod_poly_t poly, flint_rand_t state, slong len);
Expand Down
Loading