Orbiter 2022
Combinatorial Objects
finite_field.cpp
Go to the documentation of this file.
1// finite_field.cpp
2//
3// Anton Betten
4//
5// started: October 23, 2002
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//int nb_calls_to_finite_field_init = 0;
22
24{
27 T = NULL;
28 Iwo = NULL;
29 //std::string symbol_for_print;
30
31
32 //polynomial = NULL;
33
34 //std::string label;
35 //std::string label_tex;
36 //std::override_poly;
37 //std::string my_poly;
38 //std::symbol_for_print;
40 q = 0;
41 p = 0;
42 e = 0;
43 alpha = 0;
44 log10_of_q = 1;
45
50
51 nb_times_mult = 0;
52 nb_times_add = 0;
53
54 Linear_algebra = NULL;
56
57}
58
60{
61 //print_call_stats(cout);
62 //cout << "destroying tables" << endl;
63 //cout << "destroying add_table" << endl;
64
65 if (T) {
66 FREE_OBJECT(T);
67 }
68 if (Iwo) {
69 FREE_OBJECT(Iwo);
70 }
71
72#if 0
73 if (polynomial) {
74 FREE_char(polynomial);
75 }
76#endif
77 if (Linear_algebra) {
79 }
82 }
83
84}
85
86void finite_field::print_call_stats(std::ostream &ost)
87{
88 cout << "finite_field::print_call_stats" << endl;
89 cout << "nb_calls_to_mult_matrix_matrix="
91 cout << "nb_calls_to_PG_element_rank_modified="
93 cout << "nb_calls_to_PG_element_unrank_modified="
95}
96
97void finite_field::init(finite_field_description *Descr, int verbose_level)
98{
99 int f_v = (verbose_level >= 1);
100
101 if (f_v) {
102 cout << "finite_field::init" << endl;
103 }
104 if (!Descr->f_q) {
105 cout << "finite_field::init !Descr->f_q" << endl;
106 exit(1);
107 }
108
109 if (Descr->f_override_polynomial) {
110
111
113 Linear_algebra->init(this, verbose_level);
114
116 Orthogonal_indexing->init(this, verbose_level);
117
118 if (f_v) {
119 cout << "finite_field::init override_polynomial=" << Descr->override_polynomial << endl;
120 cout << "finite_field::init before init_override_polynomial" << endl;
121 }
123 Descr->override_polynomial, Descr->f_without_tables, verbose_level - 1);
124 if (f_v) {
125 cout << "finite_field::init after init_override_polynomial" << endl;
126 }
127
128
129 }
130 else {
131 if (f_v) {
132 cout << "finite_field::init before finite_field_init" << endl;
133 }
134 finite_field_init(Descr->q, Descr->f_without_tables, verbose_level - 1);
135 if (f_v) {
136 cout << "finite_field::init after finite_field_init" << endl;
137 }
138
139 }
140 if (f_v) {
141 cout << "finite_field::init done" << endl;
142 }
143}
144
145void finite_field::finite_field_init(int q, int f_without_tables, int verbose_level)
146{
147 int f_v = (verbose_level >= 1);
148 string poly;
150
151 if (f_v) {
152 cout << "finite_field::finite_field_init q=" << q << " verbose_level = " << verbose_level << endl;
153 }
154
155
157 Linear_algebra->init(this, verbose_level);
158
160 Orthogonal_indexing->init(this, verbose_level);
161
162
163
164 //nb_calls_to_finite_field_init++;
166 NT.factor_prime_power(q, p, e);
168
169 if (e > 1) {
172
173 K.get_primitive_polynomial(poly, p, e, verbose_level);
174 if (f_v) {
175 cout << "finite_field::finite_field_init q=" << q << " before init_override_polynomial poly = " << poly << endl;
176 }
177 init_override_polynomial(q, poly, f_without_tables, verbose_level);
178 if (f_v) {
179 cout << "finite_field::finite_field_init q=" << q << " after init_override_polynomial" << endl;
180 }
181 }
182 else {
184 poly.assign("");
185 if (f_v) {
186 cout << "finite_field::finite_field_init q=" << q << " before init_override_polynomial poly = " << poly << endl;
187 }
188 init_override_polynomial(q, poly, f_without_tables, verbose_level);
189 if (f_v) {
190 cout << "finite_field::finite_field_init q=" << q << " after init_override_polynomial" << endl;
191 }
192 }
193
194 char str[1000];
195
196 sprintf(str, "GF_%d", q);
197 label.assign(str);
198 sprintf(str, "{\\mathbb F}_{%d}", q);
199 label_tex.assign(str);
200
201
202
203 if (f_v) {
204 cout << "finite_field::finite_field_init done" << endl;
205 }
206}
207
208void finite_field::init_implementation(int f_without_tables, int verbose_level)
209{
210 int f_v = (verbose_level >= 1);
211 string poly;
213
214 if (f_v) {
215 cout << "finite_field::init_implementation" << endl;
216 }
217
218
219 if (f_without_tables) {
220 if (f_v) {
221 cout << "finite_field::init_implementation implementation without field tables" << endl;
222 }
224
226
227 if (f_v) {
228 cout << "finite_field::init_implementation before Iwo->init" << endl;
229 }
230 Iwo->init(this, verbose_level);
231 if (f_v) {
232 cout << "finite_field::init_implementation after Iwo->init" << endl;
233 }
234 }
235 else {
236 if (f_v) {
237 cout << "finite_field::init_implementation implementation with field tables" << endl;
238 }
240
241 if (f_v) {
242 cout << "finite_field::init_implementation before T->init" << endl;
243 }
244 T->init(this, verbose_level);
245 if (f_v) {
246 cout << "finite_field::init_implementation after T->init" << endl;
247 }
249
250 }
251
252 if (f_v) {
253 cout << "finite_field::init_implementation done" << endl;
254 }
255}
256
257
259{
260 if (q == 4) {
261 init_symbol_for_print("\\omega");
262 }
263 else if (q == 8) {
264 init_symbol_for_print("\\gamma");
265 }
266 else if (q == 16) {
267 init_symbol_for_print("\\delta");
268 }
269 else if (q == 32) {
270 init_symbol_for_print("\\eta");
271 }
272 else if (q == 64) {
273 init_symbol_for_print("\\epsilon");
274 }
275 else if (q == 128) {
276 init_symbol_for_print("\\zeta");
277 }
278 else {
279 init_symbol_for_print("\\alpha");
280 }
281}
282
283
285{
286 symbol_for_print.assign(symbol);
287}
288
290 std::string &poly, int f_without_tables, int verbose_level)
291{
292 int f_v = (verbose_level >= 1);
293 int f_vv = (verbose_level >= 2);
295
296 if (f_v) {
297 cout << "finite_field::init_override_polynomial "
298 "q=" << q << " verbose_level = " << verbose_level << endl;
299 }
300 override_poly.assign(poly);
301
303 NT.factor_prime_power(q, p, e);
304 if (f_v) {
305 cout << "finite_field::init_override_polynomial p=" << p << endl;
306 cout << "finite_field::init_override_polynomial e=" << e << endl;
307 }
308 //init_symbol_for_print("\\alpha");
309 log10_of_q = NT.int_log10(q);
311
312 if (e > 1) {
315
316 if (poly.length() == 0) {
317 K.get_primitive_polynomial(my_poly, p, e, verbose_level);
318 }
319 else {
320 my_poly.assign(poly);
321 if (f_vv) {
322 cout << "finite_field::init_override_polynomial, "
323 "using polynomial " << my_poly << endl;
324 }
325 }
326 if (f_v) {
327 cout << "finite_field::init_override_polynomial "
328 "using poly " << my_poly << endl;
329 }
330 }
331 else {
333 }
334 if (f_v) {
335 cout << "finite_field::init_override_polynomial "
336 "GF(" << q << ") = GF(" << p << "^" << e << ")";
337 if (e > 1) {
338 cout << ", polynomial = ";
340 cout << " = " << my_poly << endl;
341 }
342 else {
343 cout << endl;
344 }
345 }
346
347#if 0
348 l = my_poly.length();
349 polynomial = NEW_char(l + 1);
350 strcpy(polynomial, my_poly.c_str());
351#endif
352
353 char str[1000];
354
355 sprintf(str, "GF_%d", q);
356 label.assign(str);
357 label.append("_poly");
358 label.append(override_poly);
359
360 sprintf(str, "{\\mathbb F}_{%d,", q);
361 label_tex.assign(str);
362 label_tex.append(override_poly);
363 label_tex.append("}");
364
365
366 if (f_v) {
367 cout << "finite_field::init_override_polynomial before init_implementation" << endl;
368 }
369 init_implementation(f_without_tables, verbose_level - 1);
370 if (f_v) {
371 cout << "finite_field::init_override_polynomial after init_implementation" << endl;
372 }
373
374 if (f_vv) {
375 cout << "finite_field::init_override_polynomial "
376 "finished" << endl;
377 }
378}
379
380
381
383{
384#if 0
385 if (!f_has_table) {
386 cout << "finite_field::has_quadratic_subfield !f_has_table" << endl;
387 exit(1);
388 }
389 return T->has_quadratic_subfield();
390#else
391 if ((e % 2) == 0) {
392 return TRUE;
393 }
394 else {
395 return FALSE;
396 }
397#endif
398}
399
401{
402 if ((e % 2) != 0) {
403 cout << "finite_field::belongs_to_quadratic_subfield does not have a quadratic subfield" << endl;
404 exit(1);
405 }
406 if (!f_has_table) {
407 cout << "finite_field::belongs_to_quadratic_subfield !f_has_table" << endl;
408 exit(1);
409 }
411}
412
414 int f_latex, std::ostream &ost,
415 int verbose_level)
416{
417 int f_v = (verbose_level >= 1);
418 int f_vv = (verbose_level >= 2);
419 int p1, e1, q1, i, j, jj, subgroup_index;
421
422 if (f_v) {
423 cout << "finite_field::compute_subfield_polynomial "
424 "for subfield of order " << order_subfield << endl;
425 }
426 NT.factor_prime_power(order_subfield, p1, e1);
427 if (p1 != p) {
428 cout << "finite_field::compute_subfield_polynomial "
429 "the subfield must have the same characteristic" << endl;
430 exit(1);
431 }
432 if ((e % e1)) {
433 cout << "finite_field::compute_subfield_polynomial "
434 "is not a subfield" << endl;
435 exit(1);
436 }
437
439 GFp.finite_field_init(p, FALSE /* f_without_tables */, 0);
440
443
444 FX.create_object_by_rank_string(m, my_poly, 0/*verbose_level*/);
445 ring_theory::unipoly_domain Fq(&GFp, m, verbose_level - 1);
446
447
448 int *M;
449 int *K;
450 int *base_cols;
451 int rk, kernel_m, kernel_n;
452 long int a;
454
455 M = NEW_int(e * (e1 + 1));
456 Int_vec_zero(M, e * (e1 + 1));
457
458 K = NEW_int(e);
459 base_cols = NEW_int(e);
460 q1 = NT.i_power_j(p, e1);
461 subgroup_index = (q - 1) / (q1 - 1);
462 if (f_v) {
463 cout << "finite_field::compute_subfield_polynomial "
464 "subfield " << p << "^" << e1 << " : subgroup_index = "
465 << subgroup_index << endl;
466 }
467 for (i = 0; i <= e1; i++) {
468 j = i * subgroup_index;
469 jj = alpha_power(j);
470 Gg.AG_element_unrank(p, M + i, e1 + 1, e, jj);
471 {
473
474 Fq.create_object_by_rank(elt, jj, __FILE__, __LINE__, 0 /*verbose_level*/);
475 if (f_v) {
476 cout << i << " : " << j << " : " << jj << " : ";
477 Fq.print_object(elt, cout);
478 cout << endl;
479 }
480 Fq.delete_object(elt);
481 }
482 }
483
484 if (f_latex) {
485 ost << "$$" << endl;
486 ost << "\\begin{array}{|c|c|c|c|}" << endl;
487 ost << "\\hline" << endl;
488 ost << "i & i\\cdot d & \\alpha^{id} & \\mbox{vector} \\\\" << endl;
489 ost << "\\hline" << endl;
490
491 int h;
492
493 for (i = 0; i <= e1; i++) {
494 ost << i;
495 ost << " & ";
496 j = i * subgroup_index;
497 ost << j;
498 ost << " & ";
499 jj = alpha_power(j);
500 ost << jj;
501 ost << " & ";
502 ost << "(";
503 for (h = e - 1; h >= 0; h--) {
504 ost << M[h * (e1 + 1) + i];
505 if (h) {
506 ost << ",";
507 }
508 }
509 ost << ")";
510 ost << "\\\\" << endl;
511 //Gg.AG_element_unrank(p, M + i, e1 + 1, e, jj);
512 }
513
514 ost << "\\hline" << endl;
515 ost << "\\end{array}" << endl;
516 ost << "$$" << endl;
517 }
518
519
520 if (f_v) {
521 cout << "finite_field::compute_subfield_polynomial M=" << endl;
523 e, e1 + 1, e1 + 1, GFp.log10_of_q);
524 }
525 rk = GFp.Linear_algebra->Gauss_simple(M, e, e1 + 1,
526 base_cols, 0/*verbose_level*/);
527 if (f_vv) {
528 cout << "finite_field::compute_subfield_polynomial after Gauss=" << endl;
530 e, e1 + 1, e1 + 1, GFp.log10_of_q);
531 cout << "rk=" << rk << endl;
532 }
533 if (rk != e1) {
534 cout << "finite_field::compute_subfield_polynomial fatal: rk != e1" << endl;
535 cout << "rk=" << rk << endl;
536 exit(1);
537 }
538
539 GFp.Linear_algebra->matrix_get_kernel(M, e, e1 + 1, base_cols, rk,
540 kernel_m, kernel_n, K, 0 /* verbose_level */);
541
542 if (f_vv) {
543 cout << "kernel_m=" << kernel_m << endl;
544 cout << "kernel_n=" << kernel_n << endl;
545 }
546 if (kernel_n != 1) {
547 cout << "kernel_n != 1" << endl;
548 exit(1);
549 }
550 if (K[e1] == 0) {
551 cout << "K[e1] == 0" << endl;
552 exit(1);
553 }
554 if (K[e1] != 1) {
555 a = GFp.inverse(K[e1]);
556 for (i = 0; i < e1 + 1; i++) {
557 K[i] = GFp.mult(a, K[i]);
558 }
559 }
560 if (f_latex) {
561 ost << "Left nullspace generated by:\\\\" << endl;
562 ost << "$$" << endl;
563 Int_vec_print(ost, K, e1 + 1);
564 ost << "$$" << endl;
565 }
566
567 if (f_vv) {
568 cout << "finite_field::compute_subfield_polynomial the relation is " << endl;
569 Int_vec_print(cout, K, e1 + 1);
570 cout << endl;
571 }
572
573 a = Gg.AG_element_rank(p, K, 1, e1 + 1);
574
575 if (f_v) {
577
578 FX.create_object_by_rank(elt, a, __FILE__, __LINE__, verbose_level);
579 cout << "finite_field::compute_subfield_polynomial "
580 "subfield of order " << NT.i_power_j(p, e1)
581 << " : " << a << " = ";
582 Fq.print_object(elt, cout);
583 cout << endl;
584 Fq.delete_object(elt);
585 }
586
587 FREE_int(M);
588 FREE_int(K);
589 FREE_int(base_cols);
590 return a;
591}
592
593void finite_field::compute_subfields(int verbose_level)
594{
595 int f_v = (verbose_level >= 1);
596 //int f_vv = (verbose_level >= 2);
597 int e1;
599
600 if (f_v) {
601 cout << "finite_field::compute_subfields" << endl;
602 }
603 cout << "subfields of F_{" << q << "}:" << endl;
604
606 GFp.finite_field_init(p, FALSE /* f_without_tables */, 0);
607
610
611 FX.create_object_by_rank_string(m, my_poly, 0 /*verbose_level*/);
612 ring_theory::unipoly_domain Fq(&GFp, m, verbose_level - 1);
613
614 //Fq.print_object(m, cout);
615
616 for (e1 = 2; e1 < e; e1++) {
617 if ((e % e1) == 0) {
618 int poly;
619
621 NT.i_power_j(p, e1),
622 FALSE, cout,
623 verbose_level);
624 {
626
628 poly, __FILE__, __LINE__, verbose_level);
629 cout << "subfield of order " << NT.i_power_j(p, e1)
630 << " : " << poly << " = ";
631 Fq.print_object(elt, cout);
632 cout << endl;
633 Fq.delete_object(elt);
634 }
635 }
636 }
637 FX.delete_object(m);
638}
639
640
642{
643 int f_v = (verbose_level >= 1);
644 int i, ord;
645
646 if (f_v) {
647 cout << "finite_field::find_primitive_element" << endl;
648 }
649 for (i = 2; i < q; i++) {
650 ord = compute_order_of_element(i, 0 /*verbose_level - 3*/);
651 if (f_v) {
652 cout << "finite_field::find_primitive_element the order of " << i << " is " << ord << endl;
653 }
654 if (ord == q - 1) {
655 break;
656 }
657 }
658 if (i == q) {
659 cout << "finite_field::find_primitive_element could not find a primitive element" << endl;
660 exit(1);
661 }
662 if (f_v) {
663 cout << "finite_field::find_primitive_element done" << endl;
664 }
665 return i;
666}
667
668
669int finite_field::compute_order_of_element(int elt, int verbose_level)
670{
671 int f_v = (verbose_level >= 1);
672 int f_vv = (verbose_level >= 2);
673 int i, k;
674
675 if (f_v) {
676 cout << "finite_field::compute_order_of_element "
677 "q=" << q << " p=" << p << " e=" << e << " elt=" << elt << endl;
678 }
679
680
682 GFp.finite_field_init(p, FALSE /* f_without_tables */, 0);
683
686
687 FX.create_object_by_rank_string(m, my_poly, verbose_level - 2);
688 if (f_vv) {
689 cout << "m=";
690 FX.print_object(m, cout);
691 cout << endl;
692 }
693 {
694 ring_theory::unipoly_domain Fq(&GFp, m, verbose_level - 1);
695 ring_theory::unipoly_object a, c, Alpha;
696
697 Fq.create_object_by_rank(Alpha, elt, __FILE__, __LINE__, verbose_level);
698 Fq.create_object_by_rank(a, elt, __FILE__, __LINE__, verbose_level);
699 Fq.create_object_by_rank(c, 1, __FILE__, __LINE__, verbose_level);
700
701 for (i = 1; i < q; i++) {
702
703 if (f_vv) {
704 cout << "i=" << i << endl;
705 }
706 k = Fq.rank(a);
707 if (f_vv) {
708 cout << "a=";
709 Fq.print_object(a, cout);
710 cout << " has rank " << k << endl;
711 }
712 if (k < 0 || k >= q) {
713 cout << "finite_field::compute_order_of_element error: k = " << k << endl;
714 }
715 if (k == 1) {
716 break;
717 }
718
719 Fq.mult(a, Alpha, c, verbose_level - 1);
720 Fq.assign(c, a, verbose_level - 2);
721 }
722 Fq.delete_object(Alpha);
723 Fq.delete_object(a);
724 Fq.delete_object(c);
725 }
726 FX.delete_object(m);
727
728 if (f_v) {
729 cout << "finite_field::compute_order_of_element done "
730 "q=" << q << " p=" << p << " e=" << e << " order of " << elt << " is " << i << endl;
731 }
732 return i;
733}
734
735
736
737
738
740{
741 if (!f_has_table) {
742 cout << "finite_field::private_add_table !f_has_table" << endl;
743 exit(1);
744 }
745 return T->private_add_table();
746}
747
749{
750 if (!f_has_table) {
751 cout << "finite_field::private_mult_table !f_has_table" << endl;
752 exit(1);
753 }
754 return T->private_mult_table();
755}
756
758{
759 return 0;
760}
761
763{
764 return 1;
765}
766
768{
769 return negate(1);
770}
771
773{
774 if (i == 0) {
775 return TRUE;
776 }
777 else {
778 return FALSE;
779 }
780}
781
783{
784 if (i == 1) {
785 return TRUE;
786 }
787 else {
788 return FALSE;
789 }
790}
791
792int finite_field::mult(int i, int j)
793{
794 return mult_verbose(i, j, 0);
795}
796
797int finite_field::mult_verbose(int i, int j, int verbose_level)
798{
799 int f_v = (verbose_level >= 1);
800 int c;
801
802 if (f_v) {
803 cout << "finite_field_by_tables::mult_verbose" << endl;
804 }
805 nb_times_mult++;
806 //cout << "finite_field::mult_verbose i=" << i << " j=" << j << endl;
807 if (i < 0 || i >= q) {
808 cout << "finite_field_by_tables::mult_verbose i = " << i << endl;
809 exit(1);
810 }
811 if (j < 0 || j >= q) {
812 cout << "finite_field_by_tables::mult_verbose j = " << j << endl;
813 exit(1);
814 }
815 if (f_has_table) {
816 if (f_v) {
817 cout << "finite_field_by_tables::mult_verbose with table" << endl;
818 }
819 c = T->mult_verbose(i, j, verbose_level);
820 }
821 else {
822 if (Iwo == NULL) {
823 cout << "finite_field_by_tables::mult_verbose !f_has_table && Iwo == NULL" << endl;
824 exit(1);
825 }
826 c = Iwo->mult(i, j, verbose_level);
827 }
828 return c;
829}
830
831int finite_field::a_over_b(int a, int b)
832{
833 int bv, c;
834
835 if (b == 0) {
836 cout << "finite_field::a_over_b b == 0" << endl;
837 exit(1);
838 }
839 bv = inverse(b);
840 c = mult(a, bv);
841 return c;
842}
843
844int finite_field::mult3(int a1, int a2, int a3)
845{
846 int x;
847
848 x = mult(a1, a2);
849 x = mult(x, a3);
850 return x;
851}
852
853int finite_field::product3(int a1, int a2, int a3)
854{
855 int x;
856
857 x = mult(a1, a2);
858 x = mult(x, a3);
859 return x;
860}
861
862int finite_field::mult4(int a1, int a2, int a3, int a4)
863{
864 int x;
865
866 x = mult(a1, a2);
867 x = mult(x, a3);
868 x = mult(x, a4);
869 return x;
870}
871
872int finite_field::mult5(int a1, int a2, int a3, int a4, int a5)
873{
874 int x;
875
876 x = mult(a1, a2);
877 x = mult(x, a3);
878 x = mult(x, a4);
879 x = mult(x, a5);
880 return x;
881}
882
883int finite_field::mult6(int a1, int a2, int a3, int a4, int a5, int a6)
884{
885 int x;
886
887 x = mult(a1, a2);
888 x = mult(x, a3);
889 x = mult(x, a4);
890 x = mult(x, a5);
891 x = mult(x, a6);
892 return x;
893}
894
895int finite_field::product4(int a1, int a2, int a3, int a4)
896{
897 int x;
898
899 x = mult(a1, a2);
900 x = mult(x, a3);
901 x = mult(x, a4);
902 return x;
903}
904
905int finite_field::product5(int a1, int a2, int a3, int a4, int a5)
906{
907 int x;
908
909 x = mult(a1, a2);
910 x = mult(x, a3);
911 x = mult(x, a4);
912 x = mult(x, a5);
913 return x;
914}
915
916int finite_field::product_n(int *a, int n)
917{
918 int x, i;
919
920 if (n == 0) {
921 return 1;
922 }
923 x = a[0];
924 for (i = 1; i < n; i++) {
925 x = mult(x, a[i]);
926 }
927 return x;
928}
929
931{
932 return mult(a, a);
933}
934
936{
937 int two;
938
939 two = 2 % p;
940 return mult(two, a);
941}
942
944{
945 int four;
946
947 four = 4 % p;
948 return mult(four, a);
949}
950
952{
953 int a;
954
955 a = k % p;
956 return a;
957}
958
959int finite_field::add(int i, int j)
960{
962 int verbose_level = 0;
963 int f_v = (verbose_level >= 1);
964 int c;
965
966 nb_times_add++;
967 if (!f_has_table) {
968 cout << "finite_field::add !f_has_table" << endl;
969 exit(1);
970 }
971 if (f_has_table) {
972 if (f_v) {
973 cout << "finite_field_by_tables::add with table" << endl;
974 }
975 c = T->add(i, j);
976 }
977 else {
978 if (Iwo == NULL) {
979 cout << "finite_field_by_tables::add !f_has_table && Iwo == NULL" << endl;
980 exit(1);
981 }
982 c = Iwo->add(i, j, verbose_level);
983 }
984
985 return c;
986}
987
988int finite_field::add3(int i1, int i2, int i3)
989{
990 int x;
991
992 x = add(i1, i2);
993 x = add(x, i3);
994 return x;
995}
996
997int finite_field::add4(int i1, int i2, int i3, int i4)
998{
999 int x;
1000
1001 x = add(i1, i2);
1002 x = add(x, i3);
1003 x = add(x, i4);
1004 return x;
1005}
1006
1007int finite_field::add5(int i1, int i2, int i3, int i4, int i5)
1008{
1009 int x;
1010
1011 x = add(i1, i2);
1012 x = add(x, i3);
1013 x = add(x, i4);
1014 x = add(x, i5);
1015 return x;
1016}
1017
1018int finite_field::add6(int i1, int i2, int i3, int i4, int i5, int i6)
1019{
1020 int x;
1021
1022 x = add(i1, i2);
1023 x = add(x, i3);
1024 x = add(x, i4);
1025 x = add(x, i5);
1026 x = add(x, i6);
1027 return x;
1028}
1029
1030int finite_field::add7(int i1, int i2, int i3, int i4, int i5, int i6, int i7)
1031{
1032 int x;
1033
1034 x = add(i1, i2);
1035 x = add(x, i3);
1036 x = add(x, i4);
1037 x = add(x, i5);
1038 x = add(x, i6);
1039 x = add(x, i7);
1040 return x;
1041}
1042
1043int finite_field::add8(int i1, int i2, int i3, int i4, int i5,
1044 int i6, int i7, int i8)
1045{
1046 int x;
1047
1048 x = add(i1, i2);
1049 x = add(x, i3);
1050 x = add(x, i4);
1051 x = add(x, i5);
1052 x = add(x, i6);
1053 x = add(x, i7);
1054 x = add(x, i8);
1055 return x;
1056}
1057
1059{
1060 int verbose_level = 0;
1061 int f_v = (verbose_level >= 1);
1062 int c;
1063
1064 if (i < 0 || i >= q) {
1065 cout << "finite_field::negate i = " << i << endl;
1066 exit(1);
1067 }
1068 if (f_has_table) {
1069 if (f_v) {
1070 cout << "finite_field_by_tables::negate with table" << endl;
1071 }
1072 c = T->negate(i);
1073 }
1074 else {
1075 if (Iwo == NULL) {
1076 cout << "finite_field_by_tables::negate !f_has_table && Iwo == NULL" << endl;
1077 exit(1);
1078 }
1079 c = Iwo->negate(i, verbose_level);
1080 }
1081
1082 return c;
1083}
1084
1086{
1087 int c;
1088 int verbose_level = 0;
1089 int f_v = (verbose_level >= 1);
1090
1091 if (f_has_table) {
1092 if (f_v) {
1093 cout << "finite_field_by_tables::inverse with table" << endl;
1094 }
1095 c = T->inverse(i);
1096 }
1097 else {
1098 if (Iwo == NULL) {
1099 cout << "finite_field_by_tables::inverse !f_has_table && Iwo == NULL" << endl;
1100 exit(1);
1101 }
1102 c = Iwo->inverse(i, verbose_level);
1103 }
1104 return c;
1105}
1106
1107int finite_field::power(int a, int n)
1108// computes a^n
1109{
1110 return power_verbose(a, n, 0);
1111}
1112
1113int finite_field::power_verbose(int a, int n, int verbose_level)
1114// computes a^n
1115{
1116 int f_v = (verbose_level >= 1);
1117 int b, c;
1118
1119 if (f_v) {
1120 cout << "finite_field::power_verbose a=" << a << " n=" << n << endl;
1121 }
1122 b = a;
1123 c = 1;
1124 while (n) {
1125 if (f_v) {
1126 cout << "finite_field::power_verbose n=" << n
1127 << " a=" << a << " b=" << b << " c=" << c << endl;
1128 }
1129 if (n % 2) {
1130 //cout << "finite_field::power: mult(" << b << "," << c << ")=";
1131 c = mult(b, c);
1132 //cout << c << endl;
1133 }
1134 b = mult_verbose(b, b, verbose_level);
1135 n >>= 1;
1136 //cout << "finite_field::power: " << b << "^"
1137 //<< n << " * " << c << endl;
1138 }
1139 if (f_v) {
1140 cout << "finite_field::power_verbose a=" << a
1141 << " n=" << n << " c=" << c << " done" << endl;
1142 }
1143 return c;
1144}
1145
1146void finite_field::frobenius_power_vec(int *v, int len, int frob_power)
1147{
1148 int h;
1149
1150 for (h = 0; h < len; h++) {
1151 v[h] = frobenius_power(v[h], frob_power);
1152 }
1153}
1154
1155void finite_field::frobenius_power_vec_to_vec(int *v_in, int *v_out, int len, int frob_power)
1156{
1157 int h;
1158
1159 for (h = 0; h < len; h++) {
1160 v_out[h] = frobenius_power(v_in[h], frob_power);
1161 }
1162}
1163
1164int finite_field::frobenius_power(int a, int frob_power)
1165// computes a^{p^i}
1166{
1167 if (!f_has_table) {
1168 cout << "finite_field::frobenius_power !f_has_table" << endl;
1169 exit(1);
1170 }
1171 a = T->frobenius_power(a, frob_power);
1172 return a;
1173}
1174
1176{
1177 int j, ii = i, t = 0;
1178
1179 if (!f_has_table) {
1180 cout << "finite_field::absolute_trace !f_has_table" << endl;
1181 exit(1);
1182 }
1183 for (j = 0; j < e; j++) {
1184 //ii = power(ii, p);
1185 //cout << "absolute_trace() ii = " << ii << " -> ";
1186 ii = T->frobenius_image(ii);
1187 //cout << ii << endl;
1188 t = add(t, ii);
1189 }
1190 if (ii != i) {
1191 cout << "finite_field::absolute_trace ii != i" << endl;
1192 cout << "i=" << i << endl;
1193 cout << "ii=" << ii << endl;
1194 ii = i;
1195 for (j = 0; j < e; j++) {
1196 ii = T->frobenius_image(ii);
1197 cout << "j=" << j << " ii=" << ii << endl;
1198 }
1199 exit(1);
1200 }
1201 return t;
1202}
1203
1205{
1206 int j, ii = i, t = 1;
1207
1208 if (!f_has_table) {
1209 cout << "finite_field::absolute_norm !f_has_table" << endl;
1210 exit(1);
1211 }
1212 for (j = 0; j < e; j++) {
1213 //ii = power(ii, p);
1214 //cout << "absolute_trace ii = " << ii << " -> ";
1215 ii = T->frobenius_image(ii);
1216 //cout << ii << endl;
1217 t = mult(t, ii);
1218 }
1219 if (ii != i) {
1220 cout << "finite_field::absolute_norm ii != i" << endl;
1221 exit(1);
1222 }
1223 return t;
1224}
1225
1227{
1228 if (!f_has_table) {
1229 cout << "finite_field::alpha_power !f_has_table" << endl;
1230 exit(1);
1231 }
1232 return T->alpha_power(i);
1233}
1234
1236{
1237 if (!f_has_table) {
1238 cout << "finite_field::log_alpha !f_has_table" << endl;
1239 exit(1);
1240 }
1241 return T->log_alpha(i);
1242}
1243
1245{
1246 int l, g, order;
1248
1249 if (a == 0) {
1250 cout << "finite_field::multiplicative_order a == 0" << endl;
1251 exit(1);
1252 }
1253 l = log_alpha(a);
1254 g = NT.gcd_lint(l, q - 1);
1255 order = (q - 1) / g;
1256 return order;
1257}
1258
1259void finite_field::all_square_roots(int a, int &nb_roots, int *roots2)
1260{
1261 if (a == 0) {
1262 nb_roots = 1;
1263 roots2[0] = 0;
1264 }
1265 else {
1266 if (p == 2) {
1267 // we are in characteristic two
1268
1269 nb_roots = 1;
1270 roots2[0] = frobenius_power(a, e - 1 /* frob_power */);
1271 }
1272 else {
1273 // we are in characteristic odd
1274 int r;
1275
1276 r = log_alpha(a);
1277 if (ODD(r)) {
1278 nb_roots = 0;
1279 }
1280 else {
1281 nb_roots = 2;
1282
1283 r >>= 1;
1284 roots2[0] = alpha_power(r);
1285 roots2[1] = negate(roots2[0]);
1286 }
1287 }
1288 }
1289}
1290
1292{
1293 int r;
1294
1295 r = log_alpha(i);
1296 if (ODD(r)) {
1297 return FALSE;
1298 }
1299 return TRUE;
1300}
1301
1302
1304{
1305 int r, root;
1306
1307 r = log_alpha(i);
1308 if (ODD(r)) {
1309 cout << "finite_field::square_root not a square: " << i << endl;
1310 exit(1);
1311 //return FALSE;
1312 }
1313 r >>= 1;
1314 root = alpha_power(r);
1315 return root;
1316}
1317
1319{
1320 return alpha;
1321}
1322
1324{
1325 int r;
1326 int b, c;
1327
1328 r = e >> 1;
1329 if (e != 2 * r) {
1330 cout << "finite_field::N2 field does not have a "
1331 "quadratic subfield" << endl;
1332 exit(1);
1333 }
1334 b = frobenius_power(a, r);
1335 c = mult(a, b);
1336 return c;
1337}
1338
1340{
1341 int r;
1342 int b, c;
1343
1344 r = e / 3;
1345 if (e != 3 * r) {
1346 cout << "finite_field::N3 field does not have a "
1347 "cubic subfield" << endl;
1348 exit(1);
1349 }
1350 b = frobenius_power(a, r);
1351 c = mult(a, b);
1352 b = frobenius_power(b, r);
1353 c = mult(c, b);
1354 return c;
1355}
1356
1358{
1359 int r;
1360 int b, c;
1361
1362 r = e >> 1;
1363 if (e != 2 * r) {
1364 cout << "finite_field::T2 field does not have a "
1365 "quadratic subfield" << endl;
1366 exit(1);
1367 }
1368 b = frobenius_power(a, r);
1369 c = add(a, b);
1370 return c;
1371}
1372
1374{
1375 int r;
1376 int b, c;
1377
1378 r = e / 3;
1379 if (e != 3 * r) {
1380 cout << "finite_field::T3 field does not have a "
1381 "cubic subfield" << endl;
1382 exit(1);
1383 }
1384 b = frobenius_power(a, r);
1385 c = add(a, b);
1386 b = frobenius_power(b, r);
1387 c = add(c, b);
1388 return c;
1389}
1390
1392{
1393 int r;
1394 int b;
1395
1396 r = e >> 1;
1397 if (e != 2 * r) {
1398 cout << "finite_field::bar field does not have a "
1399 "quadratic subfield" << endl;
1400 exit(1);
1401 }
1402 b = frobenius_power(a, r);
1403 return b;
1404}
1405
1406void finite_field::abc2xy(int a, int b, int c,
1407 int &x, int &y, int verbose_level)
1408// given a, b, c, determine x and y such that
1409// c = a * x^2 + b * y^2
1410// such elements x and y exist for any choice of a, b, c.
1411{
1412 int f_v = (verbose_level >= 1);
1413 int xx, yy, cc;
1414
1415 if (f_v) {
1416 cout << "finite_field::abc2xy q=" << q
1417 << " a=" << a << " b=" << b << " c=" << c << endl;
1418 }
1419 for (x = 0; x < q; x++) {
1420 xx = mult(x, x);
1421 for (y = 0; y < q; y++) {
1422 yy = mult(y, y);
1423 cc = add(mult(a, xx), mult(b, yy));
1424 if (cc == c) {
1425 if (f_v) {
1426 cout << "finite_field::abc2xy q=" << q
1427 << " x=" << x << " y=" << y << " done" << endl;
1428 }
1429 return;
1430 }
1431 }
1432 }
1433 cout << "finite_field::abc2xy no solution" << endl;
1434 cout << "a=" << a << endl;
1435 cout << "b=" << b << endl;
1436 cout << "c=" << c << endl;
1437 exit(1);
1438}
1439
1441 int index, int a, int verbose_level)
1442{
1443 int b;
1444
1445 retract_int_vec(subfield, index, &a, &b, 1, verbose_level);
1446 return b;
1447}
1448
1450 int index, int *v_in, int *v_out, int len,
1451 int verbose_level)
1452{
1453 int f_v = (verbose_level >= 1);
1454 int a, b, i, j, idx, m, n, k;
1456
1457 if (f_v) {
1458 cout << "finite_field::retract_int_vec index=" << index << endl;
1459 }
1460 n = e / index;
1461 m = NT.i_power_j(p, n);
1462 if (m != subfield.q) {
1463 cout << "finite_field::retract_int_vec subfield "
1464 "order does not match" << endl;
1465 exit(1);
1466 }
1467 idx = (q - 1) / (m - 1);
1468 if (f_v) {
1469 cout << "finite_field::retract_int_vec "
1470 "subfield " << p << "^" << n << " = " << n << endl;
1471 cout << "idx = " << idx << endl;
1472 }
1473
1474 for (k = 0; k < len; k++) {
1475 a = v_in[k];
1476 if (a == 0) {
1477 v_out[k] = 0;
1478 continue;
1479 }
1480 i = log_alpha(a);
1481 if (i % idx) {
1482 cout << "finite_field::retract_int_vec index=" << index
1483 << " k=" << k << " a=" << a << endl;
1484 cout << "element does not lie in the subfield" << endl;
1485 exit(1);
1486 }
1487 j = i / idx;
1488 b = subfield.alpha_power(j);
1489 v_out[k] = b;
1490 }
1491 if (f_v) {
1492 cout << "finite_field::retract_int_vec done" << endl;
1493 }
1494}
1495
1497 int index, int b, int verbose_level)
1498{
1499 int f_v = (verbose_level >= 1);
1500 int a, i, j, idx, m, n;
1502
1503 if (f_v) {
1504 cout << "finite_field::embed index=" << index
1505 << " b=" << b << endl;
1506 }
1507 if (b == 0) {
1508 a = 0;
1509 goto finish;
1510 }
1511 j = subfield.log_alpha(b);
1512 n = e / index;
1513 m = NT.i_power_j(p, n);
1514 if (m != subfield.q) {
1515 cout << "finite_field::embed subfield order does not match" << endl;
1516 exit(1);
1517 }
1518 idx = (q - 1) / (m - 1);
1519 if (f_v) {
1520 cout << "subfield " << p << "^" << n << " = " << n << endl;
1521 cout << "idx = " << idx << endl;
1522 }
1523 i = j * idx;
1524 a = alpha_power(i);
1525finish:
1526 if (f_v) {
1527 cout << "finite_field::embed index=" << index
1528 << " b=" << b << " a=" << a << endl;
1529 }
1530 return a;
1531}
1532
1534 finite_field &subfield,
1535 int *&components, int *&embedding, int *&pair_embedding,
1536 int verbose_level)
1537// we think of F as two dimensional vector space over f with basis (1,alpha)
1538// for i,j \in f, with x = i + j * alpha \in F, we have
1539// pair_embedding[i * q + j] = x;
1540// also,
1541// components[x * 2 + 0] = i;
1542// components[x * 2 + 1] = j;
1543// also, for i \in f, embedding[i] is the element in F that corresponds to i
1544// components[Q * 2]
1545// embedding[q]
1546// pair_embedding[q * q]
1547
1548{
1549 int f_v = (verbose_level >= 1);
1550 int f_vv = (verbose_level >= 1);
1551 int alpha, i, j, I, J, x, q, Q;
1552
1553 if (f_v) {
1554 cout << "finite_field::subfield_embedding_2dimensional" << endl;
1555 }
1556 Q = finite_field::q;
1557 q = subfield.q;
1558 components = NEW_int(Q * 2);
1559 embedding = NEW_int(q);
1560 pair_embedding = NEW_int(q * q);
1561 alpha = p;
1562 embedding[0] = 0;
1563 for (i = 0; i < q * q; i++) {
1564 pair_embedding[i] = -1;
1565 }
1566 for (i = 0; i < Q * 2; i++) {
1567 components[i] = -1;
1568 }
1569 for (i = 1; i < q; i++) {
1570 j = embed(subfield, 2, i, verbose_level - 2);
1571 embedding[i] = j;
1572 }
1573 for (i = 0; i < q; i++) {
1574 I = embed(subfield, 2, i, verbose_level - 4);
1575 if (f_vv) {
1576 cout << "i=" << i << " I=" << I << endl;
1577 }
1578 for (j = 0; j < q; j++) {
1579 J = embed(subfield, 2, j, verbose_level - 4);
1580 x = add(I, mult(alpha, J));
1581 if (pair_embedding[i * q + j] != -1) {
1582 cout << "error" << endl;
1583 cout << "element (" << i << "," << j << ") embeds "
1584 "as (" << I << "," << J << ") = " << x << endl;
1585 exit(1);
1586 }
1587 pair_embedding[i * q + j] = x;
1588 components[x * 2 + 0] = i;
1589 components[x * 2 + 1] = j;
1590 if (f_vv) {
1591 cout << "element (" << i << "," << j << ") embeds "
1592 "as (" << I << "," << J << ") = " << x << endl;
1593 }
1594 }
1595 }
1596 if (f_vv) {
1597 print_embedding(subfield, components,
1598 embedding, pair_embedding);
1599 }
1600 if (f_v) {
1601 cout << "finite_field::subfield_embedding_2dimensional "
1602 "done" << endl;
1603 }
1604}
1605
1607{
1608 return nb_times_mult;
1609}
1610
1612{
1613 return nb_times_add;
1614}
1615
1616void finite_field::compute_nth_roots(int *&Nth_roots, int n, int verbose_level)
1617{
1618 int f_v = (verbose_level >= 1);
1619 int i, idx, beta;
1620
1621 if (f_v) {
1622 cout << "finite_field::compute_nth_roots" << endl;
1623 }
1624
1625 if ((q - 1) % n) {
1626 cout << "finite_field::compute_nth_roots n does not divide q - 1" << endl;
1627 exit(1);
1628 }
1629
1630 idx = (q - 1) / n;
1631 beta = power(alpha, idx);
1632 Nth_roots = NEW_int(n);
1633 Nth_roots[0] = 1;
1634 Nth_roots[1] = beta;
1635 for (i = 2; i < n; i++) {
1636 Nth_roots[i] = mult(Nth_roots[i - 1], beta);
1637 }
1638
1639
1640 if (f_v) {
1641 cout << "finite_field::compute_nth_roots done" << endl;
1642 }
1643}
1644
1645
1647{
1649
1650 if (e == 1) {
1651 return NT.primitive_root(p, FALSE);
1652 }
1653 return p;
1654}
1655
1656
1657}}}
1658
implementation of a finite Galois field Fq using tables
implementation of a finite Galois field Fq without any tables
int add5(int i1, int i2, int i3, int i4, int i5)
int add8(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8)
void print_minimum_polynomial(int p, std::string &polynomial)
int power_verbose(int a, int n, int verbose_level)
void init(finite_field_description *Descr, int verbose_level)
int product5(int a1, int a2, int a3, int a4, int a5)
orthogonal_geometry::orthogonal_indexing * Orthogonal_indexing
int mult_verbose(int i, int j, int verbose_level)
int mult6(int a1, int a2, int a3, int a4, int a5, int a6)
void compute_nth_roots(int *&Nth_roots, int n, int verbose_level)
void retract_int_vec(finite_field &subfield, int index, int *v_in, int *v_out, int len, int verbose_level)
int mult5(int a1, int a2, int a3, int a4, int a5)
int add7(int i1, int i2, int i3, int i4, int i5, int i6, int i7)
void finite_field_init(int q, int f_without_tables, int verbose_level)
int compute_order_of_element(int elt, int verbose_level)
void init_implementation(int f_without_tables, int verbose_level)
void frobenius_power_vec(int *v, int len, int frob_power)
void init_override_polynomial(int q, std::string &poly, int f_without_tables, int verbose_level)
void subfield_embedding_2dimensional(finite_field &subfield, int *&components, int *&embedding, int *&pair_embedding, int verbose_level)
void print_embedding(finite_field &subfield, int *components, int *embedding, int *pair_embedding)
int retract(finite_field &subfield, int index, int a, int verbose_level)
void frobenius_power_vec_to_vec(int *v_in, int *v_out, int len, int frob_power)
void abc2xy(int a, int b, int c, int &x, int &y, int verbose_level)
void all_square_roots(int a, int &nb_roots, int *roots2)
long int compute_subfield_polynomial(int order_subfield, int f_latex, std::ostream &ost, int verbose_level)
int add6(int i1, int i2, int i3, int i4, int i5, int i6)
int embed(finite_field &subfield, int index, int b, int verbose_level)
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)
void init(field_theory::finite_field *F, int verbose_level)
indexing of points in an orthogonal geometry O^epsilon(n,q)
Definition: orthogonal.h:135
void init(field_theory::finite_field *F, int verbose_level)
domain of polynomials in one variable over a finite field
Definition: ring_theory.h:691
void mult(unipoly_object a, unipoly_object b, unipoly_object &c, int verbose_level)
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 assign(unipoly_object a, unipoly_object &b, int verbose_level)
void print_object(unipoly_object p, std::ostream &ost)
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_char(n)
Definition: foundations.h:632
#define NEW_OBJECT(type)
Definition: foundations.h:638
#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 ODD(x)
Definition: foundations.h:222
#define FREE_char(p)
Definition: foundations.h:646
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects