Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit de176f3

Browse files
committedApr 6, 2024
Add example for calculating p-adic roots.
Example for calculating p-adic roots of a polynomial over the integers.
1 parent 6879047 commit de176f3

File tree

1 file changed

+447
-0
lines changed

1 file changed

+447
-0
lines changed
 

‎examples/padic_roots.c

+447
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,447 @@
1+
/* This file is public domain. Author: Hartmut Monien. */
2+
3+
#include <stdlib.h>
4+
5+
#include "flint.h"
6+
7+
#include "ulong_extras.h"
8+
9+
#include "fmpz_poly.h"
10+
#include "fmpz_poly_factor.h"
11+
12+
#include "fmpz_mod.h"
13+
#include "fmpz_mod_poly.h"
14+
15+
#include "fq.h"
16+
#include "fq_vec.h"
17+
#include "fq_poly.h"
18+
#include "fq_poly_factor.h"
19+
20+
#include "padic.h"
21+
22+
typedef struct
23+
{
24+
fq_struct *x0;
25+
slong *multiplicity;
26+
slong num;
27+
slong alloc;
28+
} fmpz_poly_roots_fq_struct;
29+
30+
typedef fmpz_poly_roots_fq_struct fmpz_poly_roots_fq_t[1];
31+
32+
void fmpz_poly_roots_fq_init(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx);
33+
void fmpz_poly_roots_fq_clear(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx);
34+
int fmpz_poly_roots_fq_print(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx);
35+
int fmpz_poly_roots_fq_fprint_pretty(FILE * file, fmpz_poly_roots_fq_t roots,
36+
fq_ctx_t fctx);
37+
int fmpz_poly_roots_fq_print_pretty(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx);
38+
void fmpz_poly_roots_fq(fmpz_poly_roots_fq_t roots, fmpz_poly_t poly,
39+
fq_ctx_t fctx);
40+
41+
42+
void
43+
fmpz_poly_roots_fq_init(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
44+
{
45+
roots->x0 = NULL;
46+
roots->multiplicity = NULL;
47+
roots->num = 0;
48+
roots->alloc = 0;
49+
}
50+
51+
void
52+
fmpz_poly_roots_fq_clear(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
53+
{
54+
_fq_vec_clear(roots->x0, roots->alloc, fctx);
55+
flint_free(roots->multiplicity);
56+
}
57+
58+
59+
char *
60+
fmpz_poly_roots_fq_get_str(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
61+
{
62+
char *buffer = NULL;
63+
size_t buffer_size = 0;
64+
FILE *out = open_memstream(&buffer, &buffer_size);
65+
66+
_fq_vec_fprint(out, roots->x0, roots->num, fctx);
67+
fclose(out);
68+
69+
return buffer;
70+
}
71+
72+
int
73+
fmpz_poly_roots_fq_print(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
74+
{
75+
_fq_vec_print(roots->x0, roots->num, fctx);
76+
return 1;
77+
}
78+
79+
char *
80+
fmpz_poly_roots_fq_get_str_pretty(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
81+
{
82+
char *buffer = NULL;
83+
size_t buffer_size = 0;
84+
FILE *out = open_memstream(&buffer, &buffer_size);
85+
slong j;
86+
87+
for (j = 0; j < roots->num; j++)
88+
{
89+
fq_fprint_pretty(out, roots->x0 + j, fctx);
90+
flint_fprintf(out, " %wd\n", roots->multiplicity[j]);
91+
}
92+
93+
fclose(out);
94+
95+
return buffer;
96+
}
97+
98+
int
99+
fmpz_poly_roots_fq_fprint_pretty(FILE *file, fmpz_poly_roots_fq_t roots,
100+
fq_ctx_t fctx)
101+
{
102+
slong j;
103+
104+
for (j = 0; j < roots->num; j++)
105+
{
106+
fq_fprint_pretty(file, roots->x0 + j, fctx);
107+
flint_fprintf(file, " %wd\n", roots->multiplicity[j]);
108+
}
109+
110+
return 1;
111+
}
112+
113+
int
114+
fmpz_poly_roots_fq_print_pretty(fmpz_poly_roots_fq_t roots, fq_ctx_t fctx)
115+
{
116+
fmpz_poly_roots_fq_fprint_pretty(stdout, roots, fctx);
117+
return 1;
118+
}
119+
120+
void
121+
fmpz_poly_roots_fq(fmpz_poly_roots_fq_t roots, fmpz_poly_t poly, fq_ctx_t fctx)
122+
{
123+
slong j, k, num;
124+
125+
fmpz_mod_ctx_t fmctx;
126+
fmpz_mod_poly_t mpoly;
127+
fq_poly_factor_t f;
128+
fq_poly_t fpoly;
129+
130+
fmpz_mod_ctx_init(fmctx, fq_ctx_prime(fctx));
131+
fmpz_mod_poly_init(mpoly, fmctx);
132+
fmpz_mod_poly_set_fmpz_poly(mpoly, poly, fmctx);
133+
134+
fq_poly_factor_init(f, fctx);
135+
fq_poly_init(fpoly, fctx);
136+
fq_poly_set_fmpz_mod_poly(fpoly, mpoly, fctx);
137+
138+
fq_poly_roots(f, fpoly, 1, fctx);
139+
140+
fmpz_mod_poly_clear(mpoly, fmctx);
141+
fmpz_mod_ctx_clear(fmctx);
142+
fq_poly_clear(fpoly, fctx);
143+
144+
num = 0;
145+
146+
for (j = 0; j < f->num; j++)
147+
{
148+
if (fq_poly_degree(f->poly + j, fctx) == 1)
149+
num++;
150+
}
151+
152+
roots->x0 = _fq_vec_init(num, fctx);
153+
roots->multiplicity = flint_malloc(sizeof(slong) * num);
154+
roots->num = num;
155+
roots->alloc = num;
156+
157+
k = 0;
158+
159+
for (j = 0; j < f->num; j++)
160+
{
161+
if (fq_poly_degree(f->poly + j, fctx) == 1)
162+
{
163+
fq_poly_get_coeff(roots->x0 + k, f->poly + j, 0, fctx);
164+
fq_neg(roots->x0 + k, roots->x0 + k, fctx);
165+
roots->multiplicity[k] = f->exp[j];
166+
k++;
167+
}
168+
}
169+
}
170+
171+
static void
172+
padic_hensel_iteration(fmpz_poly_t poly,
173+
padic_t x, padic_ctx_t ctx, slong prec)
174+
{
175+
padic_t tmp, y0, y1;
176+
padic_init2(tmp, prec);
177+
padic_init2(y0, prec);
178+
padic_init2(y1, prec);
179+
do
180+
{
181+
/* Horner evaluation of poly and poly' at x */
182+
padic_set_fmpz(y0, poly->coeffs + poly->length - 1, ctx);
183+
padic_zero(y1);
184+
for (slong j = poly->length - 2; j >= 0; j--)
185+
{
186+
padic_mul(y1, y1, x, ctx);
187+
padic_add(y1, y1, y0, ctx);
188+
padic_mul(y0, y0, x, ctx);
189+
padic_set_fmpz(tmp, poly->coeffs + j, ctx);
190+
padic_add(y0, y0, tmp, ctx);
191+
}
192+
/* Newton step: x -> x - poly / poly' */
193+
padic_inv(y1, y1, ctx);
194+
padic_mul(y1, y1, y0, ctx);
195+
padic_sub(x, x, y1, ctx);
196+
}
197+
while (padic_val(y0));
198+
padic_clear(tmp);
199+
padic_clear(y0);
200+
padic_clear(y1);
201+
}
202+
203+
static padic_struct *
204+
_padic_vec_init2(slong len, slong prec)
205+
{
206+
slong j;
207+
padic_struct *vec = flint_malloc(len * sizeof(padic_t));
208+
for (j = 0; j < len; j++)
209+
{
210+
padic_init2(vec + j, prec);
211+
}
212+
return vec;
213+
}
214+
215+
static void
216+
_padic_vec_clear(padic_struct *vec, slong len)
217+
{
218+
slong j;
219+
for (j = 0; j < len; j++)
220+
{
221+
padic_clear(vec + j);
222+
}
223+
flint_free(vec);
224+
}
225+
226+
static fmpz_poly_struct *
227+
_fmpz_poly_vec_init(slong len)
228+
{
229+
slong j;
230+
fmpz_poly_struct *vec = flint_malloc(len * sizeof(fmpz_poly_t));
231+
for (j = 0; j < len; j++)
232+
{
233+
fmpz_poly_init(vec + j);
234+
}
235+
return vec;
236+
}
237+
238+
static void
239+
_fmpz_poly_vec_clear(fmpz_poly_struct *vec, slong len)
240+
{
241+
slong j;
242+
for (j = 0; j < len; j++)
243+
{
244+
fmpz_poly_clear(vec + j);
245+
}
246+
flint_free(vec);
247+
}
248+
249+
void
250+
_padic_roots(fmpz_poly_t poly, fq_ctx_t fctx, padic_ctx_t pctx, slong prec)
251+
{
252+
slong j, level, js, ns = 1, nr = 0, nz = 0, n = fmpz_poly_degree(poly);
253+
fmpz_poly_struct *s = _fmpz_poly_vec_init(n);
254+
padic_struct
255+
* x0 = _padic_vec_init2(n, prec), *xs = _padic_vec_init2(n, prec);
256+
fmpz_poly_roots_fq_t froots;
257+
fmpz_poly_t xi;
258+
fmpz_poly_init(xi);
259+
fmpz_poly_set_coeff_fmpz(xi, 1, pctx->p);
260+
fmpz_t zero;
261+
fmpz_init(zero);
262+
fmpz_poly_set(s, poly);
263+
padic_zero(xs);
264+
for (level = 0; level < PADIC_DEFAULT_PREC; level++)
265+
{
266+
for (js = 0; js < ns; js++)
267+
{
268+
if (!fmpz_poly_is_zero(s + js))
269+
{
270+
fmpz_poly_roots_fq_init(froots, fctx);
271+
fmpz_poly_roots_fq(froots, s + js, fctx);
272+
for (j = 0; j < froots->num; j++)
273+
{
274+
fmpz_poly_get_coeff_fmpz(zero, froots->x0 + j, 0);
275+
if (*(froots->multiplicity + j) > 1)
276+
{
277+
padic_set_fmpz(xs + n - 1 - nr, zero, pctx);
278+
padic_shift(xs + n - 1 - nr, xs + n - 1 - nr, level,
279+
pctx);
280+
padic_add(xs + n - 1 - nr, xs + n - 1 - nr, xs + js,
281+
pctx);
282+
if (level + 1 < PADIC_DEFAULT_PREC)
283+
{
284+
fmpz_poly_set_coeff_fmpz(xi, 0, zero);
285+
fmpz_poly_compose(s + n - 1 - nr, s + js, xi);
286+
fmpz_pow_ui(zero, pctx->p,
287+
*(froots->multiplicity + j));
288+
if (fmpz_divisible
289+
(fmpz_poly_get_coeff_ptr(s + n - 1 - nr, 0),
290+
zero))
291+
{
292+
fmpz_poly_scalar_divexact_fmpz(s + n - 1 - nr,
293+
s + n - 1 - nr,
294+
zero);
295+
nr++;
296+
}
297+
}
298+
else
299+
{
300+
padic_print(xs + n - 1 - nr, pctx);
301+
flint_printf(" (%wd)\n",
302+
*(froots->multiplicity + j));
303+
}
304+
}
305+
else
306+
{
307+
padic_set_fmpz(x0 + nz, zero, pctx);
308+
if (!fmpz_is_zero(zero))
309+
{
310+
padic_shift(x0 + nz, x0 + nz, level, pctx);
311+
}
312+
padic_add(x0 + nz, x0 + nz, xs + js, pctx);
313+
padic_hensel_iteration(poly, x0 + nz, pctx, prec);
314+
padic_print(x0 + nz, pctx);
315+
flint_printf(" (1)\n");
316+
nz++;
317+
}
318+
}
319+
fmpz_poly_roots_fq_clear(froots, fctx);
320+
}
321+
else
322+
{
323+
padic_print(xs + n - 1 - nr, pctx);
324+
flint_printf(" (%wd)\n", fmpz_poly_degree(s + js));
325+
}
326+
}
327+
for (j = 0; j < nr; j++)
328+
{
329+
fmpz_poly_set(s + j, s + n - 1 - j);
330+
padic_set(xs + j, xs + n - 1 - j, pctx);
331+
}
332+
ns = nr;
333+
nr = 0;
334+
}
335+
fmpz_clear(zero);
336+
fmpz_poly_clear(xi);
337+
_padic_vec_clear(x0, n);
338+
_padic_vec_clear(xs, n);
339+
_fmpz_poly_vec_clear(s, n);
340+
}
341+
342+
void
343+
padic_roots(fmpz_poly_t poly, padic_ctx_t pctx, slong prec)
344+
{
345+
slong j, deg;
346+
fmpz_t tmp;
347+
fmpz_poly_factor_t f;
348+
padic_t x;
349+
fq_ctx_t fctx;
350+
fq_ctx_init(fctx, pctx->p, 1, "a");
351+
fmpz_init(tmp);
352+
padic_init(x);
353+
fmpz_poly_factor_init(f);
354+
fmpz_poly_factor(f, poly);
355+
for (j = 0; j < f->num; j++)
356+
{
357+
deg = fmpz_poly_degree(f->p + j);
358+
if (deg == 1)
359+
{
360+
fmpz_set(tmp, fmpz_poly_get_coeff_ptr(f->p + j, 0));
361+
fmpz_neg(tmp, tmp);
362+
padic_set_fmpz(x, tmp, pctx);
363+
padic_print(x, pctx);
364+
flint_printf(" (%wd)\n", *(f->exp + j));
365+
}
366+
else
367+
{
368+
_padic_roots(f->p + j, fctx, pctx, prec);
369+
}
370+
}
371+
fq_ctx_clear(fctx);
372+
}
373+
374+
/* example polynomials */
375+
376+
char *polys[] = {
377+
"3 -2774119 -2468 1",
378+
"3 6 -7 1",
379+
"4 -156 188 -33 1",
380+
"3 -11 0 1",
381+
"3 -30 1 1",
382+
"4 -17576 2028 -78 1",
383+
"10 -362880 1026576 -1172700 723680 -269325 63273 -9450 870 -45 1",
384+
"12 -39916800 120543840 -150917976 105258076 -45995730 13339535 -2637558 357423 -32670 1925 -66 1",
385+
"9 44100 -103740 103429 -57034 19019 -3928 491 -34 1",
386+
"5 83521 -19652 1734 -68 1",
387+
"12 22370117 15978655 10666271 5010005 1846306 575366 142702 28538 4585 523 35 1",
388+
"4 0 -11 0 1",
389+
"7 3 1 0 0 1 0 1",
390+
"11 23 -74 89 -68 35 0 -14 8 -2 -1 1",
391+
"4 -12 0 0 1",
392+
};
393+
394+
int
395+
main(int argc, char *argv[])
396+
{
397+
398+
const slong np = sizeof(polys) / sizeof(polys[0]);
399+
flint_printf("# examples: %d\n", np);
400+
401+
ulong n = 7;
402+
403+
if (argc != 2)
404+
{
405+
flint_printf("usage: %s p (prime)\n", argv[0]);
406+
flint_printf("find roots of polynomials over p-adic field Z[p].\n");
407+
exit(1);
408+
}
409+
else
410+
{
411+
n = atoi(argv[1]);
412+
if (!n_is_prime(n))
413+
{
414+
flint_printf("%d is not a prime as required for p-adic field.\n",
415+
n);
416+
exit(1);
417+
}
418+
};
419+
420+
fmpz_t p;
421+
fmpz_init(p);
422+
fmpz_set_ui(p, n);
423+
424+
padic_ctx_t pctx;
425+
padic_ctx_init(pctx, p, 128, 128, PADIC_SERIES);
426+
427+
fmpz_poly_t poly;
428+
fmpz_poly_init(poly);
429+
430+
/* use this to read from "poly_data" string. */
431+
432+
flint_printf("reading polynomials:\n");
433+
434+
for (slong j = 0; j < sizeof(polys) / sizeof(polys[0]); j++)
435+
{
436+
flint_printf("polynomial:\n\n");
437+
fmpz_poly_set_str(poly, polys[j]);
438+
fmpz_poly_print_pretty(poly, "x");
439+
flint_printf("\n\nroots with multiplicity:\n\n");
440+
padic_roots(poly, pctx, 64);
441+
flint_printf("\n");
442+
}
443+
444+
fmpz_poly_clear(poly);
445+
fmpz_clear(p);
446+
447+
}

0 commit comments

Comments
 (0)
Please sign in to comment.