Skip to content

Commit 0fc26d6

Browse files
author
Maël Hostettler
committed
first draft at geometric evaluation / interpolation integration
1 parent eef761b commit 0fc26d6

File tree

5 files changed

+310
-0
lines changed

5 files changed

+310
-0
lines changed

src/nmod_poly.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@ void _nmod_poly_evaluate_nmod_vec_fast_precomp(nn_ptr vs, nn_srcptr poly, slong
542542
void _nmod_poly_evaluate_nmod_vec_fast(nn_ptr ys, nn_srcptr coeffs, slong len, nn_srcptr xs, slong n, nmod_t mod);
543543
void nmod_poly_evaluate_nmod_vec_fast(nn_ptr ys, const nmod_poly_t poly, nn_srcptr xs, slong n);
544544

545+
void _nmod_poly_evaluate_geometric_nmod_vec_fast_precomp(nn_ptr vs, nn_srcptr poly, slong plen, const nmod_geometric_progression_t G, slong len);
546+
547+
void _nmod_poly_evaluate_geometric_nmod_vec_fast(nn_ptr ys, nn_srcptr coeffs, slong len, ulong r, slong n, nmod_t mod);
548+
void nmod_poly_evaluate_geometric_nmod_vec_fast(nn_ptr ys, const nmod_poly_t poly, ulong r, slong n);
549+
545550
void nmod_mat_one_addmul(nmod_mat_t dest, const nmod_mat_t mat, ulong c);
546551

547552
void nmod_poly_evaluate_mat_horner(nmod_mat_t dest, const nmod_poly_t poly, const nmod_mat_t c);
@@ -569,6 +574,12 @@ void _nmod_poly_tree_free(nn_ptr * tree, slong len);
569574

570575
void _nmod_poly_tree_build(nn_ptr * tree, nn_srcptr roots, slong len, nmod_t mod);
571576

577+
/* Geometric evaluation / interpolation *************************************/
578+
579+
void nmod_geometric_progression_init(nmod_geometric_progression_t G, ulong r, slong n, nmod_t mod);
580+
581+
void nmod_geometric_progression_clear(nmod_geometric_progression_t G);
582+
572583
/* Interpolation ************************************************************/
573584

574585
void _nmod_poly_interpolate_nmod_vec_newton(nn_ptr poly, nn_srcptr xs, nn_srcptr ys, slong n, nmod_t mod);
@@ -586,6 +597,11 @@ void nmod_poly_interpolate_nmod_vec_fast(nmod_poly_t poly, nn_srcptr xs, nn_srcp
586597
void _nmod_poly_interpolate_nmod_vec_fast_precomp(nn_ptr poly, nn_srcptr ys,
587598
const nn_ptr * tree, nn_srcptr weights, slong len, nmod_t mod);
588599

600+
void nmod_poly_interpolate_geometric_nmod_vec_fast(nmod_poly_t poly, ulong r, nn_srcptr ys, slong n);
601+
602+
void nmod_poly_interpolate_geometric_nmod_vec_fast_precomp(nmod_poly_t poly, nn_srcptr v,
603+
const nmod_geometric_progression_t G, slong len);
604+
589605
void _nmod_poly_interpolation_weights(nn_ptr w, const nn_ptr * tree, slong len, nmod_t mod);
590606

591607
/* Composition **************************************************************/
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
Copyright (C) 2025, Vincent Neiger
3+
Copyright (C) 2025, Mael Hostettler
4+
5+
This file is part of FLINT.
6+
7+
FLINT is free software: you can redistribute it and/or modify it under
8+
the terms of the GNU Lesser General Public License (LGPL) as published
9+
by the Free Software Foundation; either version 3 of the License, or
10+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
11+
*/
12+
13+
#include "nmod.h"
14+
#include "nmod_vec.h"
15+
#include "nmod_poly.h"
16+
17+
void
18+
_nmod_poly_evaluate_geometric_nmod_vec_fast_precomp(nn_ptr vs, nn_srcptr poly,
19+
slong plen, const nmod_geometric_progression_t G, slong len)
20+
{
21+
nmod_poly_t a, b;
22+
slong i, d;
23+
24+
d = G->d;
25+
FLINT_ASSERT(len <= d);
26+
27+
if (plen == 0)
28+
{
29+
for (i = 0; i < d; i++)
30+
{
31+
vs[i] = 0;
32+
}
33+
return;
34+
}
35+
36+
nmod_poly_init2(a, G->mod.n, d);
37+
nmod_poly_init(b, G->mod.n);
38+
39+
for (i = 0; i < plen; i++)
40+
{
41+
nmod_poly_set_coeff_ui(a, d - 1 - i, nmod_mul(G->x[i], poly[i], G->mod));
42+
}
43+
44+
for (i = plen + 1; i < d; i++)
45+
{
46+
nmod_poly_set_coeff_ui(a, d - 1 - i, 0);
47+
}
48+
49+
nmod_poly_mul(b, a, G->f);
50+
51+
for (i = 0; i < len; i++)
52+
{
53+
vs[i] = nmod_mul(G->x[i], nmod_poly_get_coeff_ui(b, i+d-1), G->mod);
54+
}
55+
56+
nmod_poly_clear(b);
57+
nmod_poly_clear(a);
58+
}
59+
60+
void
61+
_nmod_poly_evaluate_geometric_nmod_vec_fast(nn_ptr ys, nn_srcptr poly,
62+
slong plen, ulong r, slong n, nmod_t mod)
63+
{
64+
nmod_geometric_progression_t G;
65+
nmod_geometric_progression_init(G, r, n, mod);
66+
67+
_nmod_poly_evaluate_geometric_nmod_vec_fast_precomp(ys, poly, plen, G, n);
68+
nmod_geometric_progression_clear(G);
69+
}
70+
71+
void
72+
nmod_poly_evaluate_geometric_nmod_vec_fast(nn_ptr ys,
73+
const nmod_poly_t poly, ulong r, slong n)
74+
{
75+
_nmod_poly_evaluate_geometric_nmod_vec_fast(ys, poly->coeffs,
76+
poly->length, r, n, poly->mod);
77+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
Copyright (C) 2025, Vincent Neiger
3+
Copyright (C) 2025, Mael Hostettler
4+
5+
This file is part of FLINT.
6+
7+
FLINT is free software: you can redistribute it and/or modify it under
8+
the terms of the GNU Lesser General Public License (LGPL) as published
9+
by the Free Software Foundation; either version 3 of the License, or
10+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
11+
*/
12+
13+
#include "nmod.h"
14+
#include "nmod_vec.h"
15+
#include "nmod_poly.h"
16+
17+
void
18+
nmod_geometric_progression_init(nmod_geometric_progression_t G, ulong r, slong d, nmod_t mod)
19+
{
20+
ulong q, inv_r, inv_q, tmp, qk, inv_qk, qq, s;
21+
nn_ptr diff, inv_diff, prod_diff;
22+
slong i;
23+
24+
G->d = d;
25+
G->mod = mod;
26+
27+
nmod_poly_init2(G->f, mod.n, 2*d-1);
28+
nmod_poly_init(G->g1, mod.n);
29+
nmod_poly_init(G->g2, mod.n);
30+
nmod_poly_set_coeff_ui(G->g1, 0, 1);
31+
nmod_poly_set_coeff_ui(G->g2, 0, 1);
32+
33+
G->x = _nmod_vec_init(d);
34+
G->w = _nmod_vec_init(d);
35+
G->z = _nmod_vec_init(d);
36+
G->y = _nmod_vec_init(d);
37+
38+
G->x[0] = 1;
39+
G->y[0] = 1;
40+
G->w[0] = 1;
41+
G->z[0] = 1;
42+
43+
q = nmod_mul(r, r, mod);
44+
inv_r = nmod_inv(r, mod);
45+
inv_q = nmod_mul(inv_r, inv_r, mod);
46+
47+
nmod_poly_set_coeff_ui(G->f, 0, 1);
48+
tmp = r;
49+
for (i = 1; i < 2*d-1; i++)
50+
{
51+
nmod_poly_set_coeff_ui(G->f, i, nmod_mul(nmod_poly_get_coeff_ui(G->f, i-1), tmp, mod));
52+
tmp = nmod_mul(tmp, q, mod);
53+
}
54+
55+
tmp = inv_r;
56+
for (i = 1; i < d; i++)
57+
{
58+
G->x[i] = nmod_mul(G->x[i-1], tmp, mod);
59+
tmp = nmod_mul(tmp, inv_q, mod);
60+
}
61+
62+
inv_diff = _nmod_vec_init(d);
63+
diff = _nmod_vec_init(d);
64+
prod_diff = _nmod_vec_init(d);
65+
inv_diff[0] = 1;
66+
diff[0] = 1;
67+
prod_diff[0] = 1;
68+
69+
qk = q; // montgomery inversion
70+
for (i = 1; i < d; i++)
71+
{
72+
diff[i] = qk - 1;
73+
inv_diff[i] = diff[i];
74+
qk = nmod_mul(qk, q, mod);
75+
prod_diff[i] = nmod_mul(diff[i], prod_diff[i-1], mod);
76+
}
77+
78+
tmp = n_invmod(prod_diff[d-1], mod.n);
79+
for (i = d-1; i > 0; i--)
80+
{
81+
inv_diff[i] = nmod_mul(prod_diff[i-1], tmp, mod);
82+
tmp = nmod_mul(tmp, diff[i], mod);
83+
}
84+
inv_diff[0] = tmp;
85+
// end montgomery inversion
86+
87+
// sets sequences w, y, z and polynomials g1, g2
88+
qk = 1;
89+
inv_qk = 1;
90+
qq = 1;
91+
s = 1;
92+
93+
for (i = 1; i < d; i++)
94+
{
95+
qq = nmod_mul(qq, qk, mod); // prod q^i
96+
s = nmod_mul(s, inv_qk, mod); // prod 1/q^i
97+
G->w[i] = nmod_mul(G->w[i-1], inv_diff[i], mod); // prod 1/(q^i-1)
98+
tmp = nmod_mul(qq, G->w[i], mod); // prod q^i/(q^i-1)
99+
nmod_poly_set_coeff_ui(G->g2, i, tmp);
100+
101+
if ((i & 1) == 1)
102+
{
103+
nmod_poly_set_coeff_ui(G->g1, i, nmod_neg(tmp, mod));
104+
G->y[i] = nmod_neg(prod_diff[i], mod);
105+
G->z[i] = nmod_neg(G->w[i], mod);
106+
}
107+
else
108+
{
109+
nmod_poly_set_coeff_ui(G->g1, i, tmp);
110+
G->y[i] = prod_diff[i];
111+
G->z[i] = G->w[i];
112+
}
113+
G->y[i] = nmod_mul(G->y[i], s, mod);
114+
115+
qk = nmod_mul(qk, q, mod);
116+
inv_qk = nmod_mul(inv_qk, inv_q, mod);
117+
}
118+
119+
_nmod_vec_clear(prod_diff);
120+
_nmod_vec_clear(inv_diff);
121+
_nmod_vec_clear(diff);
122+
}
123+
124+
void
125+
nmod_geometric_progression_clear(nmod_geometric_progression_t G)
126+
{
127+
nmod_poly_clear(G->f);
128+
nmod_poly_clear(G->g2);
129+
nmod_poly_clear(G->g1);
130+
_nmod_vec_clear(G->x);
131+
_nmod_vec_clear(G->z);
132+
_nmod_vec_clear(G->y);
133+
_nmod_vec_clear(G->w);
134+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright (C) 2025, Vincent Neiger
3+
Copyright (C) 2025, Mael Hostettler
4+
5+
This file is part of FLINT.
6+
7+
FLINT is free software: you can redistribute it and/or modify it under
8+
the terms of the GNU Lesser General Public License (LGPL) as published
9+
by the Free Software Foundation; either version 3 of the License, or
10+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
11+
*/
12+
13+
#include "nmod.h"
14+
#include "nmod_vec.h"
15+
#include "nmod_poly.h"
16+
17+
void
18+
nmod_poly_interpolate_geometric_nmod_vec_fast_precomp(nmod_poly_t poly, nn_srcptr v,
19+
const nmod_geometric_progression_t G, slong len)
20+
{
21+
slong i, N;
22+
nmod_poly_t f, h;
23+
nmod_t mod;
24+
25+
N = G->d;
26+
FLINT_ASSERT(len == N);
27+
nmod_poly_fit_length(poly, N);
28+
nmod_poly_zero(poly);
29+
30+
if (N == 1)
31+
{
32+
nmod_poly_set_coeff_ui(poly, 0, v[0]);
33+
return;
34+
}
35+
36+
mod = G->mod;
37+
nmod_poly_init2(f, mod.n, N);
38+
nmod_poly_init2(h, mod.n, N);
39+
40+
for(i = 0; i < N; i++)
41+
{
42+
nmod_poly_set_coeff_ui(f, i, nmod_mul(v[i], G->w[i], mod));
43+
}
44+
45+
nmod_poly_mullow(h, f, G->g1, N);
46+
47+
for (i = 0; i < N; i++)
48+
{
49+
nmod_poly_set_coeff_ui(f, N - 1 - i, nmod_mul(nmod_poly_get_coeff_ui(h, i), G->y[i], mod));
50+
}
51+
52+
nmod_poly_mullow(h, f, G->g2, N);
53+
54+
for (i = 0; i < N; i++)
55+
{
56+
nmod_poly_set_coeff_ui(poly, i, nmod_mul(nmod_poly_get_coeff_ui(h, N - 1 - i), G->z[i], mod));
57+
}
58+
59+
nmod_poly_clear(f);
60+
nmod_poly_clear(h);
61+
}
62+
63+
void
64+
nmod_poly_interpolate_geometric_nmod_vec_fast(nmod_poly_t poly, ulong r,
65+
nn_srcptr ys, slong n)
66+
{
67+
nmod_geometric_progression_t G;
68+
nmod_geometric_progression_init(G, r, n, poly->mod);
69+
70+
nmod_poly_interpolate_geometric_nmod_vec_fast_precomp(poly, ys, G, n);
71+
nmod_geometric_progression_clear(G);
72+
}

src/nmod_types.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ nmod_mpoly_factor_struct;
8888

8989
typedef nmod_mpoly_factor_struct nmod_mpoly_factor_t[1];
9090

91+
typedef struct
92+
{
93+
nn_ptr x, t, w, y, z; // five vectors of precomputed constants
94+
nmod_poly_t f, g1, g2; // three precomputed polys
95+
nmod_t mod;
96+
slong d; // number of points
97+
98+
} nmod_geometric_progression_struct;
99+
100+
typedef nmod_geometric_progression_struct nmod_geometric_progression_t[1];
101+
91102
typedef enum
92103
{
93104
_DOT0 = 0, /* len == 0 || mod.n == 1 */

0 commit comments

Comments
 (0)