Orbiter 2022
Combinatorial Objects
nth_roots.cpp
Go to the documentation of this file.
1/*
2 * nth_roots.cpp
3 *
4 * Created on: Oct 2, 2021
5 * Author: betten
6 */
7
8
9
10#include "foundations.h"
11
12using namespace std;
13
14
15
16namespace orbiter {
17namespace layer1_foundations {
18namespace field_theory {
19
20
21
22
24{
25 n = 0;
26 F = NULL;
27 Beta = NULL;
28 Fq_Elements = NULL;
29 Min_poly = NULL;
30 Fp = NULL;
31 FpX = NULL;
32 Fq = NULL;
33 FX = NULL;
34 m = 0;
35 r = 0;
36 field_degree = 0;
37 Qm = NULL;
38 Qm1 = NULL;
39 Index = NULL;
40 Subfield_Index = NULL;
41 Cyc = NULL;
42 generator = NULL;
43 generator_Fq = NULL;
45 subfield_basis = NULL;
46}
47
49{
50 if (Qm1) {
52 }
53 if (Index) {
55 }
56 if (Subfield_Index) {
58 }
59}
60
61
62void nth_roots::init(finite_field *F, int n, int verbose_level)
63{
64 int f_v = (verbose_level >= 1);
65
66 if (f_v) {
67 cout << "nth_roots::init n=" << n << endl;
68 }
72 int i;
73
74
77
78
79 m = NT.order_mod_p(F->q, n);
80 if (f_v) {
81 cout << "nth_roots::init order of q mod n is m=" << m << endl;
82 }
87 D.create_q_to_the_n(*Qm, F->q, m);
88 D.create_qnm1(*Qm1, F->q, m);
89
90 field_degree = F->e * m;
91
92 // q = i_power_j(p, e);
93 // GF(q)=GF(p^e) has n-th roots of unity
95 if (f_v) {
96 cout << "nth_roots::init n = " << n << endl;
97 cout << "nth_roots::init m = " << m << endl;
98 cout << "nth_roots::init field_degree = " << field_degree << endl;
99 cout << "nth_roots::init Qm1 = " << *Qm1 << endl;
100 }
101
102 if (r) {
103 cout << "nth_roots::init n does not divide Qm1" << endl;
104 exit(1);
105 }
106
107 if (f_v) {
108 cout << "nth_roots::init Index = " << *Index << endl;
109 }
110
112 if (r) {
113 cout << "nth_roots::init q - 1 does not divide Qm1" << endl;
114 exit(1);
115 }
116
117 if (f_v) {
118 cout << "nth_roots::init Subfield_Index = " << *Subfield_Index << endl;
119 }
120
121
123
124 Fp->finite_field_init(F->p, FALSE /* f_without_tables */, verbose_level - 1);
125
127
128 FX->init_basic(F, verbose_level);
129
130
131 //unipoly_domain FpX(Fp);
132
134
135 FpX->init_basic(Fp, verbose_level);
136
138 string field_poly;
139
140 K.get_primitive_polynomial(field_poly, F->p, field_degree, 0);
142 field_poly,
143 verbose_level - 2);
144
145
146 if (f_v) {
147 cout << "nth_roots::init creating unipoly_domain Fq modulo M" << endl;
148 }
149
151
152 Fq->init_factorring(Fp, Min_poly, verbose_level);
153 //unipoly_domain Fq(Fp, Min_poly, verbose_level);
154 // Fq = Fp[X] modulo factor polynomial M
155
156 if (f_v) {
157 cout << "nth_roots::init extension field created" << endl;
158 }
159
161
162 if (f_v) {
163 cout << "nth_roots::init before R.compute_nth_roots_as_polynomials" << endl;
164 }
165 R.compute_nth_roots_as_polynomials(F, FpX, Fq, Beta, n, n, 0 /*verbose_level*/);
166 if (f_v) {
167 cout << "nth_roots::init after R.compute_nth_roots_as_polynomials" << endl;
168 }
169
170
171
172
173
174
175 if (f_v) {
176 cout << "nth_roots::init the n-th roots are:" << endl;
177 for (i = 0; i < n; i++) {
178 cout << "\\beta^" << i << " &=& ";
179 Fq->print_object_tight(Beta[i], cout);
180 cout << " = ";
181 Fq->print_object(Beta[i], cout);
182 cout << "\\\\" << endl;
183 }
184 }
185
186
188 Fq, Fq_Elements, n, F->q - 1,
189 0 /*verbose_level*/);
190 if (f_v) {
191 cout << "nth_roots::init the (q-1)-th roots are:" << endl;
192 for (i = 0; i < F->q - 1; i++) {
193 cout << "\\gamma^" << i << " &=& ";
195 cout << " = ";
196 Fq->print_object(Fq_Elements[i], cout);
197 cout << "\\\\" << endl;
198 }
199 }
200
201
203
204 if (f_v) {
205 cout << "nth_roots::init before Cyc->init" << endl;
206 }
207 Cyc->init(F, n, 0 /*verbose_level*/);
208 if (f_v) {
209 cout << "nth_roots::init after Cyc->init" << endl;
210 }
211
212 if (f_v) {
213 cout << "nth_roots::init q-cyclotomic sets mod n:" << endl;
214 Cyc->print();
215 }
216
217
218
220
221 for (i = 0; i < Cyc->S->nb_sets; i++) {
222
223 if (f_v) {
224 cout << "nth_roots::init creating polynomial "
225 << i << " / " << Cyc->S->nb_sets << endl;
226 }
227
229 Fq,
230 Beta, n,
231 Cyc->S->Sets[i], Cyc->S->Set_size[i],
232 generator[i],
233 0 /*verbose_level*/);
234
235 //Codes.print_polynomial(Fq, Cyc->S->Set_size[i], generator[i]);
236 //cout << endl;
237
238 }
239
240 if (f_v) {
241 cout << "nth_roots::init irreducible polynomials" << endl;
242
243 for (i = 0; i < Cyc->S->nb_sets; i++) {
244 cout << i << " : ";
245
246 Lint_vec_print(cout, Cyc->S->Sets[i], Cyc->S->Set_size[i]);
247
248 cout << " : ";
249
250 Codes.print_polynomial_tight(cout, *Fq, Cyc->S->Set_size[i], generator[i]);
251
252
253 cout << endl;
254 }
255 }
256
257 if (f_v) {
258 cout << "nth_roots::init Index" << endl;
259 Int_vec_print(cout, Cyc->Index, n);
260 cout << endl;
261 }
262
263
264 if (f_v) {
265 cout << "nth_roots::init before compute_subfield" << endl;
266 }
267
269
271
272 if (f_v) {
273 cout << "nth_roots::init after compute_subfield" << endl;
274 }
275
276
277 if (f_v) {
278 cout << "nth_roots::init subfield_basis=" << endl;
281 }
282
283 int *input_vector;
284 int *coefficients;
285 int j, h, a;
287
288 input_vector = NEW_int(field_degree);
289 coefficients = NEW_int(subfield_degree);
290
291 for (i = 0; i < Cyc->S->nb_sets; i++) {
292 cout << i << " : ";
293
294 Lint_vec_print(cout, Cyc->S->Sets[i], Cyc->S->Set_size[i]);
295
296 cout << " : ";
297
298 //Codes.print_polynomial_tight(*Fq, Cyc->S->Set_size[i], generator[i]);
299
300 int f_first = TRUE;
301 int degree = Cyc->S->Set_size[i];
302
303 for (j = 0; j <= degree; j++) {
304 if (!f_first) {
305 cout << " + ";
306 }
307 f_first = FALSE;
308
309 for (h = 0; h < field_degree; h++) {
310 input_vector[h] = FpX->s_i(generator[i][j], h);
311 }
312
315 input_vector, coefficients, 0 /*verbose_level*/);
316
317 //Orbiter->Int_vec.print(cout, input_vector, field_degree);
318 //cout << "=";
319 //Orbiter->Int_vec.print(cout, coefficients, subfield_degree);
320 //cout << "=";
321
322 a = GG.AG_element_rank(F->p, coefficients, 1, subfield_degree);
323
324 cout << a << " * Z^" << j;
325 }
326
327 cout << endl;
328 }
329
330
332
333 for (i = 0; i < Cyc->S->nb_sets; i++) {
334
335 int degree = Cyc->S->Set_size[i];
336 int *coeffs;
337
338 coeffs = NEW_int(degree + 1);
339
340 for (j = 0; j <= degree; j++) {
341
342 for (h = 0; h < field_degree; h++) {
343 input_vector[h] = FpX->s_i(generator[i][j], h);
344 }
345
348 input_vector, coefficients, 0 /*verbose_level*/);
349
350 //Orbiter->Int_vec.print(cout, input_vector, field_degree);
351 //cout << "=";
352 //Orbiter->Int_vec.print(cout, coefficients, subfield_degree);
353 //cout << "=";
354
355 a = GG.AG_element_rank(F->p, coefficients, 1, subfield_degree);
356 coeffs[j] = a;
357 }
358
360 generator_Fq[i], degree, coeffs);
361 }
362
363 for (i = 0; i < Cyc->S->nb_sets; i++) {
364 cout << i << " : ";
365 FX->print_object(generator_Fq[i], cout);
366 cout << endl;
367 }
368
369 if (f_v) {
370 cout << "nth_roots::init done" << endl;
371 }
372}
373
374void nth_roots::compute_subfield(int subfield_degree, int *&field_basis, int verbose_level)
375// field_basis[subfield_degree * field_degree]
376{
377 int f_v = (verbose_level >= 1);
378
379 if (f_v) {
380 cout << "nth_roots::compute_subfield subfield_degree=" << subfield_degree << endl;
381 }
382 int *M; // [e * (subfield_degree + 1)]
383 int *K; // [e]
384 int *base_cols; // [e]
385 int rk, kernel_m, kernel_n;
386 long int a;
387 int p, e, q1, subgroup_index;
388 int i, j;
392
393 p = F->p;
394 e = field_degree;
395 if (f_v) {
396 cout << "nth_roots::compute_subfield p=" << p << endl;
397 cout << "nth_roots::compute_subfield e=" << e << endl;
398 cout << "nth_roots::compute_subfield subfield_degree=" << subfield_degree << endl;
399 }
400 M = NEW_int(e * (subfield_degree + 1));
401 Int_vec_zero(M, e * (subfield_degree + 1));
402
403 K = NEW_int(e);
404 base_cols = NEW_int(e);
405 q1 = NT.i_power_j(p, subfield_degree);
406 subgroup_index = (Cyc->qm - 1) / (q1 - 1);
407 if (f_v) {
408 cout << "nth_roots::compute_subfield "
409 "subfield " << p << "^" << subfield_degree << " : subgroup_index = "
410 << subgroup_index << endl;
411 }
412
414
415 if (f_v) {
416 cout << "nth_roots::compute_subfield before F->compute_powers" << endl;
417 }
419 n, subgroup_index,
420 Beta, 0/*verbose_level*/);
421
422
423 if (f_v) {
424 for (i = 0; i < n; i++) {
425 cout << "\\beta^" << i << " = ";
426 Fq->print_object(Beta[i], cout);
427 cout << endl;
428 }
429 }
430
431 for (j = 0; j <= subfield_degree; j++) {
432 for (i = 0; i < e; i++) {
433 a = Fq->s_i(Beta[j], i);
434 M[i * (subfield_degree + 1) + j] = a;
435 }
436#if 0
437 j = i * subgroup_index;
438 jj = alpha_power(j);
439 Gg.AG_element_unrank(p, M + i, subfield_degree + 1, e, jj);
440
441 {
442 unipoly_object elt;
443
444 Fq.create_object_by_rank(elt, jj, __FILE__, __LINE__, 0 /*verbose_level*/);
445 if (f_v) {
446 cout << i << " : " << j << " : " << jj << " : ";
447 Fq.print_object(elt, cout);
448 cout << endl;
449 }
450 Fq.delete_object(elt);
451 }
452#endif
453
454 }
455
456 field_basis = NEW_int(subfield_degree * e);
457
458 for (j = 0; j < subfield_degree; j++) {
459 for (i = 0; i < e; i++) {
460 a = M[i * (subfield_degree + 1) + j];
461 field_basis[j * e + i] = a;
462 }
463 }
464 if (f_v) {
465 cout << "nth_roots::compute_subfield field_basis=" << endl;
466 Int_vec_print_integer_matrix_width(cout, field_basis,
468 }
469
470
471
472#if 1
473 if (f_v) {
474 cout << "nth_roots::compute_subfield M=" << endl;
477 }
478 if (f_v) {
479 cout << "nth_roots::compute_subfield before Fp->Linear_algebra->Gauss_simple" << endl;
480 }
482 M,
483 e,
484 subfield_degree + 1,
485 base_cols,
486 verbose_level);
487 if (f_v) {
488 cout << "nth_roots::compute_subfield after Gauss=" << endl;
491 cout << "rk=" << rk << endl;
492 }
493 if (rk != subfield_degree) {
494 cout << "nth_roots::compute_subfield fatal: rk != subfield_degree" << endl;
495 cout << "rk=" << rk << endl;
496 exit(1);
497 }
498
499 if (f_v) {
500 cout << "nth_roots::compute_subfield before Fp->Linear_algebra->matrix_get_kernel" << endl;
501 }
503 e, subfield_degree + 1, base_cols, rk,
504 kernel_m, kernel_n, K,
505 0 /* verbose_level */);
506
507 if (f_v) {
508 cout << "nth_roots::compute_subfield kernel_m=" << kernel_m << endl;
509 cout << "nth_roots::compute_subfield kernel_n=" << kernel_n << endl;
510 }
511 if (kernel_n != 1) {
512 cout << "nth_roots::compute_subfield kernel_n != 1" << endl;
513 exit(1);
514 }
515 if (K[subfield_degree] == 0) {
516 cout << "nth_roots::compute_subfield K[e1] == 0" << endl;
517 exit(1);
518 }
519 if (K[subfield_degree] != 1) {
520 a = Fp->inverse(K[subfield_degree]);
521 for (i = 0; i < subfield_degree + 1; i++) {
522 K[i] = Fp->mult(a, K[i]);
523 }
524 }
525
526 if (f_v) {
527 cout << "nth_roots::compute_subfield the relation is " << endl;
528 Int_vec_print(cout, K, subfield_degree + 1);
529 cout << endl;
530 }
531
532 a = Gg.AG_element_rank(p, K, 1, subfield_degree + 1);
533
534 if (f_v) {
536
537 FpX->create_object_by_rank(elt, a, __FILE__, __LINE__, verbose_level);
538 cout << "nth_roots::compute_subfield "
539 "subfield of order "
540 << NT.i_power_j(p, subfield_degree)
541 << " : " << a << " = ";
542 Fq->print_object(elt, cout);
543 cout << endl;
544 Fq->delete_object(elt);
545 }
546
547 FREE_int(M);
548 FREE_int(K);
549 FREE_int(base_cols);
550#endif
551
552
553
554 if (f_v) {
555 cout << "nth_roots::compute_subfield done" << endl;
556 }
557}
558
559
560void nth_roots::report(std::ostream &ost, int verbose_level)
561{
562 int f_v = (verbose_level >= 1);
563 int i;
564 string label;
567
568 if (f_v) {
569 cout << "nth_roots::report" << endl;
570 }
571
572 label.assign("\\alpha");
573
574 Fq->init_variable_name(label);
575
576
577
578 ost << "\\noindent Let $\\alpha$ be a primitive element of GF$(" << *Qm << ")$. " << endl;
579 ost << "Let $\\beta$ be a primitive $" << n << "$-th root in GF$(" << *Qm << ")$, " << endl;
580 ost << "so $\\beta=\\alpha^{" << *Index << "}.$ \\\\" << endl;
581 //ost << "\\begin{align*}" << endl;
582 for (i = 0; i < n; i++) {
583 ost << "$\\beta^{" << i << "} = ";
584 Fq->print_object_tight(Beta[i], ost);
585 ost << " = ";
586 Fq->print_object(Beta[i], ost);
587 ost << "$\\\\" << endl;
588 }
589 //ost << "\\end{align*}" << endl;
590 //ost << "\\clearpage" << endl;
591 ost << "\\bigskip" << endl << endl;
592
593
594 //cout << "nth_roots::init the (q-1)-th roots are:" << endl;
595 //ost << "\\begin{align*}" << endl;
596 ost << "\\noindent Let $\\gamma$ be a primitive $" << F->q - 1 << "$-th root in GF$(" << *Qm << ")$, " << endl;
597 ost << "so $\\gamma=\\alpha^{" << *Subfield_Index << "}.$ \\\\" << endl;
598 for (i = 0; i < F->q - 1; i++) {
599 ost << "$\\gamma^{" << i << "} = ";
601 ost << " = ";
602 Fq->print_object(Fq_Elements[i], ost);
603 ost << "$\\\\" << endl;
604 }
605 //ost << "\\end{align*}" << endl;
606 //ost << "\\clearpage" << endl;
607 ost << "\\bigskip" << endl << endl;
608
609 ost << "\\noindent The $q$-cyclotomic set for $q=" << F->q << "$ are:" << endl << endl;
610
611
612 Cyc->print_latex(ost);
613
614 ost << "\\bigskip" << endl << endl;
615
616 ost << "Subfield basis, a basis for GF$(" << F->q << ")$ inside GF$(" << *Qm << ")$:" << endl;
617
618 ost << "$$" << endl;
619 ost << "\\left[" << endl;
621 ost << "\\right]" << endl;
622 ost << "$$" << endl;
623
624 ost << "\\bigskip" << endl << endl;
625
626 ost << "The irreducible polynomials associated with the $" << n << "$-th roots over GF$(" << F->q << ")$ are:" << endl << endl;
627
628 ost << "\\bigskip" << endl << endl;
629
630 ost << "{\\renewcommand{\\arraystretch}{1.5}" << endl;
631 ost << "$$" << endl;
632 ost << "\\begin{array}{|r|r|l|l|l|}" << endl;
633 ost << "\\hline" << endl;
634 ost << "i & r_i & {\\rm Cyc}(r_i) & m_{\\beta^{r_i}}(X) & m_{\\beta^{r_i}}(X) \\\\" << endl;
635 ost << "\\hline" << endl;
636
637 for (i = 0; i < Cyc->S->nb_sets; i++) {
638 ost << i << " & ";
639
640 ost << Cyc->S->Sets[i][0];
641
642 ost << " & ";
643
644 Lint_vec_print(ost, Cyc->S->Sets[i], Cyc->S->Set_size[i]);
645
646 ost << " & ";
647
648 Codes.print_polynomial_tight(ost, *Fq, Cyc->S->Set_size[i], generator[i]);
649
650 ost << " & ";
651
652 FX->print_object(generator_Fq[i], ost);
653
654
655 ost << "\\\\" << endl;
656 ost << "\\hline" << endl;
657 }
658 ost << "\\end{array}" << endl;
659 ost << "$$}" << endl;
660 ost << "\\clearpage" << endl;
661
662
663}
664
665
666
667}}}
668
void print_polynomial_tight(std::ostream &ost, ring_theory::unipoly_domain &Fq, int degree, ring_theory::unipoly_object *coeffs)
void finite_field_init(int q, int f_without_tables, int verbose_level)
void report(std::ostream &ost, int verbose_level)
Definition: nth_roots.cpp:560
ring_theory::longinteger_object * Subfield_Index
void init(finite_field *F, int n, int verbose_level)
Definition: nth_roots.cpp:62
void compute_subfield(int subfield_degree, int *&field_basis, int verbose_level)
Definition: nth_roots.cpp:374
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
long int AG_element_rank(int q, int *v, int stride, int len)
provides access to pre-computed combinatorial data in encoded form
void get_primitive_polynomial(std::string &poly, int p, int e, int verbose_level)
int Gauss_simple(int *A, int m, int n, int *base_cols, int verbose_level)
void matrix_get_kernel(int *M, int m, int n, int *base_cols, int nb_base_cols, int &kernel_m, int &kernel_n, int *kernel, int verbose_level)
void get_coefficients_in_linear_combination(int k, int n, int *basis_of_subspace, int *input_vector, int *coefficients, int verbose_level)
void init(field_theory::finite_field *F, int n, int verbose_level)
void int_matrix_print_tex(std::ostream &ost, int *p, int m, int n)
domain to compute with objects of type longinteger
Definition: ring_theory.h:240
void integral_division_by_int(longinteger_object &a, int b, longinteger_object &q, int &r)
void create_q_to_the_n(longinteger_object &a, int q, int n)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void create_irreducible_polynomial(field_theory::finite_field *F, unipoly_domain *Fq, unipoly_object *&Beta, int n, long int *cyclotomic_set, int cylotomic_set_size, unipoly_object *&generator, int verbose_level)
void compute_nth_roots_as_polynomials(field_theory::finite_field *F, unipoly_domain *FpX, unipoly_domain *Fq, unipoly_object *&Beta, int n1, int n2, int verbose_level)
void compute_powers(field_theory::finite_field *F, unipoly_domain *Fq, int n, int start_idx, unipoly_object *&Beta, int verbose_level)
domain of polynomials in one variable over a finite field
Definition: ring_theory.h:691
void create_object_of_degree_with_coefficients(unipoly_object &p, int d, int *coeff)
void print_object_tight(unipoly_object p, std::ostream &ost)
void create_object_by_rank(unipoly_object &p, long int rk, const char *file, int line, int verbose_level)
void create_object_by_rank_string(unipoly_object &p, std::string &rk, int verbose_level)
void init_basic(field_theory::finite_field *F, int verbose_level)
void print_object(unipoly_object p, std::ostream &ost)
void init_factorring(field_theory::finite_field *F, unipoly_object m, int verbose_level)
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_pvoid(n)
Definition: foundations.h:637
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define Lint_vec_print(A, B, C)
Definition: foundations.h:686
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define Int_vec_print_integer_matrix_width(A, B, C, D, E, F)
Definition: foundations.h:691
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects