Orbiter 2022
Combinatorial Objects
cyclic_codes.cpp
Go to the documentation of this file.
1/*
2 * cyclic_codes.cpp
3 *
4 * Created on: Jun 24, 2021
5 * Author: betten
6 */
7
8#include "foundations.h"
9
10using namespace std;
11
12
13
14namespace orbiter {
15namespace layer1_foundations {
16namespace coding_theory {
17
21 int verbose_level)
22{
23 int f_v = (verbose_level >= 1);
24
25 if (f_v) {
26 cout << "coding_theory_domain::make_BCH_code q=" << F->q << " n=" << n
27 << " d=" << d << endl;
28 }
29
30
32
33 Nth->init(F, n, verbose_level);
34
35 int *Selection;
36 int *Sel;
37 int nb_sel;
38 int i, j;
39
40
41 Selection = NEW_int(Nth->Cyc->S->nb_sets);
42 Sel = NEW_int(Nth->Cyc->S->nb_sets);
43
44 for (i = 0; i < Nth->Cyc->S->nb_sets; i++) {
45 Selection[i] = FALSE;
46 }
47
48 for (i = 0; i < d - 1; i++) {
49 j = Nth->Cyc->Index[(1 + i) % n];
50 Selection[j] = TRUE;
51 }
52
53 nb_sel = 0;
54 for (i = 0; i < Nth->Cyc->S->nb_sets; i++) {
55 if (Selection[i]) {
56 Sel[nb_sel++] = i;
57 }
58 }
59
60 if (f_v) {
61 cout << "coding_theory_domain::make_BCH_code Sel=";
62 Int_vec_print(cout, Sel, nb_sel);
63 cout << endl;
64 }
65
67
68 Nth->FX->create_object_by_rank(P, 1, __FILE__, __LINE__, 0 /*verbose_level*/);
69 Nth->FX->create_object_by_rank(Q, 1, __FILE__, __LINE__, 0 /*verbose_level*/);
70
71 for (i = 0; i < nb_sel; i++) {
72
73 j = Sel[i];
74
75 if (f_v) {
76 cout << "coding_theory_domain::make_BCH_code P=";
77 Nth->FX->print_object(P, cout);
78 cout << endl;
79 cout << "j=" << j << endl;
80 Nth->FX->print_object(Nth->generator_Fq[j], cout);
81 cout << endl;
82 }
83 Nth->FX->mult(P, Nth->generator_Fq[j], Q, verbose_level);
84 if (f_v) {
85 cout << "coding_theory_domain::make_BCH_code Q=";
86 Nth->FX->print_object(Q, cout);
87 cout << endl;
88 }
89 Nth->FX->assign(Q, P, 0 /* verbose_level */);
90 }
91
92
93
94 if (f_v) {
95 cout << "coding_theory_domain::make_BCH_code q=" << F->q << " n=" << n
96 << " d=" << d << " done" << endl;
97 }
98}
99
100
101
103 int *roots, int nb_roots, int f_poly, std::string &poly,
104 int f_dual, std::string &fname_txt, std::string &fname_csv,
105 int verbose_level)
106{
107 int f_v = (verbose_level >= 1);
108 int f_vv = (verbose_level >= 2);
109 int p, e, m, r, i;
114
115 NT.factor_prime_power(q, p, e);
116 if (f_v) {
117 cout << "coding_theory_domain::make_cyclic_code q=" << q << " p=" << q
118 << " e=" << e << " n=" << n << endl;
119 for (i = 0; i < nb_roots; i++) {
120 cout << roots[i] << " ";
121 }
122 cout << endl;
123 if (f_dual) {
124 cout << "coding_theory_domain::make_cyclic_code dual code" << endl;
125 }
126 }
127 m = NT.order_mod_p(q, n);
128 if (f_v) {
129 cout << "coding_theory_domain::make_cyclic_code order mod q is m=" << m << endl;
130 }
131 D.create_qnm1(Qm1, q, m);
132
133 // q = i_power_j(p, e);
134 // GF(q)=GF(p^e) has n-th roots of unity
135 D.integral_division_by_int(Qm1, n, Index, r);
136 //b = (q - 1) / n;
137 if (r != 0) {
138 cout << "coding_theory_domain::make_cyclic_code n does not divide q^m-1" << endl;
139 exit(1);
140 }
141 if (f_v) {
142 cout << "coding_theory_domain::make_cyclic_code GF(" << q << "^" << m << ") has "
143 << n << "-th roots of unity" << endl;
144 if (Index.is_one()) {
145 cout << "coding_theory_domain::make_cyclic_code this is a primitive code" << endl;
146 }
147 else {
148 cout << "coding_theory_domain::make_cyclic_code we take as " << n << "-th root \\beta = \\alpha^"
149 << Index << ", where \\alpha is a primitive element of "
150 "the field" << endl;
151 }
152 }
153
154 int j, degree, field_degree;
155 int *taken;
156 int *transversal, tl = 0;
157
158 field_degree = m * e;
159 degree = 0;
160 taken = NEW_int(n);
161 transversal = NEW_int(n);
162 for (i = 0; i < n; i++) {
163 taken[i] = FALSE;
164 }
165
166
167 for (i = 0; i < nb_roots; i++) {
168 j = roots[i];
169 if (taken[j]) {
170 cout << q << "-cyclotomic coset of "
171 << j << " already taken" << endl;
172 continue;
173 }
174 if (!taken[j]) {
175 transversal[tl++] = j;
176 }
177 taken[j] = TRUE;
178 degree++;
179 if (f_v) {
180 cout << q << "-cyclotomic coset of "
181 << j << " : " << j;
182 }
183 while (TRUE) {
184 j = (q * j) % n;
185 if (taken[j]) {
186 break;
187 }
188 taken[j] = TRUE;
189 degree++;
190 if (f_v) {
191 cout << "," << j;
192 }
193 }
194 if (f_v) {
195 cout << " degree=" << degree << endl;
196 }
197 }
198
199 if (f_v) {
200 cout << "coding_theory_domain::make_cyclic_code transversal: ";
201 for (i = 0; i < tl; i++) {
202 cout << transversal[i] << " ";
203 }
204 cout << endl;
205 cout << "coding_theory_domain::make_cyclic_code exponents:";
206 for (i = 0; i < n; i++) {
207 if (!taken[i]) {
208 continue;
209 }
210 cout << i << ", ";
211 }
212 cout << endl;
213 cout << "coding_theory_domain::make_cyclic_code degree=" << degree << endl;
214 }
215
216 if (f_dual) {
217 for (i = 0; i < n; i++) {
218 taken[i] = !taken[i];
219 }
220 degree = n - degree;
221 if (f_v) {
222 cout << "coding_theory_domain::make_cyclic_code dually, exponents:";
223 for (i = 0; i < n; i++) {
224 if (!taken[i])
225 continue;
226 cout << i << ", ";
227 }
228 cout << endl;
229 cout << "coding_theory_domain::make_cyclic_code degree=" << degree << endl;
230 }
231 }
232
235 ring_theory::unipoly_object beta, beta_i, c;
236
237 if (f_v) {
238 cout << "coding_theory_domain::make_cyclic_code creating the finite field of order " << p << endl;
239 }
240 Fp.finite_field_init(p, FALSE /* f_without_tables */, verbose_level - 1);
241
243 string field_poly;
245
246 if (f_v) {
247 cout << "coding_theory_domain::make_cyclic_code before K.get_primitive_polynomial" << endl;
248 }
249 K.get_primitive_polynomial(field_poly, p, field_degree, 0);
250
251 if (f_v) {
252 cout << "coding_theory_domain::make_cyclic_code before FpX.create_object_by_rank_string" << endl;
253 }
254 FpX.create_object_by_rank_string(M, field_poly, verbose_level - 1);
255
256 if (f_v) {
257 cout << "coding_theory_domain::make_cyclic_code choosing the following irreducible "
258 "and primitive polynomial:" << endl;
259 FpX.print_object(M, cout); cout << endl;
260 }
261
262 if (f_v) {
263 cout << "coding_theory_domain::make_cyclic_code creating unipoly_domain Fq modulo M" << endl;
264 }
265 ring_theory::unipoly_domain Fq(&Fp, M, verbose_level); // Fq = Fp[X] modulo factor polynomial M
266 if (f_vv) {
267 cout << "coding_theory_domain::make_cyclic_code extension field created" << endl;
268 }
269
270 Fq.create_object_by_rank(c, 0, __FILE__, __LINE__, verbose_level);
271 Fq.create_object_by_rank(beta, p, __FILE__, __LINE__, verbose_level); // the element alpha
272 Fq.create_object_by_rank(beta_i, 1, __FILE__, __LINE__, verbose_level);
273 if (!Index.is_one()) {
274 //Fq.power_int(beta, b);
275 if (f_v) {
276 cout << "\\alpha = ";
277 Fq.print_object(beta, cout);
278 cout << endl;
279 }
280 if (f_v) {
281 cout << "coding_theory_domain::make_cyclic_code before Fq.power_longinteger" << endl;
282 }
283 Fq.power_longinteger(beta, Index, verbose_level - 1);
284 if (f_v) {
285 cout << "\\beta = \\alpha^" << Index << " = ";
286 Fq.print_object(beta, cout);
287 cout << endl;
288 }
289 }
290 else {
291 if (f_v) {
292 cout << "coding_theory_domain::make_cyclic_code this is a primitive BCH code" << endl;
293 }
294 }
295
296 if (f_v) {
297 cout << "coding_theory_domain::make_cyclic_code before allocating generator etc" << endl;
298 }
299
304
305
306 // create the polynomial X - a:
307 if (f_v) {
308 cout << "coding_theory_domain::make_cyclic_code creating X-a" << endl;
309 }
310 for (i = 0; i < 2; i++) {
311 if (i == 1) {
312 Fq.create_object_by_rank(coeffs[i], 1, __FILE__, __LINE__, verbose_level);
313 }
314 else {
315 Fq.create_object_by_rank(coeffs[i], 0, __FILE__, __LINE__, verbose_level);
316 }
317 }
318 for (i = 0; i <= degree; i++) {
319 if (f_v) {
320 cout << "coding_theory_domain::make_cyclic_code creating generator[" << i << "]" << endl;
321 }
322 Fq.create_object_by_rank(generator[i], 0, __FILE__, __LINE__, verbose_level);
323 Fq.create_object_by_rank(tmp[i], 0, __FILE__, __LINE__, verbose_level);
324 }
325 if (f_v) {
326 cout << "coding_theory_domain::make_cyclic_code creating generator[0]" << endl;
327 }
328 Fq.create_object_by_rank(generator[0], 1, __FILE__, __LINE__, verbose_level);
329
330 // now coeffs has degree 1
331 // and generator has degree 0
332
333 if (f_vv) {
334 cout << "coding_theory_domain::make_cyclic_code coeffs:" << endl;
335 print_polynomial(Fq, 1, coeffs);
336 cout << endl;
337 cout << "coding_theory_domain::make_cyclic_code generator:" << endl;
338 print_polynomial(Fq, 0, generator);
339 cout << endl;
340 }
341
342 if (f_v) {
343 cout << "coding_theory_domain::make_cyclic_code creating Pc" << endl;
344 }
345 Fq.create_object_by_rank(Pc, 0, __FILE__, __LINE__, verbose_level);
346 if (f_v) {
347 cout << "coding_theory_domain::make_cyclic_code creating Pd" << endl;
348 }
349 Fq.create_object_by_rank(Pd, 0, __FILE__, __LINE__, verbose_level);
350
351 r = 0;
352 for (i = 0; i < n; i++) {
353 if (f_v) {
354 cout << "i=" << i << ", r=" << r << endl;
355 }
356 if (!taken[i]) {
357 continue;
358 }
359 if (f_v) {
360 cout << "coding_theory_domain::make_cyclic_code working on root " << i << endl;
361 }
362 if (f_v) {
363 cout << "coding_theory_domain::make_cyclic_code before Fq.assign beta" << endl;
364 }
365 Fq.assign(beta, beta_i, verbose_level);
366 if (f_v) {
367 cout << "coding_theory_domain::make_cyclic_code before Fq.power_int" << endl;
368 }
369 Fq.power_int(beta_i, i, verbose_level);
370 if (f_v) {
371 cout << "coding_theory_domain::make_cyclic_code before Fq.negate" << endl;
372 }
373 Fq.negate(beta_i);
374 if (f_v) {
375 cout << "coding_theory_domain::make_cyclic_code before Fq.assign beta_i" << endl;
376 }
377 Fq.assign(beta_i, coeffs[0], verbose_level);
378 if (f_v) {
379 cout << "coding_theory_domain::make_cyclic_code root: " << i << " : ";
380 Fq.print_object(beta_i, cout);
381 //cout << " : ";
382 //print_polynomial(Fq, 2, coeffs);
383 cout << endl;
384 }
385
386
387 if (f_v) {
388 cout << "coding_theory_domain::make_cyclic_code before Fq.assign(generator[j], tmp[j])" << endl;
389 }
390 for (j = 0; j <= r; j++) {
391 Fq.assign(generator[j], tmp[j], verbose_level);
392 }
393
394 //cout << "tmp:" << endl;
395 //print_polynomial(Fq, r, tmp);
396 //cout << endl;
397
398 if (f_v) {
399 cout << "coding_theory_domain::make_cyclic_code before Fq.assign(tmp[j], generator[j + 1])" << endl;
400 }
401 for (j = 0; j <= r; j++) {
402 Fq.assign(tmp[j], generator[j + 1], verbose_level);
403 }
404 Fq.delete_object(generator[0]);
405 Fq.create_object_by_rank(generator[0], 0, __FILE__, __LINE__, verbose_level);
406
407 //cout << "generator after shifting up:" << endl;
408 //print_polynomial(Fq, r + 1, generator);
409 //cout << endl;
410
411 for (j = 0; j <= r; j++) {
412 if (f_v) {
413 cout << "coding_theory_domain::make_cyclic_code j=" << j << endl;
414 }
415 if (f_v) {
416 cout << "coding_theory_domain::make_cyclic_code before Fq.mult(tmp[j], coeffs[0], Pc)" << endl;
417 }
418 Fq.mult(tmp[j], coeffs[0], Pc, verbose_level - 1);
419 if (f_v) {
420 cout << "coding_theory_domain::make_cyclic_code before Fq.add()" << endl;
421 }
422 Fq.add(Pc, generator[j], Pd);
423 if (f_v) {
424 cout << "coding_theory_domain::make_cyclic_code before Fq.assign()" << endl;
425 }
426 Fq.assign(Pd, generator[j], verbose_level);
427 }
428 r++;
429 if (f_v) {
430 cout << "coding_theory_domain::make_cyclic_code r=" << r << endl;
431 }
432 if (f_v) {
433 cout << "coding_theory_domain::make_cyclic_code current polynomial: ";
434 print_polynomial(Fq, r, generator);
435 cout << endl;
436 }
437
438 }
439 if (f_v) {
440 cout << "coding_theory_domain::make_cyclic_code The generator polynomial is: ";
441 print_polynomial(Fq, r, generator);
442 cout << endl;
443 }
444
445 Fq.delete_object(c);
446 Fq.delete_object(beta);
447 Fq.delete_object(beta_i);
448
449
450 int *generator_subfield;
451 int *Genma;
452
453 if (f_v) {
454 cout << "coding_theory_domain::make_cyclic_code before field_reduction" << endl;
455 }
456 field_reduction(n, q, p, e, m, Fp, Fq, r,
457 generator, generator_subfield, f_poly, poly, verbose_level);
458 cout << "coding_theory_domain::make_cyclic_code generator polynomial:" << endl;
459 for (j = 0; j <= degree; j++) {
460 cout << generator_subfield[j] << " ";
461 }
462 cout << endl;
463
464 if (f_v) {
465 cout << "coding_theory_domain::make_cyclic_code before generator_matrix_cyclic_code" << endl;
466 }
467 generator_matrix_cyclic_code(n, degree, generator_subfield, Genma);
468 cout << "coding_theory_domain::make_cyclic_code generator matrix: " << endl;
469 Int_vec_print_integer_matrix_width(cout, Genma, n - degree, n, n, 3);
470
471
472 {
473 ofstream fp(fname_txt);
474 int k = n - degree;
475
476
477 fp << n << " " << k << " " << t << " " << q << endl;
478 for (i = 0; i < k; i++) {
479 for (j = 0; j < n; j++) {
480 fp << Genma[i * n + j] << " ";
481 }
482 fp << endl;
483 }
484 fp << endl;
485 }
486 cout << "coding_theory_domain::make_cyclic_code Written file " << fname_txt << " of size "
487 << Fio.file_size(fname_txt) << endl;
488
489
490 {
491 int k = n - degree;
492
493
494 Fio.int_matrix_write_csv(fname_csv, Genma, k, n);
495 cout << "coding_theory_domain::make_cyclic_code Written file " << fname_csv << " of size "
496 << Fio.file_size(fname_csv) << endl;
497 }
498
499
501
502 int k = n - degree;
503
504 cout << "$$" << endl;
505 cout << "\\left[" << endl;
506 L.int_matrix_print_tex(cout, Genma, k, n);
507 cout << "\\right]" << endl;
508 cout << "$$" << endl;
509
510 //cout << "before FREE_int(taken)" << endl;
511 FREE_int(taken);
512 //cout << "before FREE_int(transversal)" << endl;
513 FREE_int(transversal);
514 //cout << "before FREE_int(generator_subfield)" << endl;
515 FREE_int(generator_subfield);
516 //cout << "before FREE_int(Genma)" << endl;
517 FREE_int(Genma);
518 //cout << "before FREE_OBJECTS(generator)" << endl;
519 for (i = 0; i <= degree; i++) {
520 Fq.delete_object(generator[i]);
521 }
522 //FREE_OBJECTS(generator);
523 cout << "before FREE_OBJECTS(tmp)" << endl;
524 for (i = 0; i <= degree; i++) {
525 Fq.delete_object(tmp[i]);
526 }
527 FREE_OBJECTS(tmp);
528 //cout << "before FREE_OBJECTS(coeffs)" << endl;
529 for (i = 0; i < 2; i++) {
530 Fq.delete_object(coeffs[i]);
531 }
532 FREE_OBJECTS(coeffs);
533
534}
535
537 int degree, int *generator_polynomial, int *&M)
538{
539 int k = n - degree;
540 int i, j;
541
542 M = NEW_int(k * n);
543 Int_vec_zero(M, k * n);
544 for (i = 0; i < k; i++) {
545 for (j = 0; j <= degree; j++) {
546 M[i * n + j + i] = generator_polynomial[j];
547 }
548 }
549}
550
552 int degree, ring_theory::unipoly_object *coeffs)
553{
554 int i, f_first = TRUE;
555
556 for (i = 0; i <= degree; i++) {
557 if (Fq.is_zero(coeffs[i])) {
558 continue;
559 }
560 if (!f_first) {
561 cout << " + ";
562 }
563 f_first = FALSE;
564 if (!Fq.is_one(coeffs[i])) {
565 cout << "(";
566 Fq.print_object(coeffs[i], cout);
567 cout << ") * ";
568 }
569 cout << " Z^" << i;
570 }
571}
572
575 int degree, ring_theory::unipoly_object *coeffs)
576{
577 int i, f_first = TRUE;
578
579 for (i = 0; i <= degree; i++) {
580 if (!f_first) {
581 ost << " + ";
582 }
583 f_first = FALSE;
584
585 ost << "(";
586 Fq.print_object_tight(coeffs[i], ost);
587 ost << ") ";
588 ost << " X^{" << i << "}";
589 }
590}
591
592
593void coding_theory_domain::field_reduction(int n, int q, int p, int e, int m,
596 int degree, ring_theory::unipoly_object *generator, int *&generator_subfield,
597 int f_poly, std::string &poly,
598 int verbose_level)
599{
600 int f_v = (verbose_level >= 1);
601 //int f_vv = (verbose_level >= 2);
602 int r;
605
606 if (f_v) {
607 cout << "coding_theory_domain::field_reduction" << endl;
608 }
609 D.create_qnm1(Qm1, q, m);
610
611 D.integral_division_by_int(Qm1, q - 1, Index, r);
612
613 if (r != 0) {
614 cout << "coding_theory_domain::field_reduction q - 1 "
615 "does not divide q^m - 1" << endl;
616 exit(1);
617 }
618 if (f_v) {
619 cout << "considering the subfield GF(" << q
620 << ") of GF(" << q << "^" << m << ")" << endl;
621 cout << "subgroup index = " << Index << endl;
622 }
623
624 ring_theory::unipoly_object c, beta, beta_i;
625 ring_theory::longinteger_object *beta_rk_table, rk;
626 int i, j;
627
628
630
631 Fq.create_object_by_rank(c, 0, __FILE__, __LINE__, verbose_level);
632 Fq.create_object_by_rank(beta, p, __FILE__, __LINE__, verbose_level); // the element alpha
633 Fq.create_object_by_rank(beta_i, 1, __FILE__, __LINE__, verbose_level);
634 if (f_v) {
635 cout << "\\alpha = ";
636 Fq.print_object(beta, cout);
637 cout << endl;
638 }
639 Fq.power_longinteger(beta, Index, verbose_level - 1);
640 if (f_v) {
641 cout << "\\beta = \\alpha^" << Index << " = ";
642 Fq.print_object(beta, cout);
643 cout << endl;
644 }
645 for (i = 1; i <= q - 1; i++) {
646 Fq.assign(beta, beta_i, verbose_level);
647 Fq.power_int(beta_i, i, 0);
648 Fq.rank_longinteger(beta_i, beta_rk_table[i]);
649 if (f_v) {
650 cout << i << " : ";
651 Fq.print_object(beta_i, cout);
652 cout << " : " << beta_rk_table[i] << endl;
653 }
654 }
655
656 generator_subfield = NEW_int(degree + 1);
657
658 for (i = 0; i <= degree; i++) {
659 Fq.rank_longinteger(generator[i], rk);
660 if (f_v) {
661 cout << "coefficient " << i << " has rk " << rk << endl;
662 }
663 if (rk.is_zero()) {
664 generator_subfield[i] = 0;
665 continue;
666 }
667 for (j = 1; j <= q - 1; j++) {
668 if (D.compare(rk, beta_rk_table[j]) == 0) {
669 generator_subfield[i] = j;
670 break;
671 }
672 }
673 if (j == q) {
674 cout << "error, coefficient "
675 "does not lie in the subfield" << endl;
676 exit(1);
677 }
678 }
679 if (f_v) {
680 cout << "over the subfield, exponential notation:" << endl;
681 for (i = 0; i <= degree; i++) {
682 cout << " " << generator_subfield[i] << "Z^" << i;
683 }
684 cout << endl;
685 }
686 if (f_v) {
687 cout << "i : beta^i" << endl;
688 }
689 for (i = 0; i <= e; i++) {
690 Fq.assign(beta, beta_i, verbose_level);
691 Fq.power_int(beta_i, i, 0);
692 if (f_v) {
693 cout << i << " : ";
694 Fq.print_object(beta_i, cout);
695 cout << endl;
696 }
697 }
698
699 if (!f_poly) {
700 goto the_end;
701 }
702
703 {
705
706 fq.init_override_polynomial(q, poly, FALSE /* f_without_tables */, verbose_level);
707 cout << "q = " << q << " override polynomial = " << poly << endl;
708
709 for (i = 0; i <= degree; i++) {
710 j = generator_subfield[i];
711 if (j == 0) {
712 continue;
713 }
714 generator_subfield[i] = fq.alpha_power(j);
715 }
716 if (f_v) {
717 cout << "over the subfield:" << endl;
718 for (i = 0; i <= degree; i++) {
719 j = generator_subfield[i];
720 if (j == 0) {
721 continue;
722 }
723 cout << " + " << j << " x^" << i;
724 }
725 cout << endl;
726 }
727 }
728
729the_end:
730
731 Fq.delete_object(c);
732 Fq.delete_object(beta);
733 Fq.delete_object(beta_i);
734 FREE_OBJECTS(beta_rk_table);
735
736 if (f_v) {
737 cout << "coding_theory_domain::field_reduction done" << endl;
738 }
739
740}
741
745 int designed_distance, int &bose_distance,
746 int &transversal_length, int *&transversal,
747 ring_theory::longinteger_object *&rank_of_irreducibles,
748 int verbose_level)
749{
750 int f_v = (verbose_level >= 1);
751 int f_vv = (verbose_level >= 2);
752 int f_vvv = (verbose_level >= 3);
753 int p = F->q;
754 int e, i, j, r;
758
759 if (f_v) {
760 cout << "coding_theory_domain::BCH_generator_polynomial "
761 "n=" << n << " designed_distance="
762 << designed_distance << " p=" << p << endl;
763 }
764
766
767
768 e = NT.order_mod_p(p, n);
769 q.create(p, __FILE__, __LINE__);
770 m1.create(-1, __FILE__, __LINE__);
771 D.power_int(q, e);
772 D.add(q, m1, qm1);
773 // q = i_power_j(p, e);
774 // GF(q)=GF(p^e) has n-th roots of unity
775 D.integral_division_by_int(qm1, n, b, r);
776 //b = (q - 1) / n;
777 if (r != 0) {
778 cout << "coding_theory_domain::BCH_generator_polynomial r != 0" << endl;
779 exit(1);
780 }
781 if (f_v) {
782 cout << "GF(" << q << ") "
783 "= GF(" << p << "^" << e << ") "
784 "has " << n << "-th roots of unity" << endl;
785 if (b.is_one()) {
786 cout << "this is a primitive BCH code" << endl;
787 }
788 else {
789 cout << "we take as " << n << "-th root \\beta = \\alpha^" << b << ", where "
790 "\\alpha is a primitive element of the field" << endl;
791 }
792 }
793
794 string field_poly;
795 ring_theory::unipoly_object m, M, h1, h2;
797
798 K.get_primitive_polynomial(field_poly, p, e, 0);
799 FX.create_object_by_rank_string(m, field_poly, verbose_level - 2);
800 FX.create_object_by_rank_string(M, field_poly, verbose_level - 2);
801
802 FX.create_object_by_rank(g, 1, __FILE__, __LINE__, verbose_level);
803 FX.create_object_by_rank(h1, 0, __FILE__, __LINE__, verbose_level);
804 FX.create_object_by_rank(h2, 0, __FILE__, __LINE__, verbose_level);
805
806 if (f_vv) {
807 cout << "choosing the following irreducible "
808 "and primitive polynomial:" << endl;
809 FX.print_object(m, cout); cout << endl;
810 }
811
812 ring_theory::unipoly_domain Fq(F, M, verbose_level - 1);
813 ring_theory::unipoly_object beta, beta_i, c;
814 if (f_vvv) {
815 cout << "extension field created" << endl;
816 }
817 Fq.create_object_by_rank(c, 0, __FILE__, __LINE__, verbose_level);
818 Fq.create_object_by_rank(beta, p, __FILE__, __LINE__, verbose_level); // the primitive element alpha
819 Fq.create_object_by_rank(beta_i, 1, __FILE__, __LINE__, verbose_level);
820 if (!b.is_one()) {
821 //Fq.power_int(beta, b, 0 /* verbose_level */);
822 if (f_vvv) {
823 cout << "\\alpha = ";
824 Fq.print_object(beta, cout);
825 cout << endl;
826 }
827 Fq.power_longinteger(beta, b, verbose_level - 1);
828#if 0
829 if (b.as_int() == 11) {
830 for (i = 1; i <= b.as_int(); i++) {
831 Fq.create_object_by_rank(beta, p); // the element alpha
832 Fq.power_int(beta, i, 0 /* verbose_level */);
833 cout << "\\alpha^" << i << " = ";
834 Fq.print_object(beta, cout);
835 cout << endl;
836 }
837 }
838#endif
839 if (f_vvv) {
840 cout << "\\beta = \\alpha^" << b << " = ";
841 Fq.print_object(beta, cout);
842 cout << endl;
843 }
844 }
845 else {
846 if (f_vvv) {
847 cout << "this is a primitive BCH code" << endl;
848 }
849 }
850
851 // now beta is a primitive n-th root of unity
852
853#if 0
854 if (1 + designed_distance - 2 >= q - 1) {
855 cout << "coding_theory_domain::BCH_generator_polynomial "
856 "1 + designed_distance - 2 >= q - 1" << endl;
857 exit(1);
858 }
859#endif
860
863
864
865 for (i = 0; i < n; i++) {
866 Fq.rank_longinteger(beta_i, beta_rk_table[i]);
867
868 if (f_vvv) {
869 cout << "\\beta^" << i << " = ";
870 Fq.print_object(beta_i, cout);
871 cout << " = " << beta_rk_table[i] << endl;
872 }
873 Fq.mult(beta, beta_i, c, verbose_level - 1);
874 Fq.assign(c, beta_i, verbose_level);
875 }
876 if (f_vvv) {
877 for (i = 0; i < n; i++) {
878 cout << "\\beta^" << i << " = ";
879 //Fq.print_object(beta_i, cout);
880 cout << " = " << beta_rk_table[i] << endl;
881 }
882 }
883
884
885 int *chosen = NEW_int(n);
886 //int *transversal = NEW_int(n);
887 //int transversal_length = 0, i0;
888 int i0;
889
890 transversal = NEW_int(n);
891 transversal_length = 0;
892
893 for (i = 0; i < n; i++) {
894 chosen[i] = FALSE;
895 }
896
897 for (i = 1; i <= 1 + designed_distance - 2; i++) {
898 Fq.mult(beta, beta_i, c, verbose_level - 1);
899 Fq.assign(c, beta_i, verbose_level);
900
901 Fq.rank_longinteger(beta_i, ai);
902 if (f_vvv) {
903 cout << "\\beta^" << i << " = ";
904 Fq.print_object(beta_i, cout);
905 cout << " = " << ai << endl;
906 }
907 if (chosen[i]) {
908 continue;
909 }
910
911 transversal[transversal_length++] = i;
912 if (f_v) {
913 cout << "orbit of conjugate elements "
914 "(in powers of \\beta):" << endl;
915 cout << "{ ";
916 }
917 ai.assign_to(bi);
918 i0 = i;
919 do {
920 chosen[i] = TRUE;
921 Fq.create_object_by_rank_longinteger(c, bi, __FILE__, __LINE__, verbose_level);
922 if (f_vvv) {
923 cout << bi << " = ";
924 Fq.print_object(c, cout);
925 }
926 else if (f_v) {
927 cout << i << " ";
928 }
929 //power_coefficients(c, p);
930 Fq.power_int(c, p, 0 /* verbose_level */);
931 Fq.rank_longinteger(c, bi);
932 for (j = 0; j < n; j++) {
933 if (D.compare(bi, beta_rk_table[j]) == 0) {
934 break;
935 }
936 }
937 if (j == n) {
938 cout << "couldn't find rank in the table (A)" << endl;
939 exit(1);
940 }
941 if (f_vv) {
942 cout << " is \\beta^" << j << endl;
943 }
944 i = j;
945 } while (j != i0);
946 if (f_vv || f_v) {
947 cout << "}" << endl;
948 }
949 }
950
951 // compute the bose_distance:
952 Fq.create_object_by_rank(beta_i, 1, __FILE__, __LINE__, verbose_level);
953 for (i = 1; ; i++) {
954 Fq.mult(beta, beta_i, c, verbose_level - 1);
955 FX.assign(c, beta_i, verbose_level);
956 Fq.rank_longinteger(beta_i, ai);
957 for (j = 0; j < n; j++) {
958 if (D.compare(ai, beta_rk_table[j]) == 0) {
959 break;
960 }
961 }
962 if (j == n) {
963 cout << "couldn't find rank in the table (B)" << endl;
964 exit(1);
965 }
966 if (!chosen[j]) {
967 break;
968 }
969 }
970 bose_distance = i;
971
973
974 if (f_v) {
975 cout << "taking the minimum polynomials of { ";
976 for (i = 0; i < transversal_length; i++) {
977 cout << transversal[i] << " ";
978 }
979 cout << "}" << endl;
980 }
981
982 rank_of_irreducibles = NEW_OBJECTS(
983 ring_theory::longinteger_object, transversal_length);
984
985 for (i = 0; i < transversal_length; i++) {
986
987 // minimum_polynomial(h1, ai, p, f_vv);
989 beta_rk_table[transversal[i]], rk, p, f_vv);
990 FX.create_object_by_rank_longinteger(h1, rk, __FILE__, __LINE__, verbose_level - 2);
991 if (f_vv) {
992 cout << "minimal polynomial of \\beta^" << transversal[i] << " is ";
993 FX.print_object(h1, cout);
994 cout << " of rank " << rk << endl;
995 }
996 rk.assign_to(rank_of_irreducibles[i]);
997 FX.mult(g, h1, h2, verbose_level - 1);
998 FX.assign(h2, g, verbose_level);
999 }
1000
1001 Fq.delete_object(c);
1002 Fq.delete_object(beta);
1003 Fq.delete_object(beta_i);
1004 FX.delete_object(h1);
1005 FX.delete_object(h2);
1006 FX.delete_object(m);
1007 FREE_OBJECTS(beta_rk_table);
1008 FREE_int(chosen);
1009 //delete [] transversal;
1010 if (f_v) {
1011 cout << "BCH(" << n << "," << p << ","
1012 << designed_distance << ") = ";
1013 FX.print_object(g, cout);
1014 cout << " bose_distance = " << bose_distance << endl;
1015 }
1016}
1017
1019 ring_theory::unipoly_object a, int *&genma, int n, int &k,
1020 int verbose_level)
1021{
1022 int f_v = (verbose_level >= 1);
1023 int *r = (int *) a;
1024 int d = r[0];
1025 int *A = r + 1;
1026
1027 int i, j, x;
1028
1029 k = n - d;
1030 if (k < 0) {
1031 cout << "coding_theory_domain::compute_generator_matrix k < 0" << endl;
1032 exit(1);
1033 }
1034 genma = NEW_int(k * n);
1035 for (i = 0; i < k * n; i++) {
1036 genma[i] = 0;
1037 }
1038 for (i = 0; i < k; i++) {
1039 for (j = 0; j <= d; j++) {
1040 x = A[j];
1041 genma[i * n + i + j] = x;
1042 }
1043 }
1044 if (f_v) {
1045 cout << "coding_theory_domain::compute_generator_matrix generator matrix:" << endl;
1046 Int_vec_print_integer_matrix(cout, genma, k, n);
1047 }
1048}
1049
1050
1051
1052void coding_theory_domain::make_BCH_codes(int n, int q, int t, int b, int f_dual, int verbose_level)
1053{
1054 int f_v = (verbose_level >= 1);
1055
1056 if (f_v) {
1057 cout << "coding_theory_domain::make_BCH_codes" << endl;
1058 }
1059
1060 char fname[1000];
1061 std::string fname_txt;
1062 std::string fname_csv;
1064 int *roots;
1065 int nb_roots;
1066 int i, j;
1067
1068 roots = NEW_int(t - 1);
1069 nb_roots = t - 1;
1070 for (i = 0; i < t - 1; i++) {
1071 j = NT.mod(b + i, n);
1072 roots[i] = j;
1073 }
1074 snprintf(fname, 1000, "BCH_%d_%d", n, t);
1075
1076 fname_txt.assign(fname);
1077 fname_txt.append(".txt");
1078 fname_csv.assign(fname);
1079 fname_csv.append(".csv");
1080
1081 cout << "roots: ";
1082 Int_vec_print(cout, roots, nb_roots);
1083 cout << endl;
1084
1086
1087 string dummy;
1088
1089 dummy.assign("");
1090
1091 Codes.make_cyclic_code(n, q, t, roots, nb_roots,
1092 FALSE /*f_poly*/, dummy /*poly*/, f_dual,
1093 fname_txt, fname_csv, verbose_level);
1094
1095 FREE_int(roots);
1096
1097 if (f_v) {
1098 cout << "coding_theory_domain::make_BCH_codes done" << endl;
1099 }
1100}
1101
1102
1103}}}
1104
1105
1106
1107
1108
1109
void print_polynomial(ring_theory::unipoly_domain &Fq, int degree, ring_theory::unipoly_object *coeffs)
void field_reduction(field_theory::finite_field *FQ, field_theory::finite_field *Fq, std::string &label, int m, int n, std::string &genma_text, int verbose_level)
void BCH_generator_polynomial(field_theory::finite_field *F, ring_theory::unipoly_object &g, int n, int designed_distance, int &bose_distance, int &transversal_length, int *&transversal, ring_theory::longinteger_object *&rank_of_irreducibles, int verbose_level)
void make_BCH_codes(int n, int q, int t, int b, int f_dual, int verbose_level)
void print_polynomial_tight(std::ostream &ost, ring_theory::unipoly_domain &Fq, int degree, ring_theory::unipoly_object *coeffs)
void generator_matrix_cyclic_code(field_theory::finite_field *F, int n, std::string &poly_coeffs, int verbose_level)
void make_cyclic_code(int n, int q, int t, int *roots, int nb_roots, int f_poly, std::string &poly, int f_dual, std::string &fname_txt, std::string &fname_csv, int verbose_level)
void compute_generator_matrix(ring_theory::unipoly_object a, int *&genma, int n, int &k, int verbose_level)
void make_BCH_code(int n, field_theory::finite_field *F, int d, field_theory::nth_roots *&Nth, ring_theory::unipoly_object &P, int verbose_level)
void finite_field_init(int q, int f_without_tables, int verbose_level)
void init_override_polynomial(int q, std::string &poly, int f_without_tables, int verbose_level)
the nth roots over Fq using an extension field
void init(finite_field *F, int n, int verbose_level)
Definition: nth_roots.cpp:62
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 int_matrix_write_csv(std::string &fname, int *M, int m, int n)
Definition: file_io.cpp:1300
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
int compare(longinteger_object &a, longinteger_object &b)
void add(longinteger_object &a, longinteger_object &b, longinteger_object &c)
void integral_division_by_int(longinteger_object &a, int b, longinteger_object &q, int &r)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void create(long int i, const char *file, int line)
domain of polynomials in one variable over a finite field
Definition: ring_theory.h:691
void add(unipoly_object a, unipoly_object b, unipoly_object &c)
void power_int(unipoly_object &a, int n, int verbose_level)
void print_object_tight(unipoly_object p, std::ostream &ost)
void mult(unipoly_object a, unipoly_object b, unipoly_object &c, int verbose_level)
void power_longinteger(unipoly_object &a, longinteger_object &n, int verbose_level)
void create_object_by_rank_longinteger(unipoly_object &p, longinteger_object &rank, const char *file, int line, 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 rank_longinteger(unipoly_object p, longinteger_object &rank)
void minimum_polynomial_factorring_longinteger(longinteger_object &alpha, longinteger_object &rk_minpoly, int p, 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_OBJECTS(p)
Definition: foundations.h:652
#define Int_vec_print_integer_matrix(A, B, C, D)
Definition: foundations.h:690
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_OBJECT(type)
Definition: foundations.h:638
#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 NEW_OBJECTS(type, n)
Definition: foundations.h:639
#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