Orbiter 2022
Combinatorial Objects
global.cpp
Go to the documentation of this file.
1// global.cpp
2//
3// Anton Betten
4// 10.11.1999
5// moved from D2 to ORBI Nov 15, 2007
6
8#include "discreta.h"
9
10using namespace std;
11
12
13namespace orbiter {
14namespace layer2_discreta {
15
16
17
18#undef DEBUG_CALLOC_NOBJECTS_PLUS_LENGTH
19#undef TONELLI_VERBOSE
20#undef DEBUG_INVERT_MOD_INTEGER
21
22
23
24/**** global variables ***/
25
26
27// printing_mode gl_printing_mode = printing_mode_ascii;
28// int printing_mode = PRintING_MODE_ASCII;
29
30#define MAX_PRINTING_MODE_STACK 100
31
33static enum printing_mode_enum printing_mode_stack[MAX_PRINTING_MODE_STACK];
34
35
36const char *discreta_home = NULL;
37const char *discreta_arch = NULL;
38
39
40/**** global functions ***/
41
42static void Binomial_using_table(int n, int k, discreta_matrix & T, discreta_base & res);
43
45{
46 int verbose_level = 0;
47 int f_v = (verbose_level >= 1);
48 char str[1000];
50
51 discreta_home = getenv("DISCRETA_HOME");
52 if (discreta_home == NULL) {
53 if (f_v) {
54 cout << "discreta_init WARNING: $DISCRETA_HOME not set !" << endl;
55 }
56 discreta_home = ".";
57 }
58 discreta_arch = getenv("DISCRETA_ARCH");
59 if (discreta_arch == NULL) {
60 if (f_v) {
61 cout << "discreta_init WARNING: $DISCRETA_ARCH not set !" << endl;
62 }
63 discreta_arch = ".";
64 }
65 if (discreta_home) {
66
67 strcpy(str, discreta_home);
68 strcat(str, "/lib/this_is");
69
70#if 1
71 if (Fio.file_size(str) <= 0) {
72 if (f_v) {
73 cout << "discreta_init WARNING: can't find my library (DISCRETA_HOME/lib) !" << endl;
74 }
75 }
76#endif
77 }
78 database_init(verbose_level);
79}
80
82{
83 discreta_base *p = new( operator new(sizeof(discreta_base)) ) discreta_base;
84
85 p->c_kind(k);
86 return p;
87}
88
90{
91 operator delete(p); /* free(p); */
92}
93
95{
96 int i;
98
99 p = (discreta_base *) operator new(n * sizeof(discreta_base));
100 if (p == NULL) {
101 cout << "calloc_nobjects no memory" << endl;
102 exit(1);
103 }
104 for (i = 0; i < n; i++) {
105 new( &p[i] ) discreta_base;
106 p[i].c_kind(k);
107 }
108 return p;
109}
110
112{
113 int i;
114
115 for (i = 0; i < n; i++) {
116 p[i].freeself();
117 }
118 operator delete(p);
119}
120
122{
123 int i;
124 discreta_base *p;
125
126#ifdef DEBUG_CALLOC_NOBJECTS_PLUS_LENGTH
127 cout << "calloc_nobjects_plus_length n=" << n << endl;
128#endif
129 p = (discreta_base *) operator new((n + 1) * sizeof(discreta_base));
130 if (p == NULL) {
131 cout << "calloc_nobjects_plus_length no memory" << endl;
132 exit(1);
133 }
134 p++;
135 for (i = 0; i < n; i++) {
136 new( &p[i] ) discreta_base;
137 p[i].c_kind(k);
138 }
139 p[-1].c_kind(INTEGER);
140 p[-1].m_i_i(n);
141 return p;
142}
143
145{
146 int i, n;
147
148 n = p[-1].s_i_i();
149 if (n < 0) {
150 cout << "free_nobjects_plus_length length = " << n << " < 0" << endl;
151 }
152#ifdef DEBUG_CALLOC_NOBJECTS_PLUS_LENGTH
153 cout << "free_nobjects_plus_length n=" << n << endl;
154#endif
155 for (i = 0; i < n; i++) {
156 p[i].freeself();
157 }
158 p[-1].freeself();
159 p--;
160 operator delete(p);
161}
162
164{
165 int i;
166 discreta_base *p;
167
168 p = (discreta_base *) operator new((m * n + 2) * sizeof(discreta_base));
169 if (p == NULL) {
170 cout << "calloc_m_times_n_objects no memory" << endl;
171 exit(1);
172 }
173 p++;
174 p++;
175 for (i = 0; i < m * n; i++) {
176 new( &p[i] ) discreta_base;
177 p[i].c_kind(k);
178 }
179 p[-2].c_kind(INTEGER);
180 p[-2].m_i_i(m);
181 p[-1].c_kind(INTEGER);
182 p[-1].m_i_i(n);
183 return p;
184}
185
187{
188 int i, m, n;
189
190 m = p[-2].s_i_i();
191 n = p[-1].s_i_i();
192 if (m < 0) {
193 cout << "free_m_times_n_objects m = " << m << " < 0" << endl;
194 }
195 if (n < 0) {
196 cout << "free_m_times_n_objects n = " << n << " < 0" << endl;
197 }
198 for (i = 0; i < m * n; i++) {
199 p[i].freeself();
200 }
201 p[-2].freeself();
202 p[-1].freeself();
203 p--;
204 p--;
205 operator delete(p);
206}
207
208void printobjectkind(ostream& ost, kind k)
209{
210 ost << kind_ascii(k);
211}
212
213const char *kind_ascii(kind k)
214{
215 switch(k) {
216 case BASE: return "BASE";
217 case INTEGER: return "INTEGER";
218 case VECTOR: return "VECTOR";
219 case NUMBER_PARTITION: return "NUMBER_PARTITION";
220 case PERMUTATION: return "PERMUTATION";
221
222 case MATRIX: return "MATRIX";
223
224 case LONGINTEGER: return "LONGINTEGER";
225 //case SUBGROUP_LATTICE: return "SUBGROUP_LATTICE";
226 //case SUBGROUP_ORBIT: return "SUBGROUP_ORBIT";
227
228 case MEMORY: return "MEMORY";
229
230 case HOLLERITH: return "HOLLERITH";
231 case DATABASE: return "DATABASE";
232 case BTREE: return "BTREE";
233
234 case PERM_GROUP: return "PERM_GROUP";
235 case BT_KEY: return "BT_KEY";
236
237 case DESIGN_PARAMETER: return "DESIGN_PARAMETER";
238
239 //case GROUP_SELECTION: return "GROUP_SELECTION";
240 case UNIPOLY: return "UNIPOLY";
241
242 case DESIGN_PARAMETER_SOURCE: return "DESIGN_PARAMETER_SOURCE";
243 //case SOLID: return "SOLID";
244
245 case BITMATRIX: return "BITMATRIX";
246 //case PC_PRESENTATION: return "PC_PRESENTATION";
247 //case PC_SUBGROUP: return "PC_SUBGROUP";
248 //case GROUP_WORD: return "GROUP_WORD";
249 //case GROUP_TABLE: return "GROUP_TABLE";
250 //case ACTION: return "ACTION";
251 //case GEOMETRY: return "GEOMETRY";
252 default: return "unknown kind";
253 }
254}
255
257{
258 switch(k) {
259 case vector_entries: return "vector_entries";
260 case vector_positions: return "vector_positions";
261 default: return "unknown action_kind";
262 }
263}
264
266{
267 uint_4 z;
268
269 z = x;
270 x = y;
271 y = z;
272}
273
274
275ostream& operator<<(ostream& ost, discreta_base& p)
276{
277 // cout << "operator<< starting\n";
278 p.print(ost);
279 // cout << "operator<< finished\n";
280 return ost;
281};
282
283
284
285int invert_mod_integer(int i, int p)
286{
287 integer a, b;
288
289#ifdef DEBUG_INVERT_MOD_INTEGER
290 cout << "invert_mod_integer i=" << i << ", p=" << p << endl;
291#endif
292 a.m_i(i);
293 b.m_i(p);
294 a.power_int_mod(p - 2, b);
295#ifdef DEBUG_INVERT_MOD_INTEGER
296 cout << "i^-1=" << a.s_i() << endl;
297#endif
298 return a.s_i();
299
300#if 0
301 with ww(GFp, p);
302 integer x;
303
304#ifdef DEBUG_INVERT_MOD_INTEGER
305 cout << "invert_mod_integer i=" << i << ", p=" << p << endl;
306#endif
307 x.m_i(i);
308 x.invert();
309#ifdef DEBUG_INVERT_MOD_INTEGER
310 cout << "i^-1=" << x.s_i() << endl;
311#endif
312 return x.s_i();
313#endif
314}
315
316
317int remainder_mod(int i, int n)
318{
319 if (i < 0) {
320 i *= -1;
321 i %= n;
322 if (i == 0)
323 return 0;
324 else
325 return n - i;
326 }
327 return i % n;
328}
329
330void factor_integer(int n, Vector& primes, Vector& exponents)
331//Factors the integer $n = \prod_{i=1}^r p_i^{e_i}$.
332//The vector primes holds the primes $p_i$,
333//the vector exponents holds the $e_i$.
334{
335 int d, last_prime = 2, l;
337
338 if (n == 0) {
339 cout << "factor_integer n == 0" << endl;
340 exit(1);
341 }
342 if (n == 1) {
343 primes.m_l(0);
344 exponents.m_l(0);
345 return;
346 }
347 d = NT.sp_ge(n, last_prime);
348 primes.m_l(1);
349 exponents.m_l(1);
350 l = 1;
351 primes.m_ii(0, d);
352 exponents.m_ii(0, 1);
353 last_prime = d;
354 n /= d;
355 while (n != 1) {
356 d = NT.sp_ge(n, last_prime);
357 // cout << "n=" << n << " last_prime=" << last_prime << " next_prime=" << d << endl;
358 if (d == last_prime) {
359 exponents.m_ii(l - 1, exponents.s_ii(l - 1) + 1);
360 }
361 else {
362 primes.inc();
363 exponents.inc();
364 primes.m_ii(l, d);
365 exponents.m_ii(l, 1);
366 l++;
367 last_prime = d;
368 }
369 n /= d;
370 }
371}
372
373void discreta_print_factorization(Vector& primes, Vector& exponents, ostream &o)
374//Prints the factorization.
375{
376 int i, p, e, l;
377
378 l = primes.s_l();
379 if (l != exponents.s_l()) {
380 cout << "print_factorization l != exponents.s_l()" << endl;
381 exit(1);
382 }
384 for (i = 0; i < l; i++) {
385 p = primes.s_ii(i);
386 e = exponents.s_ii(i);
387 if (e > 1) {
388 o << p << "^";
389 if (e >= 10)
390 o << "{" << e << "}";
391 else
392 o << e;
393 }
394 else
395 o << p;
396 if (i < l - 1)
397 o << "\\cdot ";
398 }
399 }
400 else {
401 for (i = 0; i < l; i++) {
402 p = primes.s_ii(i);
403 e = exponents.s_ii(i);
404 if (e > 1)
405 o << p << "^" << e;
406 else
407 o << p;
408 if (i < l)
409 o << " ";
410 }
411 }
412}
413
415//Prints the factorization.
416{
417 int i, p, e, l;
418
419 l = primes.s_l();
420 if (l != exponents.s_l()) {
421 cout << "print_factorization l != exponents.s_l()" << endl;
422 exit(1);
423 }
424 h.init("");
426 for (i = 0; i < l; i++) {
427 p = primes.s_ii(i);
428 e = exponents.s_ii(i);
429 if (e > 1) {
430 h.append_i(p);
431 h.append("^");
432 if (e >= 10) {
433 h.append("{");
434 h.append_i(e);
435 h.append("}");
436 }
437 else {
438 h.append_i(e);
439 }
440 }
441 else
442 h.append_i(p);
443 if (i < l - 1)
444 h.append("\\cdot ");
445 }
446 }
447 else {
448 for (i = 0; i < l; i++) {
449 p = primes.s_ii(i);
450 e = exponents.s_ii(i);
451 if (e > 1) {
452 h.append_i(p);
453 h.append("^");
454 h.append_i(e);
455 }
456 else
457 h.append_i(p);
458 if (i < l)
459 h.append(" ");
460 }
461 }
462}
463
464int nb_primes(int n)
465//Returns the number of primes in the prime factorization
466//of $n$ (including multiplicities).
467{
468 int i = 0;
469 int d;
471
472 if (n < 0)
473 n = -n;
474 while (n != 1) {
475 d = NT.smallest_primedivisor(n);
476 i++;
477 n /= d;
478 }
479 return i;
480}
481
482int factor_if_prime_power(int n, int *p, int *e)
483//Computes $p$ and $e$ with $n=p^e$.
484//If $n$ is not a prime power, FALSE is returned.
485{
486 Vector vp, ve;
487
488 factor_integer(n, vp, ve);
489 if (vp.s_l() != 1) {
490 return FALSE;
491 }
492 *p = vp.s_ii(0);
493 *e = ve.s_ii(0);
494 return TRUE;
495}
496
497int Euler(int n)
498//Computes Eulers $\varphi$-function for $n$.
499//Uses the prime factorization of $n$. before: eulerfunc
500{
501 Vector p, e;
502 int i, k, p1, e1, l;
504
505 factor_integer(n, p, e);
506 k = 1;
507 l = p.s_l();
508 for (i = 0; i < l; i++) {
509 p1 = p.s_ii(i);
510 e1 = e.s_ii(i);
511 if (e1 > 1)
512 k *= NT.i_power_j(p1, e1 - 1);
513 k *= (p1 - 1);
514 }
515 return k;
516}
517
518int Moebius(int i)
519//Computes the number-theoretic $\mu$ (= moebius) function of $i$. before: moebius.
520{
521 Vector vp, ve;
522 int j, a, l;
523
524 factor_integer(i, vp, ve);
525 l = vp.s_l();
526 for (j = 0; j < l; j++) {
527 a = ve.s_ii(j);
528 if (a > 1)
529 return 0;
530 }
531 if (EVEN(l))
532 return 1;
533 else
534 return -1;
535}
536
537
538int NormRemainder(int a, int m)
539//absolute smallest remainder: Computes $r$ such that
540//$a \equiv r$ mod $m$ and $- \frac{m}{2} < r \le \frac{m}{2}$ holds.
541{
542 int q, m0, m1, m_halbe;
543
544 if (m == 0) {
545 cout << "NormRemainder m == 0" << endl;
546 exit(1);
547 }
548 m0 = m;
549 m_halbe = m0 >> 1;
550 q = a / m0;
551 m1 = a - q * m0;
552 if (m1 > m_halbe)
553 m1 -= m0;
554 if (ODD(m0)) {
555 if (m1 < - m_halbe)
556 m1 += m0;
557 }
558 else {
559 if (m1 <= - m_halbe)
560 m1 += m0;
561 }
562 return m1;
563}
564
565int log2(int n)
566//returns $\log_2(n)$
567{
568 int i;
569
570 if (n <= 0) {
571 cout << "log2 n <= 0" << endl;
572 exit(1);
573 }
574 for (i = -1; n > 0; i++) {
575 n >>= 1;
576 }
577 return i;
578}
579
580int sqrt_mod(int a, int p, int verbose_level)
581// solves x^2 = a mod p. Returns x
582{
583 int f_v = (verbose_level >= 1);
584 int a1, x;
585
586 if (f_v) {
587 cout << "sqrt_mod a=" << a << " p=" << p << endl;
588 }
589 a1 = a % p;
590 if (p < 300) {
591 if (a1 < 0) {
592 a1 = - a1;
593 a1 = a1 % p;
594 if (a1) {
595 a1 = p - a1;
596 }
597 }
598 for (x = 0; x < p; x++) {
599 if ((x * x) % p == a1) {
600 if (f_v) {
601 cout << "sqrt_mod a=" << a << " p=" << p << " done" << endl;
602 }
603 return x;
604 }
605 }
606 cout << "sqrt_mod() a not a quadratic residue" << endl;
607 cout << "a = " << a << " p=" << p << endl;
608 exit(1);
609 }
610 else {
611 x = sqrt_mod_involved(a1, p, verbose_level);
612 longinteger X, Y, P;
613
614 X.homo_z(x);
615 P.homo_z(p);
616 Y.mult_mod(X, X, P);
617 if (Y.modp(p) != a1) {
618 cout << "sqrt_mod error in sqrt_mod_invoved" << endl;
619 exit(1);
620 }
621 if (f_v) {
622 cout << "sqrt_mod a=" << a << " p=" << p << " done" << endl;
623 }
624 return x;
625 }
626}
627
628int sqrt_mod_involved(int a, int p, int verbose_level)
629// solves x^2 = a mod p. Returns x
630{
631 int f_v = (verbose_level >= 1);
632 longinteger P, m1;
633 longinteger A, X, a2, a4, b, X2;
634 int round;
636
637 if (f_v) {
638 cout << "sqrt_mod_involved" << endl;
639 }
640 A.homo_z(a);
641 P.homo_z(p);
642 if (p % 4 == 3) {
643 X = A;
644 X.power_int_mod((p + 1) >> 2, P);
645 return X.s_i();
646 }
647 if (p % 8 == 5) {
648 b = A;
649 b.power_int_mod((p - 1) >> 2, P);
650 // cout << "A = " << A << endl;
651 // cout << "b = A^(p-1)/4=" << b << endl;
652 if (b.is_one()) {
653 X = A;
654 X.power_int_mod((p + 3) >> 3, P);
655 if (f_v) {
656 cout << "sqrt_mod_involved done" << endl;
657 }
658 return X.s_i();
659 }
660 m1 = P;
661 m1.dec();
662 if (b.compare_with(m1) == 0) {
663 a2.add_mod(A, A, P);
664 a4.add_mod(a2, a2, P);
665 a4.power_int_mod((p - 5) >> 3, P);
666 X.mult_mod(a2, a4, P);
667 if (f_v) {
668 cout << "sqrt_mod_involved done" << endl;
669 }
670 return X.s_i();
671 }
672 else {
673 cout << "sqrt_mod() p % 8 = 5 and power neq +-1" << endl;
674 cout << "power = " << b << endl;
675 cout << "-1 = " << m1 << endl;
676 exit(1);
677 }
678 }
679 // now p % 8 == 1
680 // Tonelli / Shanks algorithm:
681 int n, r = 0, q, e, m;
682 longinteger Z, N, Y, B, T, d, mP, AB, Ypower, Bpower;
683
684#ifdef TONELLI_VERBOSE
685 cout << "sqrt_mod(), Tonelli / Shanks:\n";
686#endif
687 q = p - 1;
688 e = 0;
689 while (EVEN(q)) {
690 q >>= 1;
691 e++;
692 }
693#ifdef TONELLI_VERBOSE
694 cout << "p - 1 = 2^" << e << " * " << q << endl;
695#endif
696
697#if 0
698 do {
699 n = (int)(((double)rand() * (double)p / RAND_MAX)) % p;
700 r = Legendre(n, p, verbose_level - 1);
701 } while (r >= 0);
702#else
703 for (n = 1; n < p - 1; n++) {
704 r = NT.Legendre(n, p, verbose_level - 1);
705 if (r == -1) {
706 break;
707 }
708 }
709#endif
710
711#ifdef TONELLI_VERBOSE
712 cout << "n=" << n << " p=" << p << " Legendre(n,p)=" << r<< endl;
713#endif
714 cout << "n=" << n << " p=" << p << " Legendre(n,p)=" << r<< endl;
715 N.homo_z(n);
716 Z = N;
717 Z.power_int_mod(q, P);
718 Y = Z;
719 r = e;
720 X = A;
721 X.power_int_mod((q - 1) >> 1, P);
722 d.mult_mod(X, X, P);
723 B.mult_mod(A, d, P);
724 X.mult_mod(A, X, P);
725#ifdef TONELLI_VERBOSE
726 cout << "initialization:\n";
727#endif
728 round = 0;
729 while (TRUE) {
730#ifdef TONELLI_VERBOSE
731 cout << "Z=" << Z << endl;
732 cout << "Y=" << Y << endl;
733 cout << "r=" << r << endl;
734 cout << "X=" << X << endl;
735 cout << "B=" << B << endl;
736#endif
737
738
739 X2.mult_mod(X, X, P);
740 AB.mult_mod(A, B, P);
741 Ypower = Y;
742 Ypower.power_int_mod(1 << (r - 1), P);
743 Bpower = B;
744 Bpower.power_int_mod(1 << (r - 1), P);
745
746 d = Y;
747 d.power_int_mod(1 << (r - 1), P);
748 mP = P;
749 mP.negate();
750 d += mP;
751 if (!d.is_m_one()) {
752 cout << "loop invariant violated: Y^{2^{r-1}} != -1" << endl;
753 exit(1);
754 }
755
756 d.mult_mod(A, B, P);
757 //X2.mult_mod(X, X, P);
758 if (d.compare_with(X2) != 0) {
759 cout << "loop invariant violated: ab != x^2" << endl;
760 cout << "ab=" << d << endl;
761 cout << "x^2=" << X2 << endl;
762 exit(1);
763 }
764
765 d = B;
766 d.power_int_mod(1 << (r - 1), P);
767 if (!d.is_one()) {
768 cout << "loop invariant violated: B^{2^{r-1}} != 1" << endl;
769 exit(1);
770 }
771
772
773 if (B.modp(p) == 1) {
774 m = -1;
775 }
776 else {
777 for (m = 1; ; m++) {
778 d = B;
779 d.power_int_mod(1 << m, P);
780 if (d.is_one())
781 break;
782 if (m >= r) {
783 cout << "sqrt_mod(), Tonelli / Shanks:" << endl;
784 cout << "error: a is not a quadratic residue mod p" << endl;
785 exit(1);
786 }
787 }
788 }
789
790
791 cout << round << " & " << A << " & " << B << " & " << X << " & "
792 << X2 << " & " << Y << " & " << r << " & " << AB
793 << " & " << Ypower << " & " << Bpower << " & ";
794
795 if (m == -1) {
796 cout << " & & & & \\\\" << endl;
797 }
798 else {
799 cout << m;
800 }
801
802 //cout << "m=" << m << endl;
803
804 if (m == -1) {
805 if (f_v) {
806 cout << "sqrt_mod_involved done" << endl;
807 }
808 return X.s_i();
809 }
810
811#ifdef TONELLI_VERBOSE
812 cout << "m=" << m << endl;
813#endif
814 T = Y;
815 T.power_int_mod(1 << (r - m - 1), P);
816 Y.mult_mod(T, T, P);
817 r = m;
818 X.mult_mod(X, T, P);
819 B.mult_mod(B, Y, P);
820
821 cout << " & " << Y << " & " << X << " & " << B << " & " << r;
822 cout << "\\\\" << endl;
823 round++;
824 }
825 if (f_v) {
826 cout << "sqrt_mod_involved done" << endl;
827 }
828}
829
830void html_head(ostream& ost, char *title_long, char *title_short)
831{
832 ost << "<html>\n";
833 ost << "<head>\n";
834 ost << "<title>\n";
835 ost << title_short << "\n";
836 ost << "</title>\n";
837 ost << "</head>\n";
838
839 ost << "<body>\n";
840 ost << "<h1>\n";
841 ost << title_long << "\n";
842 ost << "</h1>\n";
843 ost << "<hr>\n";
844}
845
846void html_foot(ostream& ost)
847{
848 hollerith h;
849
851 ost << "<p><hr><p>\n";
852 ost << "created: " << h.s() << endl;
853 ost << "</body>\n";
854 ost << "</html>\n";
855}
856
857void sieve(Vector &primes, int factorbase, int verbose_level)
858{
859 int f_v = (verbose_level >= 1);
860 int i, from, to, l, unit_size = 1000;
861
862 primes.m_l(0);
863 for (i = 0; ; i++) {
864 from = i * unit_size + 1;
865 to = from + unit_size - 1;
866 sieve_primes(primes, from, to, factorbase, FALSE);
867 l = primes.s_l();
868 cout << "[" << from << "," << to
869 << "], total number of primes = "
870 << l << endl;
871 if (l >= factorbase)
872 break;
873 }
874
875 if (f_v) {
876 print_intvec_mod_10(primes);
877 }
878}
879
880void sieve_primes(Vector &v, int from, int to, int limit, int verbose_level)
881{
882 int f_v = (verbose_level >= 1);
883 int x, y, l, k, p, f_prime;
884
885 l = v.s_l();
886 if (ODD(from))
887 x = from;
888 else
889 x = from + 1;
890 for (; x <= to; x++, x++) {
891 if (x <= 1)
892 continue;
893 f_prime = TRUE;
894 for (k = 0; k < l; k++) {
895 p = v[k].s_i_i();
896 y = x / p;
897 // cout << "x=" << x << " p=" << p << " y=" << y << endl;
898 if ((x - y * p) == 0) {
899 f_prime = FALSE;
900 break;
901 }
902 if (y < p)
903 break;
904#if 0
905 if ((x % p) == 0)
906 break;
907#endif
908 }
909 if (!f_prime)
910 continue;
911 if (nb_primes(x) != 1) {
912 cout << "error: " << x << " is not prime!\n";
913 }
914 v.append_integer(x);
915 if (f_v) {
916 cout << v.s_l() << " " << x << endl;
917 }
918 l++;
919 if (l >= limit)
920 return;
921 }
922}
923
925{
926 int i, l;
927
928 l = v.s_l();
929 for (i = 0; i < l; i++) {
930 cout << v.s_ii(i) << " ";
931 if ((i + 1) % 10 == 0)
932 cout << endl;
933 }
934 cout << endl;
935}
936
937
938void stirling_second(int n, int k, int f_ordered,
939 discreta_base &res, int verbose_level)
940// number of set partitions of an n-set with exactly k classes
941{
942 int f_v = (verbose_level >= 1);
943 // cout << "stirling_second() partition is currently disabled" << endl;
944 discreta_base a, b, c;
946
947 if (n == 0) {
948 if (k == 0) {
949 res.m_i_i(1);
950 return;
951 }
952 else {
953 res.m_i_i(0);
954 return;
955 }
956 }
957 if (k == 0) {
958 res.m_i_i(0);
959 return;
960 }
961 if (k > n) {
962 res.m_i_i(0);
963 return;
964 }
965
966 if (f_v) {
967 cout << "stirling_second";
968 if (f_ordered) {
969 cout << " ordered ";
970 }
971 cout << "(" << n << ", " << k << ")" << endl;
972 }
973 a.m_i_i(0);
974 p.first_into_k_parts(n, k);
975 do {
976 if (f_v) {
977 cout << p << endl;
978 }
979 p.multinomial_ordered(b, f_v);
980 a += b;
981 } while (p.next_into_k_parts(n, k));
982 if (!f_ordered) {
983 b.factorial(k);
985 c.swap(a);
986 }
987 a.swap(res);
988 if (f_v) {
989 cout << "stirling_second";
990 if (f_ordered) {
991 cout << " ordered ";
992 }
993 cout << "(" << n << ", " << k << ") = " << res << endl;
994 }
995}
996
997void stirling_first(int n, int k, int f_signless,
998 discreta_base &res, int verbose_level)
999// $(-1)^{n+k} \cdot$ number of elements in $\Sym_n$ with exactly k cycles
1000{
1001 int f_v = (verbose_level >= 1);
1002 // cout << "stirling_first() partition is currently disabled" << endl;
1003 discreta_base a, b, c;
1005 int l, x, ax;
1006
1007 if (n == 0) {
1008 if (k == 0) {
1009 res.m_i_i(1);
1010 return;
1011 }
1012 else {
1013 res.m_i_i(0);
1014 return;
1015 }
1016 }
1017 if (k == 0) {
1018 res.m_i_i(0);
1019 return;
1020 }
1021 if (k > n) {
1022 res.m_i_i(0);
1023 return;
1024 }
1025
1026 if (f_v) {
1027 cout << "stirling_first";
1028 if (f_signless) {
1029 cout << " signless ";
1030 }
1031 cout << "(" << n << ", " << k << ")" << endl;
1032 }
1033 a.m_i_i(0);
1034 p.first_into_k_parts(n, k);
1035 do {
1036 if (f_v) {
1037 cout << p << endl;
1038 }
1039 p.multinomial_ordered(b, f_v);
1040
1041
1042 l = p.s_l();
1043 for (x = 1; x <= l; x++) {
1044 ax = p[x - 1];
1045 if (ax == 0)
1046 continue;
1047 c.factorial(x - 1);
1048 c.power_int(ax);
1049 b *= c;
1050 }
1051
1052 a += b;
1053
1054 } while (p.next_into_k_parts(n, k));
1055
1056 b.factorial(k);
1058
1059 if (!f_signless) {
1060 if (ODD(n + k))
1061 c.negate();
1062 }
1063
1064 res = c;
1065 if (f_v) {
1066 cout << "stirling_first";
1067 if (f_signless) {
1068 cout << " signless ";
1069 }
1070 cout << "(" << n << ", " << k << ") = " << res << endl;
1071 }
1072}
1073
1074void Catalan(int n, Vector &v, int verbose_level)
1075{
1076 int f_v = (verbose_level >= 1);
1077 int i;
1078
1079 v.m_l_n(n + 1);
1080 v[0].m_i_i(1);
1081 v[1].m_i_i(1);
1082 for (i = 2; i <= n; i++) {
1083 Catalan_n(i, v, v[i], f_v);
1084 }
1085}
1086
1087void Catalan_n(int n, Vector &v, discreta_base &res, int verbose_level)
1088{
1089 int f_v = (verbose_level >= 1);
1090 int i;
1091 discreta_base a, b;
1092
1093 a.m_i_i(0);
1094 for (i = 1; i <= n; i++) {
1095 b = v[i - 1];
1096 b *= v[n - i];
1097 a += b;
1098 }
1099 if (f_v) {
1100 cout << "Catalan_n(" << n << ")=" << a << endl;
1101 }
1102 a.swap(res);
1103}
1104
1105void Catalan_nk_matrix(int n, discreta_matrix &Cnk, int verbose_level)
1106{
1107 //int f_v = (verbose_level >= 1);
1108 int i, k;
1109 discreta_base a;
1110
1111 Catalan_nk_star_matrix(n, Cnk, verbose_level);
1112 for (k = n; k > 0; k--) {
1113 for (i = 0; i <= n; i++) {
1114 a = Cnk[i][k - 1];
1115 a.negate();
1116 Cnk[i][k] += a;
1117 }
1118 }
1119}
1120
1121void Catalan_nk_star_matrix(int n, discreta_matrix &Cnk, int verbose_level)
1122{
1123 //int f_v = (verbose_level >= 1);
1124 int i, k;
1125
1126 Cnk.m_mn_n(n + 1, n + 1);
1127
1128 Cnk[0][0].m_i_i(1);
1129 for (k = 1; k <= n; k++) {
1130 Cnk[0][k].m_i_i(1);
1131 }
1132
1133 for (k = 1; k <= n; k++) {
1134 Cnk[1][k].m_i_i(1);
1135 }
1136
1137
1138 for (i = 2; i <= n; i++) {
1139 Cnk[i][1].m_i_i(1);
1140 for (k = 2; k <= n; k++) {
1141 Catalan_nk_star(i, k, Cnk, Cnk[i][k], verbose_level - 1);
1142 }
1143 }
1144}
1145
1146void Catalan_nk_star(int n, int k, discreta_matrix &Cnk, discreta_base &res, int verbose_level)
1147{
1148 int f_v = (verbose_level >= 1);
1149 int i;
1150 discreta_base a, b;
1151
1152 a.m_i_i(0);
1153 for (i = 0; i <= n - 1; i++) {
1154 b = Cnk[i][k - 1];
1155 b *= Cnk[n - i - 1][k];
1156 a += b;
1157 }
1158 if (f_v) {
1159 cout << "Catalan_nk_star(" << n << ", " << k << ")=" << a << endl;
1160 }
1161 a.swap(res);
1162}
1163
1164
1166// Computes ${n \choose k}$ into res as an {\em object}.
1167// This function uses a recursion formula.
1168{
1169 discreta_base n1, res1, k1, tmp;
1170
1171 if (k < 0) {
1172 cout << "N_choose_K(): k < 0" << endl;
1173 exit(1);
1174 }
1175 k1.m_i_i(k);
1176#if 0
1177 if (k1.gt(n)) {
1178 res->m_i_i(0);
1179 }
1180#endif
1181 if (k == 0) {
1182 res.m_i_i(1);
1183 return;
1184 }
1185 if (k == 1) {
1186 res = n;
1187 return;
1188 }
1189 if (n.is_one()) {
1190 res.m_i_i(1);
1191 return;
1192 }
1193 n1 = n;
1194 n1.dec();
1195 N_choose_K(n1, k - 1, res1);
1196 res1 *= n;
1197 // a = n * n_choose_k(n - 1, k - 1);
1198 k1.m_i_i(k);
1199 res1.integral_division_exact(k1, res);
1200 // b = a / k;
1201}
1202
1203void Binomial(int n, int k, discreta_base & n_choose_k)
1204// Computes binomial coefficients as {\em objects}
1205// so that large numbers are no problem.
1206// This function uses an internal table to remember all
1207// previously computed values. This may speed up
1208// those computations where Binomial() is heavily involved !
1209{
1210 static discreta_matrix *T = NULL;
1211 int tn, i, j;
1212
1213 if (k < 0) {
1214 cout << "Binomial(): k < 0" << endl;
1215 exit(1);
1216 }
1217 if (k > n) {
1218 n_choose_k.m_i_i(0);
1219 return;
1220 }
1221 if (n == 0 || k == 0 || k == n) {
1222 n_choose_k.m_i_i(1);
1223 return;
1224 }
1225 if (T == NULL) {
1227 T->m_mn_n(10, 10);
1228 }
1229 tn = T->s_m();
1230 if (tn < n + 1) {
1231 discreta_matrix TT;
1232
1233#if 0
1234 cout << "reallocating table of binomial coefficients to length " << n + 1 << endl;
1235#endif
1236 TT.m_mn_n(n + 1, n + 1);
1237 for (i = 0; i < tn; i++) {
1238 for (j = 0; j <= i; j++) {
1239 (*T)[i][j].swap(TT[i][j]);
1240 }
1241 }
1242 TT.swap(*T);
1243 }
1244 Binomial_using_table(n, k, *T, n_choose_k);
1245}
1246
1247static void Binomial_using_table(int n, int k, discreta_matrix & T, discreta_base & res)
1248{
1249 discreta_base tmp1, tmp2;
1250 int m;
1251
1252 m = T.s_m();
1253 if (m < n) {
1254 cout << "Binomial_using_table: m < n" << endl;
1255 exit(1);
1256 }
1257 if (k > n) {
1258 cout << "Binomial_using_table: k > n" << endl;
1259 exit(1);
1260 }
1261 if (k > (n >> 1) + 1) {
1262 Binomial_using_table(n, n - k, T, res);
1263 T[n][k] = T[n][n - k];
1264 return;
1265 }
1266 if (n == 0) {
1267 cout << "Binomial_using_table: n == 0" << endl;
1268 exit(1);
1269 }
1270 if (n < 0) {
1271 cout << "Binomial_using_table: n < 0" << endl;
1272 exit(1);
1273 }
1274 if (k < 0) {
1275 cout << "Binomial_using_table: k < 0" << endl;
1276 exit(1);
1277 }
1278 if (n == k) {
1279 T.m_iji(n, k, 1);
1280 res.m_i_i(1);
1281 return;
1282 }
1283 if (k == 0) {
1284 T.m_iji(n, k, 1);
1285 res.m_i_i(1);
1286 return;
1287 }
1288 if (k == 1) {
1289 T.m_iji(n, k, n);
1290 res.m_i_i(n);
1291 return;
1292 }
1293 if (T.s_ij(n, k).is_zero()) {
1294 Binomial_using_table(n - 1, k - 1, T, tmp1);
1295 Binomial_using_table(n - 1, k, T, tmp2);
1296 tmp1 += tmp2;
1297 res = tmp1;
1298 T[n][k] = tmp1;
1299 }
1300 else {
1301 res = T[n][k];
1302 }
1303}
1304
1305void Krawtchouk(int n, int q, int i, int j, discreta_base & a)
1306// $\sum_{u=0}^{\min(i,j)} (-1)^u \cdot (q-1)^{i-u} \cdot {j \choose u} \cdot $
1307// ${n - j \choose i - u}$
1308{
1309 int u, u_max;
1310 discreta_base b, c, d;
1311
1312 a.m_i_i(0);
1313 u_max = MINIMUM(i, j);
1314 for (u = 0; u <= u_max; u++) {
1315 b.m_i_i(q - 1);
1316 b.power_int(i - u);
1317 if (ODD(u))
1318 b.negate();
1319 Binomial(j, u, c);
1320 Binomial(n - j, i - u, d);
1321 b *= c;
1322 b *= d;
1323 a += b;
1324 }
1325}
1326
1327void tuple2_rank(int rank, int &i, int &j, int n, int f_injective)
1328//enumeration of 2-tuples $(i,j)$ (f_injective TRUE iff $i=j$ forbidden).
1329//this routine produces the tuple with number ``rank'' into $i$ and $j$.
1330//$n$ is the number of points $1 \le i,j \le n$.
1331{
1332 int a;
1333
1334 if (f_injective) {
1335 a = rank % (n - 1);
1336 i = (rank - a) / (n - 1);
1337 if (a < i)
1338 j = a;
1339 else
1340 j = a + 1;
1341 }
1342 else {
1343 a = rank % n;
1344 i = (rank - a) / n;
1345 j = a;
1346 }
1347}
1348
1349int tuple2_unrank(int i, int j, int n, int f_injective)
1350//inverse function of tuple2_rank():
1351//returns the rank of a given tuple $(i,j)$.
1352{
1353 int rank;
1354
1355 if (f_injective) {
1356 rank = i * (n - 1);
1357 if (j < i)
1358 rank += j;
1359 else if (j == i) {
1360 cout << "tuple2_unrank() not injective !" << endl;
1361 exit(1);
1362 }
1363 else
1364 rank += j - 1;
1365 }
1366 else {
1367 rank = i * n + j;
1368 }
1369 return rank;
1370}
1371
1372
1373#include <string.h>
1374
1375void output_texable_string(ostream & ost, char *in)
1376{
1377 int i, l;
1378 char str[100], c;
1379
1380 l = strlen(in);
1381 for (i = 0; i < l; i++) {
1382 c = in[i];
1383 if (c == '_') {
1384 ost << "\\_";
1385 }
1386 else {
1387 str[0] = c;
1388 str[1] = 0;
1389 ost << str;
1390 }
1391 }
1392}
1393
1394void texable_string(char *in, char *out)
1395{
1396 int i, l;
1397 char str[100], c;
1398
1399 l = strlen(in);
1400 out[0] = 0;
1401 for (i = 0; i < l; i++) {
1402 c = in[i];
1403 if (c == '_') {
1404 strcat(out, "\\_");
1405 }
1406 else {
1407 str[0] = c;
1408 str[1] = 0;
1409 strcat(out, str);
1410 }
1411 }
1412}
1413
1414static int table_of_primes[] = {
1415 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
1416 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
1417 73, 79, 83, 89, 97 } ; // the first 25 primes
1418static int table_of_primes_len = 25;
1419
1421{
1422 int i;
1423
1424 if (n <= table_of_primes_len) {
1425 P.m_l(n);
1426 for (i = 0; i < n; i++) {
1427 P.m_ii(i, table_of_primes[i]);
1428 }
1429 }
1430 else {
1431 cout << "the_first_n_primes: n too large" << endl;
1432 exit(1);
1433 }
1434}
1435
1436#include <math.h>
1437
1438void midpoint_of_2(int *Px, int *Py, int i1, int i2, int idx)
1439{
1440 double x, y;
1441
1442 x = (double)(Px[i1] + Px[i2]) * 0.5;
1443 y = (double)(Py[i1] + Py[i2]) * 0.5;
1444 Px[idx] = (int) x;
1445 Py[idx] = (int) y;
1446}
1447
1448void midpoint_of_5(int *Px, int *Py, int i1, int i2, int i3, int i4, int i5, int idx)
1449{
1450 double x, y;
1451
1452 x = (double)(Px[i1] + Px[i2] + Px[i3] + Px[i4] + Px[i5]) * 0.2;
1453 y = (double)(Py[i1] + Py[i2] + Py[i3] + Py[i4] + Py[i5]) * 0.2;
1454 Px[idx] = (int) x;
1455 Py[idx] = (int) y;
1456}
1457
1458void ratio_int(int *Px, int *Py, int idx_from, int idx_to, int idx_result, double r)
1459{
1460 int dx, dy;
1461
1462 dx = (int)((double)(Px[idx_to] - Px[idx_from]) * r);
1463 dy = (int)((double)(Py[idx_to] - Py[idx_from]) * r);
1464 Px[idx_result] = Px[idx_from] + dx;
1465 Py[idx_result] = Py[idx_from] + dy;
1466}
1467
1468
1469#if 0
1470int nb_of_bits()
1471{
1472 return sizeof (uint) * 8;
1473}
1474
1475void bit_set(uint & g, int k)
1476{
1477 g |= (((uint) 1) << k);
1478}
1479
1480void bit_clear(uint & g, int k)
1481{
1482 g &= ~(((uint) 1) << k);
1483}
1484
1485int bit_test(uint & g, int k)
1486{
1487 return ( (g & (((uint) 1) << k)) ? TRUE : FALSE );
1488}
1489
1490void bitset2vector(uint g, Vector &v)
1491{
1492 int i = 0;
1493
1494 v.m_l(0);
1495 while (g != 0) {
1496 if (bit_test(g, 0)) {
1497 v.append_integer(i);
1498 }
1499 i++;
1500 g >>= 1;
1501 }
1502}
1503#endif
1504
1506// n is the projective dimension
1507{
1508 with ww(dom);
1509 int i, j, l;
1510 Vector v;
1512
1513 int qq = dom->order_int();
1514 int q = dom->order_subfield_int();
1515 l = Gg.nb_PG_elements(n, qq);
1516 p.m_l(l);
1517 v.m_l_n(n + 1);
1518 for (i = 0; i < l; i++) {
1519 v.PG_element_unrank(i);
1520 for (j = 0; j <= n; j++) {
1521 v[j].power_int(q);
1522 }
1523 v.PG_element_rank(j);
1524 p.m_ii(i, j);
1525 }
1526}
1527
1529// n is the dimension
1530{
1531 with ww(dom);
1532 int i, j, l;
1533 Vector v;
1535
1536 int qq = dom->order_int();
1537 int q = dom->order_subfield_int();
1538 l = Gg.nb_AG_elements(n, qq);
1539 p.m_l(l);
1540 v.m_l_n(n);
1541 for (i = 0; i < l; i++) {
1542 v.AG_element_unrank(i);
1543 for (j = 0; j < n; j++) {
1544 v[j].power_int(q);
1545 }
1546 v.AG_element_rank(j);
1547 p.m_ii(i, j);
1548 }
1549}
1550
1551void translation_in_AG(domain *dom, int n, int i,
1552 discreta_base & a, permutation &p)
1553{
1554 with ww(dom);
1555 int ii, j, l;
1556 Vector v;
1558
1559 int q = dom->order_int();
1560 l = Gg.nb_AG_elements(n, q);
1561 p.m_l(l);
1562 v.m_l_n(n);
1563 for (ii = 0; ii < l; ii++) {
1564 v.AG_element_unrank(ii);
1565 // cout << "ii=" << ii << " v=" << v;
1566 v[i] += a;
1567 v.AG_element_rank(j);
1568 p.m_ii(ii, j);
1569 // cout << " j=" << j << endl;
1570 }
1571}
1572
1574{
1575 if (printing_mode_stack_size == 0)
1576 return printing_mode_ascii;
1577 else
1578 return printing_mode_stack[printing_mode_stack_size - 1];
1579}
1580
1582{
1584 cout << "printing_mode() overflow in printing_mode stack" << endl;
1585 exit(1);
1586 }
1587 printing_mode_stack[printing_mode_stack_size++] = printing_mode;
1588}
1589
1591{
1592 if (printing_mode_stack_size == 0) {
1593 cout << "~printing_mode() underflow in printing_mode stack" << endl;
1594 exit(1);
1595 }
1597}
1598
1599void call_system(char *cmd)
1600{
1601 printf("executing: %s\n", cmd);
1602 system(cmd);
1603}
1604
1605void fill_char(void *v, int cnt, int c)
1606{
1607 char ch = (char)c;
1608 char *s;
1609
1610 s = (char *)v;
1611 cnt++;
1612 while (--cnt)
1613 *s++ = ch;
1614}
1615
1616#define HASH_PRIME ((int)(1 << 30)-1)
1617
1618int hash_int(int hash0, int a)
1619{
1620 int h = hash0;
1621
1622 do {
1623 h <<= 1;
1624 if (ODD(a)) {
1625 h++;
1626 }
1627 h = h % HASH_PRIME;
1628 a >>= 1;
1629 } while (a);
1630 return h;
1631}
1632
1633void queue_init(Vector &Q, int elt)
1634{
1635 Q.m_l(2);
1636 Q.m_ii(0, 1);
1637 Q[1].change_to_vector();
1638 Q[1].as_vector().m_l_n(1);
1639 Q[1].as_vector().m_ii(0, elt);
1640}
1641
1643{
1644 int elt, i, l, a;
1645 Vector &v = Q[1].as_vector();
1646
1647 l = Q.s_ii(0);
1648 if (l <= 0) {
1649 cout << "queue_get_and_remove_first_element() queue is empty" << endl;
1650 exit(1);
1651 }
1652 elt = v.s_ii(0);
1653 for (i = 0; i < l - 1; i++) {
1654 a = v.s_ii(i + 1);
1655 v.m_ii(i, a);
1656 }
1657 Q.m_ii(0, l - 1);
1658 return elt;
1659}
1660
1662{
1663 int l;
1664
1665 l = Q.s_ii(0);
1666 return l;
1667}
1668
1669void queue_append(Vector &Q, int elt)
1670{
1671 int l;
1672
1673 Vector &v = Q[1].as_vector();
1674 l = Q.s_ii(0);
1675 if (v.s_l() == l) {
1676 v.append_integer(elt);
1677 }
1678 else {
1679 v.m_ii(l, elt);
1680 }
1681 Q.m_ii(0, l + 1);
1682}
1683
1684void print_classification_tex(Vector &content, Vector &multiplicities)
1685{
1686 print_classification_tex(content, multiplicities, cout);
1687}
1688
1689void print_classification_tex(Vector &content, Vector &multiplicities, ostream& ost)
1690{
1691 int i, l;
1692
1693 l = content.s_l();
1694 // ost << "(";
1695 for (i = 0; i < l; i++) {
1696 ost << content[i];
1697 if (!multiplicities[i].is_one()) {
1698 ost << "^{" << multiplicities[i] << "}";
1699 }
1700 if (i < l - 1)
1701 ost << ",$ $";
1702 }
1703 // ost << ")";
1704}
1705
1706void perm2permutation(int *a, int n, permutation &p)
1707{
1708 int i;
1709
1710 p.m_l_n(n);
1711 for (i = 0; i < n; i++) {
1712 p.s_i(i) = a[i];
1713 }
1714}
1715
1716int Gauss_int(int *A, int f_special, int f_complete, int *base_cols,
1717 int f_P, int *P, int m, int n, int Pn,
1718 int q, int *add_table, int *mult_table,
1719 int *negate_table, int *inv_table, int verbose_level)
1720// returns the rank which is the number of entries in base_cols
1721// A is a m x n matrix,
1722// P is a m x Pn matrix (if f_P is TRUE)
1723{
1724 int f_v = (verbose_level >= 1);
1725 int rank, i, j, k, jj;
1726 int pivot, pivot_inv = 0, a, b, c, z, f;
1728
1729 if (f_v) {
1730 cout << "Gauss_int Gauss algorithm for matrix:" << endl;
1731 Int_vec_print_integer_matrix(cout, A, m, n);
1732 }
1733 i = 0;
1734 for (j = 0; j < n; j++) {
1735
1736 /* search for pivot element: */
1737 for (k = i; k < m; k++) {
1738 if (A[k * n + j]) {
1739 // pivot element found:
1740 if (k != i) {
1741 for (jj = j; jj < n; jj++) {
1742 Algo.int_swap(A[i * n + jj], A[k * n + jj]);
1743 }
1744 if (f_P) {
1745 for (jj = 0; jj < Pn; jj++) {
1746 Algo.int_swap(P[i * Pn + jj], P[k * Pn + jj]);
1747 }
1748 }
1749 }
1750 break;
1751 } // if != 0
1752 } // next k
1753
1754 if (k == m) // no pivot found
1755 continue; // increase j, leave i constant
1756
1757 if (f_v) {
1758 cout << "Gauss_int row " << i << " pivot in row " << k << " colum " << j << endl;
1759 }
1760
1761 base_cols[i] = j;
1762
1763 pivot = A[i * n + j];
1764 pivot_inv = inv_table[pivot];
1765 if (!f_special) {
1766 // make pivot to 1:
1767 for (jj = j; jj < n; jj++) {
1768 A[i * n + jj] = mult_table[A[i * n + jj] * q + pivot_inv];
1769 }
1770 if (f_P) {
1771 for (jj = 0; jj < Pn; jj++) {
1772 P[i * Pn + jj] = mult_table[P[i * Pn + jj] * q + pivot_inv];
1773 }
1774 }
1775 if (f_v) {
1776 cout << "Gauss_int pivot=" << pivot << " pivot_inv=" << pivot_inv
1777 << " made to one: " << A[i * n + j] << endl;
1778 }
1779 }
1780
1781 /* do the gaussian elimination: */
1782 for (k = i + 1; k < m; k++) {
1783 z = A[k * n + j];
1784 if (z == 0)
1785 continue;
1786 if (f_special) {
1787 f = mult_table[z * q + pivot_inv];
1788 }
1789 else {
1790 f = z;
1791 }
1792 f = negate_table[f];
1793 A[k * n + j] = 0;
1794 if (f_v) {
1795 cout << "Gauss_int eliminating row " << k << endl;
1796 }
1797 for (jj = j + 1; jj < n; jj++) {
1798 a = A[i * n + jj];
1799 b = A[k * n + jj];
1800 // c := b + f * a
1801 // = b - z * a if !f_special
1802 // b - z * pivot_inv * a if f_special
1803 c = mult_table[f * q + a];
1804 c = add_table[c * q + b];
1805 A[k * n + jj] = c;
1806 if (f_v) {
1807 cout << A[k * n + jj] << " ";
1808 }
1809 }
1810 if (f_P) {
1811 for (jj = 0; jj < Pn; jj++) {
1812 a = P[i * Pn + jj];
1813 b = P[k * Pn + jj];
1814 // c := b - z * a
1815 c = mult_table[f * q + a];
1816 c = add_table[c * q + b];
1817 P[k * Pn + jj] = c;
1818 }
1819 }
1820 if (f_v) {
1821 cout << endl;
1822 }
1823 }
1824 i++;
1825 if (f_v) {
1826 cout << "Gauss_int A=" << endl;
1827 Int_vec_print_integer_matrix(cout, A, m, n);
1828 if (f_P) {
1829 cout << "Gauss_int P=" << endl;
1830 Int_vec_print_integer_matrix(cout, P, m, Pn);
1831 }
1832 }
1833 } // next j
1834 rank = i;
1835 if (f_complete) {
1836 for (i = rank - 1; i >= 0; i--) {
1837 j = base_cols[i];
1838 if (!f_special) {
1839 a = A[i * n + j];
1840 }
1841 else {
1842 pivot = A[i * n + j];
1843 pivot_inv = inv_table[pivot];
1844 }
1845 // do the gaussian elimination in the upper part:
1846 for (k = i - 1; k >= 0; k--) {
1847 z = A[k * n + j];
1848 if (z == 0)
1849 continue;
1850 A[k * n + j] = 0;
1851 for (jj = j + 1; jj < n; jj++) {
1852 a = A[i * n + jj];
1853 b = A[k * n + jj];
1854 if (f_special) {
1855 a = mult_table[a * q + pivot_inv];
1856 }
1857 c = mult_table[z * q + a];
1858 c = negate_table[c];
1859 c = add_table[c * q + b];
1860 A[k * n + jj] = c;
1861 }
1862 if (f_P) {
1863 for (jj = 0; jj < Pn; jj++) {
1864 a = P[i * Pn + jj];
1865 b = P[k * Pn + jj];
1866 if (f_special) {
1867 a = mult_table[a * q + pivot_inv];
1868 }
1869 c = mult_table[z * q + a];
1870 c = negate_table[c];
1871 c = add_table[c * q + b];
1872 P[k * Pn + jj] = c;
1873 }
1874 }
1875 } // next k
1876 } // next i
1877 }
1878 if (f_v) {
1879 cout << "Gauss_int the rank is " << rank << endl;
1880 }
1881 return rank;
1882}
1883
1884void char_move(char *p, char *q, int len)
1885{
1886 int i;
1887
1888 for (i = 0; i < len; i++)
1889 *q++ = *p++;
1890}
1891
1892void int_vector_realloc(int *&p, int old_length, int new_length)
1893{
1894 int *q = new int[new_length];
1895 int m, i;
1896
1897 m = MINIMUM(old_length, new_length);
1898 for (i = 0; i < m; i++) {
1899 q[i] = p[i];
1900 }
1901 delete [] p;
1902 p = q;
1903}
1904
1905void int_vector_shorten(int *&p, int new_length)
1906{
1907 int *q = new int[new_length];
1908 int i;
1909
1910 for (i = 0; i < new_length; i++) {
1911 q[i] = p[i];
1912 }
1913 delete [] p;
1914 p = q;
1915}
1916
1917void int_matrix_realloc(int *&p, int old_m, int new_m, int old_n, int new_n)
1918{
1919 int *q = new int[new_m * new_n];
1920 int m = MINIMUM(old_m, new_m);
1921 int n = MINIMUM(old_n, new_n);
1922 int i, j;
1923
1924 for (i = 0; i < m; i++) {
1925 for (j = 0; j < n; j++) {
1926 q[i * new_n + j] = p[i * old_n + j];
1927 }
1928 }
1929 delete [] p;
1930 p = q;
1931}
1932
1933int code_is_irreducible(int k, int nmk, int idx_zero, int *M)
1934{
1935 static int col_reached[1000];
1936 static int row_reached[1000];
1937
1938 /* 0: as yet not reached
1939 * 1: reached, but as yet not processed
1940 * 2: reached and processed. */
1941 int c_reached = 0;
1942 /* number of 1's and 2's in c[] */
1943 int r_reached = 0;
1944 int c_processed = 0;
1945 /* number of 2's in c[] */
1946 int r_processed = 0;
1947 int i, j;
1948
1949 if (nmk >= 1000) {
1950 cout << "code_is_irreducible() nmk > 1000" << endl;
1951 exit(1);
1952 }
1953 if (k >= 1000) {
1954 cout << "code_is_irreducible() k > 1000" << endl;
1955 exit(1);
1956 }
1957 for (j = 0; j < nmk; j++)
1958 col_reached[j] = 0;
1959 for (i = 0; i < k; i++)
1960 row_reached[i] = 0;
1961 row_reached[0] = 1;
1962 r_reached++;
1963 i = 0;
1964 for (j = 0; j < nmk; j++) {
1965 if (M[i * nmk + j] != 0) {
1966 if (col_reached[j] == 0) {
1967 col_reached[j] = 1;
1968 c_reached++;
1969 }
1970 }
1971 }
1972 row_reached[0] = 2;
1973 r_processed++;
1974 while ((c_processed < c_reached) ||
1975 (r_processed < r_reached)) {
1976
1977 /* do a column if there is
1978 * an unprocessed one: */
1979 if (c_processed < c_reached) {
1980 for (j = 0; j < nmk; j++) {
1981 /* search unprocessed col */
1982 if (col_reached[j] == 1) {
1983 /* do column j */
1984 for (i = 0; i < k; i++) {
1985 if (M[i * nmk + j] != idx_zero) {
1986 if (row_reached[i] == 0) {
1987 row_reached[i] = 1;
1988 r_reached++;
1989 }
1990 }
1991 }
1992 /* column j is now processed */
1993 col_reached[j] = 2;
1994 c_processed++;
1995 break; /* for j */
1996 }
1997 }
1998 }
1999
2000 /* do a row if there is an unprocessed one: */
2001 if (r_processed < r_reached) {
2002 for (i = 0; i < k; i++) {
2003 /* search unprocessed row */
2004 if (row_reached[i] == 1) {
2005 /* do row i */
2006 for (j = 0; j < nmk; j++) {
2007 if (M[i * nmk + j] != idx_zero) {
2008 if (col_reached[j] == 0) {
2009 col_reached[j] = 1;
2010 c_reached++;
2011 }
2012 }
2013 }
2014 /* row i is now processed */
2015 row_reached[i] = 2;
2016 r_processed++;
2017 break; /* for i */
2018 }
2019 }
2020 }
2021
2022 }
2023 // printf("code_is_irreducible() c_processed = %d r_processed = %d "
2024 // "nmk = %d k = %d\n", c_processed, r_processed, nmk, k);
2025 if (c_processed < nmk || r_processed < k)
2026 return FALSE;
2027 return TRUE;
2028}
2029
2030
2031
2032void fine_tune(field_theory::finite_field *F, int *mtxD, int verbose_level)
2033// added Dec 28 2009
2034// This is here because it uses sqrt_mod_involved
2035// used in algebra/create_element.cpp
2036{
2037 int f_v = (verbose_level >= 1);
2038 int f_vv = (verbose_level >= 2);
2039 int i;
2040 int q = F->q;
2042
2043 if (f_v) {
2044 cout << "fine_tune: tuning matrix:" << endl;
2046 mtxD, 4, 4, 4, F->log10_of_q);
2047 }
2048
2049 int mtxGram[16];
2050 int mtxDt[16];
2051 int mtxE[16];
2052 int mtxF[16];
2053 int mtxG[16];
2054
2055 for (i = 0; i < 16; i++) {
2056 mtxGram[i] = 0;
2057 }
2058 mtxGram[0 * 4 + 1] = 1;
2059 mtxGram[1 * 4 + 0] = 1;
2060 mtxGram[2 * 4 + 3] = 1;
2061 mtxGram[3 * 4 + 2] = 1;
2062
2063 F->Linear_algebra->transpose_matrix(mtxD, mtxDt, 4, 4);
2064 F->Linear_algebra->mult_matrix_matrix(mtxDt, mtxGram, mtxE, 4, 4, 4,
2065 0 /* verbose_level */);
2066 F->Linear_algebra->mult_matrix_matrix(mtxE, mtxD, mtxF, 4, 4, 4,
2067 0 /* verbose_level */);
2068
2069 if (f_vv) {
2070 cout << "D^transpose * Gram * D = " << endl;
2072 mtxF, 4, 4, 4, F->log10_of_q);
2073 }
2074
2075 int c, d, cv;
2076
2077 c = -1;
2078 for (i = 0; i < 16; i++) {
2079 if (mtxGram[i] == 0) {
2080 if (mtxF[i]) {
2081 cout << "does not preserve the form" << endl;
2082 }
2083 }
2084 else {
2085 d = mtxF[i];
2086 if (c == -1) {
2087 c = d;
2088 }
2089 else {
2090 if (d != c) {
2091 cout << "does not preserve the form (type 2 error)" << endl;
2092 }
2093 }
2094 }
2095 }
2096 if (f_vv) {
2097 cout << "scalar c = " << c << endl;
2098 }
2099 cv = F->inverse(c);
2100 if (f_vv) {
2101 cout << "cv = " << cv << endl;
2102 }
2103 int p, h, s;
2104 NT.is_prime_power(q, p, h);
2105 if (h > 1) {
2106 cout << "q is not a prime" << endl;
2107 exit(1);
2108 }
2109 s = sqrt_mod_involved(cv, q, verbose_level - 2);
2110 if (f_vv) {
2111 cout << "sqrt(cv) = " << s << endl;
2112 }
2113
2114
2115 for (i = 0; i < 16; i++) {
2116 mtxG[i] = F->mult(mtxD[i], s);
2117 }
2118
2119 if (f_vv) {
2120 cout << "mtxG = s * mtxD:" << endl;
2122 mtxG, 4, 4, 4, F->log10_of_q);
2123 }
2124
2125
2126 int mtxGt[16];
2127 F->Linear_algebra->transpose_matrix(mtxG, mtxGt, 4, 4);
2128 F->Linear_algebra->mult_matrix_matrix(mtxGt, mtxGram, mtxE, 4, 4, 4,
2129 0 /* verbose_level */);
2130 F->Linear_algebra->mult_matrix_matrix(mtxE, mtxG, mtxF, 4, 4, 4,
2131 0 /* verbose_level */);
2132
2133 if (f_vv) {
2134 cout << "G^transpose * Gram * G = " << endl;
2135 Int_vec_print_integer_matrix_width(cout, mtxF, 4, 4, 4, F->log10_of_q);
2136 }
2137
2138
2139 for (i = 0; i < 16; i++) {
2140 mtxD[i] = mtxG[i];
2141 }
2142 if (f_v) {
2143 cout << "fine_tune: the resulting matrix is" << endl;
2144 Int_vec_print_integer_matrix_width(cout, mtxD, 4, 4, 4, F->log10_of_q);
2145 }
2146
2147
2148 //int At2[4], As2[4], f_switch2;
2149
2150 //cout << "calling O4_isomorphism_4to2" << endl;
2151 //O4_isomorphism_4to2(F, At2, As2, f_switch2, mtxG, verbose_level);
2152}
2153
2154
2155}}
2156
various functions related to geometries
Definition: geometry.h:721
void transpose_matrix(int *A, int *At, int ma, int na)
void mult_matrix_matrix(int *A, int *B, int *C, int m, int n, int o, int verbose_level)
DISCRETA vector class for vectors of DISCRETA objects.
Definition: discreta.h:797
Vector & append_integer(int a)
Definition: vector.cpp:390
void m_ii(int i, int a)
Definition: discreta.h:824
DISCRETA base class. All DISCRETA classes are derived from this class.
Definition: discreta.h:382
void integral_division_exact(discreta_base &x, discreta_base &q)
Definition: base.cpp:907
virtual std::ostream & print(std::ostream &)
Definition: base.cpp:219
discreta_base & factorial(int z)
Definition: base.cpp:859
discreta_base & power_int_mod(int l, discreta_base &p)
Definition: base.cpp:499
void add_mod(discreta_base &x, discreta_base &y, discreta_base &p)
Definition: base.cpp:680
void swap(discreta_base &a)
Definition: base.cpp:179
void mult_mod(discreta_base &x, discreta_base &y, discreta_base &p)
Definition: base.cpp:372
discreta_base & power_int(int l)
Definition: base.cpp:447
discreta_matrix & m_mn_n(int m, int n)
DISCRETA class for influencing arithmetic operations.
Definition: discreta.h:1360
DISCRETA string class.
Definition: discreta.h:626
DISCRETA integer class.
Definition: discreta.h:667
DISCRETA class for integers of arbitrary magnitude.
Definition: discreta.h:727
DISCRETA class for partitions of an integer.
Definition: discreta.h:1310
void multinomial_ordered(discreta_base &res, int f_v)
DISCRETA permutation class.
Definition: discreta.h:976
DISCRETA class related to printing of objects.
Definition: discreta.h:1426
printing_mode(enum printing_mode_enum printing_mode)
Definition: global.cpp:1581
DISCRETA class related to class domain.
Definition: discreta.h:1413
#define Int_vec_print_integer_matrix(A, B, C, D)
Definition: foundations.h:690
#define MINIMUM(x, y)
Definition: foundations.h:216
#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 EVEN(x)
Definition: foundations.h:221
#define ODD(x)
Definition: foundations.h:222
unsigned int uint_4
Definition: foundations.h:184
#define MAX_PRINTING_MODE_STACK
Definition: global.cpp:30
#define HASH_PRIME
Definition: global.cpp:1616
void print_intvec_mod_10(Vector &v)
Definition: global.cpp:924
void fill_char(void *v, int cnt, int c)
Definition: global.cpp:1605
void discreta_print_factorization(Vector &primes, Vector &exponents, std::ostream &o)
void html_foot(std::ostream &ost)
enum printing_mode_enum current_printing_mode()
Definition: global.cpp:1573
discreta_base * calloc_nobjects_plus_length(int n, kind k)
Definition: global.cpp:121
void texable_string(char *in, char *out)
Definition: global.cpp:1394
void print_factorization_hollerith(Vector &primes, Vector &exponents, hollerith &h)
Definition: global.cpp:414
void free_nobjects_plus_length(discreta_base *p)
Definition: global.cpp:144
void stirling_first(int n, int k, int f_signless, discreta_base &res, int verbose_level)
Definition: global.cpp:997
void freeobject(discreta_base *p)
Definition: global.cpp:89
void Catalan_nk_matrix(int n, discreta_matrix &Cnk, int verbose_level)
Definition: global.cpp:1105
discreta_base * callocobject(kind k)
Definition: global.cpp:81
void ratio_int(int *Px, int *Py, int idx_from, int idx_to, int idx_result, double r)
Definition: global.cpp:1458
void sieve_primes(Vector &v, int from, int to, int limit, int verbose_level)
Definition: global.cpp:880
void int_vector_realloc(int *&p, int old_length, int new_length)
Definition: global.cpp:1892
int sqrt_mod_involved(int a, int p, int verbose_level)
Definition: global.cpp:628
void tuple2_rank(int rank, int &i, int &j, int n, int f_injective)
Definition: global.cpp:1327
void free_m_times_n_objects(discreta_base *p)
Definition: global.cpp:186
void database_init(int verbose_level)
Definition: btree.cpp:53
void sieve(Vector &primes, int factorbase, int verbose_level)
Definition: global.cpp:857
void int_matrix_realloc(int *&p, int old_m, int new_m, int old_n, int new_n)
Definition: global.cpp:1917
void Binomial(int n, int k, discreta_base &n_choose_k)
Definition: global.cpp:1203
void printobjectkind(std::ostream &ost, kind k)
void frobenius_in_AG(domain *dom, int n, permutation &p)
Definition: global.cpp:1528
void free_nobjects(discreta_base *p, int n)
Definition: global.cpp:111
int Gauss_int(int *A, int f_special, int f_complete, int *base_cols, int f_P, int *P, int m, int n, int Pn, int q, int *add_table, int *mult_table, int *negate_table, int *inv_table, int verbose_level)
Definition: global.cpp:1716
void uint4_swap(uint_4 &x, uint_4 &y)
Definition: global.cpp:265
int factor_if_prime_power(int n, int *p, int *e)
Definition: global.cpp:482
int sqrt_mod(int a, int p, int verbose_level)
Definition: global.cpp:580
void midpoint_of_5(int *Px, int *Py, int i1, int i2, int i3, int i4, int i5, int idx)
Definition: global.cpp:1448
int hash_int(int hash0, int a)
Definition: global.cpp:1618
void stirling_second(int n, int k, int f_ordered, discreta_base &res, int verbose_level)
Definition: global.cpp:938
const char * discreta_arch
Definition: global.cpp:37
void midpoint_of_2(int *Px, int *Py, int i1, int i2, int idx)
Definition: global.cpp:1438
int queue_get_and_remove_first_element(Vector &Q)
Definition: global.cpp:1642
const char * kind_ascii(kind k)
Definition: global.cpp:213
void fine_tune(layer1_foundations::field_theory::finite_field *F, int *mtxD, int verbose_level)
Definition: global.cpp:2032
void Catalan(int n, Vector &v, int verbose_level)
Definition: global.cpp:1074
void print_classification_tex(Vector &content, Vector &multiplicities)
Definition: global.cpp:1684
int queue_length(Vector &Q)
Definition: global.cpp:1661
@ PERM_GROUP
PERM_GROUP.
Definition: discreta.h:76
@ PERMUTATION
PERMUTATION.
Definition: discreta.h:57
@ DESIGN_PARAMETER
DESIGN_PARAMETER.
Definition: discreta.h:81
@ HOLLERITH
HOLLERITH.
Definition: discreta.h:71
@ NUMBER_PARTITION
NUMBER_PARTITION.
Definition: discreta.h:55
@ BITMATRIX
BITMATRIX.
Definition: discreta.h:89
@ LONGINTEGER
LONGINTEGER.
Definition: discreta.h:65
@ DESIGN_PARAMETER_SOURCE
DESIGN_PARAMETER_SOURCE.
Definition: discreta.h:86
std::ostream & operator<<(std::ostream &ost, class discreta_base &p)
void Catalan_n(int n, Vector &v, discreta_base &res, int verbose_level)
Definition: global.cpp:1087
void the_first_n_primes(Vector &P, int n)
Definition: global.cpp:1420
void queue_init(Vector &Q, int elt)
Definition: global.cpp:1633
void N_choose_K(discreta_base &n, int k, discreta_base &res)
Definition: global.cpp:1165
int tuple2_unrank(int i, int j, int n, int f_injective)
Definition: global.cpp:1349
int NormRemainder(int a, int m)
Definition: global.cpp:538
void call_system(char *cmd)
Definition: global.cpp:1599
void html_head(std::ostream &ost, char *title_long, char *title_short)
void queue_append(Vector &Q, int elt)
Definition: global.cpp:1669
void translation_in_AG(domain *dom, int n, int i, discreta_base &a, permutation &p)
Definition: global.cpp:1551
void int_vector_shorten(int *&p, int new_length)
Definition: global.cpp:1905
void Krawtchouk(int n, int q, int i, int j, discreta_base &a)
Definition: global.cpp:1305
void factor_integer(int n, Vector &primes, Vector &exponents)
Definition: global.cpp:330
const char * discreta_home
Definition: global.cpp:36
discreta_base * calloc_nobjects(int n, kind k)
Definition: global.cpp:94
void Catalan_nk_star_matrix(int n, discreta_matrix &Cnk, int verbose_level)
Definition: global.cpp:1121
void char_move(char *p, char *q, int len)
Definition: global.cpp:1884
void perm2permutation(int *a, int n, permutation &p)
Definition: global.cpp:1706
void frobenius_in_PG(domain *dom, int n, permutation &p)
Definition: global.cpp:1505
const char * action_kind_ascii(action_kind k)
Definition: global.cpp:256
int remainder_mod(int i, int n)
Definition: global.cpp:317
int invert_mod_integer(int i, int p)
Definition: global.cpp:285
void output_texable_string(std::ostream &ost, char *in)
discreta_base * calloc_m_times_n_objects(int m, int n, kind k)
Definition: global.cpp:163
int code_is_irreducible(int k, int nmk, int idx_zero, int *M)
Definition: global.cpp:1933
void Catalan_nk_star(int n, int k, discreta_matrix &Cnk, discreta_base &res, int verbose_level)
Definition: global.cpp:1146
the orbiter library for the classification of combinatorial objects