Orbiter 2022
Combinatorial Objects
longinteger_domain.cpp
Go to the documentation of this file.
1// longinteger_domain.cpp
2//
3// Anton Betten
4//
5// started as longinteger.cpp: October 26, 2002
6// moved here: January 23, 2015
7
8
9
10#include "foundations.h"
11
12using namespace std;
13
14
15
16namespace orbiter {
17namespace layer1_foundations {
18namespace ring_theory {
19
20
21
24{
25 int r;
26
27 if (a.sign() != b.sign()) {
28 if (a.sign())
29 return -1;
30 else
31 return 1;
32 }
33 r = compare_unsigned(a, b);
34 if (a.sign())
35 return -1 * r;
36 else
37 return r;
38}
39
42// returns -1 if a < b, 0 if a = b,
43// and 1 if a > b, treating a and b as unsigned.
44{
45 int i, l;
46 char ai, bi;
47
48 l = MAXIMUM(a.len(), b.len());
49 for (i = l - 1; i >= 0; i--) {
50 if (i < a.len())
51 ai = a.rep()[i];
52 else
53 ai = 0;
54 if (i < b.len())
55 bi = b.rep()[i];
56 else
57 bi = 0;
58 if (ai < bi)
59 return -1;
60 else if (ai > bi)
61 return 1;
62 }
63 return 0;
64}
65
67{
68 if (compare_unsigned(a, b) == -1)
69 return TRUE;
70 else
71 return FALSE;
72}
73
77// c = a - b, assuming a > b
78{
79 int i;
80 char ai, bi, carry;
81
82 c.freeself();
83 c.sign() = FALSE;
84 c.len() = a.len();
85 c.rep() = NEW_char(c.len());
86 for (i = 0; i < c.len(); i++)
87 c.rep()[i] = 0;
88
89 carry = 0;
90 for (i = 0; i < a.len(); i++) {
91 if (i < b.len())
92 bi = b.rep()[i];
93 else
94 bi = 0;
95 bi += carry;
96 ai = a.rep()[i];
97 if (bi > ai) {
98 ai += 10;
99 carry = 1;
100 }
101 else
102 carry = 0;
103 c.rep()[i] = ai - bi;
104 }
105 c.normalize();
106}
107
110// a := a - b, assuming a > b
111{
112 int i;
113 char ai, bi, carry;
114
115 carry = 0;
116 for (i = 0; i < a.len(); i++) {
117 if (i < b.len()) {
118 bi = b.rep()[i];
119 }
120 else {
121 bi = 0;
122 }
123 bi += carry;
124 ai = a.rep()[i];
125 if (bi > ai) {
126 ai += 10;
127 carry = 1;
128 }
129 else {
130 carry = 0;
131 }
132 a.rep()[i] = ai - bi;
133 }
134 //c.normalize();
135}
136
140{
141 int cmp, carry, i, ai, bi, ci;
142
143 c.freeself();
144 c.len() = MAXIMUM(a.len(), b.len()) + 1;
145 if ((a.sign() && b.sign()) || (!a.sign() && !b.sign())) {
146 c.sign() = a.sign();
147 }
148 else {
149 // mixed signs: subtraction
150 cmp = compare_unsigned(a, b);
151 if (cmp < 0) {
152 // |a| < |b|
153
154 subtract_signless(b, a, c);
155 c.sign() = b.sign();
156 c.normalize();
157 return;
158 }
159 else if (cmp > 0) {
160 // |a| > |b|
161
162 subtract_signless(a, b, c);
163 c.sign() = a.sign();
164 c.normalize();
165 return;
166 }
167 else {
168 // |a| = |b|
169 c.zero();
170 return;
171 }
172 }
173 c.rep() = NEW_char(c.len());
174 for (i = 0; i < c.len(); i++) {
175 c.rep()[i] = 0;
176 }
177
178 carry = 0;
179 for (i = 0; i < c.len(); i++) {
180 if (i < a.len()) {
181 ai = a.rep()[i];
182 }
183 else {
184 ai = 0;
185 }
186 if (i < b.len()) {
187 bi = b.rep()[i];
188 }
189 else {
190 bi = 0;
191 }
192 ci = ai + bi + carry;
193 if (ci >= 10) {
194 carry = 1;
195 }
196 else {
197 carry = 0;
198 }
199 c.rep()[i] = ci % 10;
200 }
201 c.normalize();
202}
203
206 longinteger_object &m, int verbose_level)
207{
208 int f_v = (verbose_level >= 1);
210
211 if (f_v ) {
212 cout << "longinteger_domain::add_mod "
213 "a=" << a << " b=" << b << " m=" << m << endl;
214 }
215 add(a, b, d);
217 d, m,
218 q, c,
219 0 /*verbose_level*/);
220 if (f_v ) {
221 cout << "longinteger_domain::add_mod "
222 "a=" << a << " + b=" << b << " mod m=" << m << " is " << c << endl;
223 }
224
225}
226
229// a := a + b
230{
232
233 add(a, b, C);
234 C.assign_to(a);
235}
236
239// a := a - b
240{
242
243 if (is_less_than(a, b)) {
244 subtract_signless(b, a, c);
246 }
247 else {
248 subtract_signless(a, b, c);
249 }
250 c.assign_to(a);
251}
252
254 longinteger_object &a, long int b)
255// a := a + b
256{
259
260 B.create(b, __FILE__, __LINE__);
261 add(a, B, C);
262 C.assign_to(a);
263}
264
265
269{
270 int i, j;
271 char ai, bj, d, carry;
272 int f_v = FALSE;
273
274 if (a.is_zero() || b.is_zero()) {
275 c.create(0, __FILE__, __LINE__);
276 return;
277 }
278 if ((a.sign() && !b.sign()) || (!a.sign() && b.sign())) {
279 c.sign() = TRUE;
280 }
281 else {
282 c.sign() = FALSE;
283 }
284
285 c.freeself();
286 c.len() = a.len() + b.len() + 2;
287 c.rep() = NEW_char(c.len());
288 for (i = 0; i < c.len(); i++) {
289 c.rep()[i] = 0;
290 }
291
292 if (f_v) {
293 cout << "longinteger_domain::mult a=";
294 print_digits(a.rep(), a.len());
295 cout << "b=";
296 print_digits(b.rep(), b.len());
297 cout << endl;
298 }
299 for (j = 0; j < b.len(); j++) {
300 bj = b.rep()[j];
301 carry = 0;
302 for (i = 0; i < a.len(); i++) {
303 ai = a.rep()[i];
304 d = ai * bj + carry + c.rep()[i + j];
305 if (d >= 100) {
306 cout << "longinteger:mult error: d >= 100" << endl;
307 exit(1);
308 }
309 carry = d / 10;
310 c.rep()[i + j] = d % 10;
311 if (f_v) {
312 cout << "c[" << i + j << "]=" << d % 10 << "="
313 << (char)('0' + c.rep()[i + j]) << endl;
314 }
315 }
316 if (carry) {
317 c.rep()[j + a.len()] = carry;
318 if (f_v) {
319 cout << "c[" << j + a.len() << "]=" << carry << "="
320 << (char)('0' + carry) << endl;
321 }
322 }
323 }
324 if (f_v) {
325 cout << "longinteger_domain::mult c=";
326 print_digits(c.rep(), c.len());
327 cout << endl;
328 }
329 c.normalize();
330 if (f_v) {
331 cout << "longinteger_domain::mult after normalize, c=";
332 print_digits(c.rep(), c.len());
333 cout << endl;
334 }
335}
336
339{
341
342 mult(a, b, C);
343 C.assign_to(a);
344}
345
346
348 longinteger_object &a, int b)
349{
351
352 B.create(b, __FILE__, __LINE__);
353 mult(a, B, C);
354 C.assign_to(a);
355}
356
357static int do_division(longinteger_domain &D,
359{
360 int i, cmp;
361
362 for (i = 9; i >= 0; i--) {
363 cmp = D.compare(r, table[i]);
364 if (cmp >= 0) {
365 return i;
366 }
367 }
368 cout << "do_division we should never reach this point" << endl;
369 exit(1);
370}
371
374 longinteger_object &m, int verbose_level)
375{
376 int f_v = (verbose_level >= 1);
377 int f_vv = (verbose_level >= 2);
378 int i, j, l;
379 char ai, bj, d, carry;
380 //longinteger_object table[10], cc;
381 longinteger_object q, r, c0;
382
383 if (f_v ) {
384 cout << "longinteger_domain::mult_mod "
385 "a=" << a << " b=" << b << " m=" << m << endl;
386 }
387 if (a.is_zero() || b.is_zero()) {
388 c.create(0, __FILE__, __LINE__);
389 return;
390 }
391 if (compare_unsigned(a, m) >= 0) {
392 cout << a << " * " << b << endl;
393 cout << "longinteger_domain::mult_mod a >= m" << endl;
394 exit(1);
395 }
396 if (compare_unsigned(b, m) >= 0) {
397 cout << a << " * " << b << endl;
398 cout << "longinteger_domain::mult_mod b >= m" << endl;
399 exit(1);
400 }
401 if ((a.sign() && !b.sign()) || (!a.sign() && b.sign())) {
402 c.sign() = TRUE;
403 }
404 else {
405 c.sign() = FALSE;
406 }
407
408#if 0
409 for (i = 0; i < 10; i++) {
410 cc.create(i);
411 mult(m, cc, table[i]);
412 }
413#endif
414
415 if (f_v) {
416 cout << "longinteger_domain::mult_mod "
417 "calling c.freeself" << endl;
418 }
419 c.freeself();
420 if (f_v) {
421 cout << "longinteger_domain::mult_mod"
422 "after c.freeself" << endl;
423 }
424 l = m.len();
425 c.len() = (int) (l + 2);
426 c.rep() = NEW_char(c.len());
427 for (i = 0; i < c.len(); i++) {
428 c.rep()[i] = 0;
429 }
430 c.assign_to(c0);
431
432 for (j = b.len() - 1; j >= 0; j--) {
433 if (f_vv) {
434 cout << "j=" << j << endl;
435 }
436 bj = b.rep()[j];
437 carry = 0;
438 for (i = 0; i < l; i++) {
439 if (i < a.len()) {
440 ai = a.rep()[i];
441 }
442 else {
443 ai = 0;
444 }
445 d = ai * bj + carry + c.rep()[i];
446 //cout << (int) ai << " * " << (int) bj << " + "
447 // << (int)carry << " + " << (int) c.rep()[i]
448 // << " = " << (int)d << endl;
449 if (d >= 100) {
450 cout << "longinteger:mult_mod error: d >= 100" << endl;
451 exit(1);
452 }
453 carry = d / 10;
454 c.rep()[i] = d % 10;
455 }
456 if (carry) {
457 d = c.rep()[i] + carry;
458 carry = d / 10;
459 c.rep()[i] = d % 10;
460 i++;
461 }
462 if (carry) {
463 d = c.rep()[i] + carry;
464 carry = d / 10;
465 c.rep()[i] = d % 10;
466 if (carry) {
467 cout << "longinteger_domain::mult_mod "
468 "error: carry" << endl;
469 exit(1);
470 }
471 }
472 if (f_vv) {
473 cout << "longinteger_domain::mult_mod "
474 "c=" << c << " len " << c.len() << endl;
475 }
476 integral_division(c, m, q, r, 0/*verbose_level - 1*/);
477 //h = do_division(*this, c, table);
478 //subtract_signless_in_place(c, table[h]);
479 if (f_vv) {
480 cout << "longinteger_domain::mult_mod "
481 "r=" << r << " len " << r.len() << endl;
482 }
483 c0.assign_to(c);
484 if (f_vv) {
485 cout << "longinteger_domain::mult_mod"
486 "c=c0=" << c << " len " << c.len() << endl;
487 }
488 if (j) {
489 c.rep()[0] = 0;
490 for (i = 0; i < r.len(); i++) {
491 if (i + 1 < c.len()) {
492 c.rep()[i + 1] = r.rep()[i];
493 }
494 }
495 i++;
496 for (; i < c.len(); i++) {
497 c.rep()[i] = 0;
498 }
499 }
500 else {
501 for (i = 0; i < r.len(); i++) {
502 if (i < c.len()) {
503 c.rep()[i] = r.rep()[i];
504 }
505 }
506 for (; i < c.len(); i++) {
507 c.rep()[i] = 0;
508 }
509 }
510 if (f_vv) {
511 cout << "c=" << c << " len " << c.len() << endl;
512 }
513 }
514 c.normalize();
515 if (f_v) {
516 cout << "longinteger_domain::mult_mod " << a << " * " << b
517 << " = " << c << " mod " << m << endl;
518 }
519}
520
522 longinteger_object &a, int *x, int len, int verbose_level)
523{
525 int i;
526 int f_v = (verbose_level >= 1);
527
528 if (f_v) {
529 cout << "longinteger_domain::multiply_up" << endl;
530 }
531 a.one();
532 if (f_v) {
533 cout << "longinteger_domain::multiply_up "
534 "a=" << a << endl;
535 }
536 for (i = 0; i < len; i++) {
537 if (x[i] == 1) {
538 continue;
539 }
540 b.create(x[i], __FILE__, __LINE__);
541 if (f_v) {
542 cout << "longinteger_domain::multiply_up "
543 "i=" << i << " x[i]=" << x[i]
544 << " b=" << b << endl;
545 }
546 mult(a, b, c);
547 if (f_v) {
548 cout << "longinteger_domain::multiply_up "
549 "i=" << i << " x[i]=" << x[i]
550 << " c=" << c << endl;
551 }
552 c.assign_to(a);
553 if (f_v) {
554 cout << "longinteger_domain::multiply_up "
555 "i=" << i << " x[i]=" << x[i]
556 << " a=" << a << endl;
557 }
558 //cout << "*" << x[i] << "=" << a << endl;
559 }
560 if (f_v) {
561 cout << "longinteger_domain::multiply_up done" << endl;
562 }
563}
564
566 longinteger_object &a, long int *x, int len, int verbose_level)
567{
569 int i;
570 int f_v = (verbose_level >= 1);
571
572 if (f_v) {
573 cout << "longinteger_domain::multiply_up_lint" << endl;
574 }
575 a.one();
576 if (f_v) {
577 cout << "longinteger_domain::multiply_up_lint "
578 "a=" << a << endl;
579 }
580 for (i = 0; i < len; i++) {
581 if (x[i] == 1) {
582 continue;
583 }
584 b.create(x[i], __FILE__, __LINE__);
585 if (f_v) {
586 cout << "longinteger_domain::multiply_up_lint "
587 "i=" << i << " x[i]=" << x[i]
588 << " b=" << b << endl;
589 }
590 mult(a, b, c);
591 if (f_v) {
592 cout << "longinteger_domain::multiply_up_lint "
593 "i=" << i << " x[i]=" << x[i]
594 << " c=" << c << endl;
595 }
596 c.assign_to(a);
597 if (f_v) {
598 cout << "longinteger_domain::multiply_up_lint "
599 "i=" << i << " x[i]=" << x[i]
600 << " a=" << a << endl;
601 }
602 //cout << "*" << x[i] << "=" << a << endl;
603 }
604 if (f_v) {
605 cout << "longinteger_domain::multiply_up_lint done" << endl;
606 }
607}
608
611{
613
614 integral_division(a, b, q, r, 0);
615 return q.as_int();
616}
617
620{
622
623 integral_division(a, b, q, r, 0);
624 return q.as_lint();
625}
626
629 longinteger_object &a_over_b)
630{
632
633 integral_division(a, b, a_over_b, r, 0);
634 if (!r.is_zero()) {
635 cout << "longinteger_domain::integral_division_exact "
636 "b does not divide a" << endl;
637 exit(1);
638 }
639}
640
644 int verbose_level)
645{
646 int f_v = (verbose_level >= 1);
647 longinteger_object table[10], c;
648 int i, l, ql;
649
650 if (f_v) {
651 cout << "longinteger_domain::integral_division "
652 "dividing a=" << a << " by b=" << b << endl;
653 }
654 if (a.sign()) {
655 cout << "longinteger_domain::integral_division "
656 "a is negative" << endl;
657 exit(1);
658 }
659 if (b.sign()) {
660 cout << "longinteger_domain::integral_division "
661 "b is negative" << endl;
662 exit(1);
663 }
664 if (compare(a, b) == -1) {
665 q.zero();
666 a.assign_to(r);
667 return;
668 }
669
670 for (i = 0; i < 10; i++) {
671 c.create(i, __FILE__, __LINE__);
672 mult(b, c, table[i]);
673 }
674 q.freeself();
675 r.freeself();
676
677 // load r with leading b.len() digits of a:
678 r.sign() = FALSE;
679 r.len() = b.len() + 1;
680 r.rep() = NEW_char(r.len());
681 l = a.len() - b.len();
682 for (i = 0; i < b.len(); i++) {
683 r.rep()[i] = a.rep()[l + i];
684 }
685 r.rep()[b.len()] = 0;
686
687 // allocate q of length a.len() - b.len() + 1
688 q.sign() = FALSE;
689 q.len() = a.len() - b.len() + 1;
690 q.rep() = NEW_char(q.len());
691 for (i = 0; i < q.len(); i++) {
692 q.rep()[i] = 0;
693 }
694
695 // main loop containing the divisions:
696 for ( ; l >= 0; l--) {
697 ql = do_division(*this, r, table);
698 q.rep()[l] = ql;
699 subtract_signless(r, table[ql], c);
700 if (f_v) {
701 cout << "l=" << l << " r=" << r
702 << " ql=" << ql << " c=" << c << endl;
703 }
704
705 if (l == 0) {
706 break;
707 }
708
709 // put c into r, shift up by one digit
710 // and append the next digit a[l-1].
711 for (i = 0; i < c.len(); i++) {
712 r.rep()[i + 1] = c.rep()[i];
713 }
714 for (i++ ; i < r.len(); i++) {
715 r.rep()[i] = 0;
716 }
717 r.rep()[0] = a.rep()[l - 1];
718 }
719 c.assign_to(r);
720 r.normalize();
721 q.normalize();
722}
723
726 int b, longinteger_object &q, int &r)
727{
729 int verbose_level = 0;
730
731 B.create(b, __FILE__, __LINE__);
732 integral_division(a, B, q, R, verbose_level);
733 r = R.as_int();
734}
735
738 long int b, longinteger_object &q, long int &r)
739{
741 int verbose_level = 0;
742
743 B.create(b, __FILE__, __LINE__);
744 integral_division(a, B, q, R, verbose_level);
745 r = R.as_lint();
746}
747
751 longinteger_object &u, longinteger_object &v, int verbose_level)
752// the gcd computed here is always nonnegative
753{
754 int f_v = (verbose_level >= 1);
755 int f_vv = (verbose_level >= 2);
756 longinteger_object q, rm1, r, rp1, sm1, s, sp1, tm1, t, tp1, x, y;
757 int c;
758
759 if (f_v) {
760 cout << "longinteger_domain::extended_gcd "
761 "a=" << a << " b=" << b << endl;
762 }
763 if (a.is_zero()) {
764 b.assign_to(g);
765 u.create(0, __FILE__, __LINE__);
766 v.create(1, __FILE__, __LINE__);
767 if (g.sign()) {
768 g.negate();
769 u.negate();
770 v.negate();
771 }
772 return;
773 }
774 if (b.is_zero()) {
775 a.assign_to(g);
776 u.create(1, __FILE__, __LINE__);
777 v.create(0, __FILE__, __LINE__);
778 if (g.sign()) {
779 g.negate();
780 u.negate();
781 v.negate();
782 }
783 return;
784 }
785 c = compare_unsigned(a, b);
786 if (c < 0) { // |a| < |b|
787 extended_gcd(b, a, g, v, u, verbose_level);
788 return;
789 }
790 if (a.sign()) {
791 a.negate();
792 extended_gcd(a, b, g, u, v, verbose_level);
793 a.negate();
794 u.negate();
795 if (g.sign()) {
796 g.negate();
797 u.negate();
798 v.negate();
799 }
800 return;
801 }
802 if (b.sign()) {
803 b.negate();
804 extended_gcd(a, b, g, u, v, verbose_level);
805 b.negate();
806 v.negate();
807 if (g.sign()) {
808 g.negate();
809 u.negate();
810 v.negate();
811 }
812 return;
813 }
814
815 // now a > 0, b > 0 and a >= b
816 a.assign_to(rm1);
817 b.assign_to(r);
818 sm1.create(1, __FILE__, __LINE__);
819 tm1.create(0, __FILE__, __LINE__);
820 s.create(0, __FILE__, __LINE__);
821 t.create(1, __FILE__, __LINE__);
822 while (TRUE) {
823 integral_division(rm1, r, q, rp1, verbose_level - 1);
824 if (rp1.is_zero()) {
825 r.assign_to(g);
826 s.assign_to(u);
827 t.assign_to(v);
828 return;
829 }
830 if (f_vv) {
831 rm1.print(cout);
832 cout << " = ";
833 q.print(cout);
834 cout << " * ";
835 r.print(cout);
836 cout << " + ";
837 rp1.print(cout);
838 cout << endl;
839 }
840 q.negate();
841 mult(q, s, x);
842 mult(q, t, y);
843 add(sm1, x, sp1);
844 add(tm1, y, tp1);
845 r.swap_with(rm1);
846 s.swap_with(sm1);
847 t.swap_with(tm1);
848 rp1.swap_with(r);
849 sp1.swap_with(s);
850 tp1.swap_with(t);
851 if (f_vv) {
852 r.print(cout);
853 cout << " = ";
854 s.print(cout);
855 cout << " * ";
856 a.print(cout);
857 cout << " + ";
858 t.print(cout);
859 cout << " * ";
860 b.print(cout);
861 cout << endl;
862 }
863 }
864}
865
867 longinteger_object &a, int b)
868{
869 int r, l = 0;
870 longinteger_object a1, a2;
871
872 a.assign_to(a1);
873 a1.normalize();
874 while (!a1.is_zero()) {
875 integral_division_by_int(a1, b, a2, r);
876 l++;
877 a2.assign_to(a1);
878 }
879 return l;
880}
881
883 longinteger_object &a, int b, int *&rep, int &len)
884{
885 int i, r;
886 longinteger_object a1, a2;
887
888 a.assign_to(a1);
889 a1.normalize();
890 len = 0;
891 while (!a1.is_zero()) {
892 integral_division_by_int(a1, b, a2, r);
893 len++;
894 a2.assign_to(a1);
895 }
896 a.assign_to(a1);
897 a1.normalize();
898 rep = NEW_int(len);
899 for (i = 0; i < len; i++) {
900 integral_division_by_int(a1, b, a2, r);
901 rep[i] = r;
902 a2.assign_to(a1);
903 }
904 for (i = 0; i < len; i++) {
905 cout << rep[i] << " ";
906 }
907 cout << endl;
908}
909
911 longinteger_object &a, int n)
912{
913 longinteger_object b, c, d;
914
915 a.assign_to(b);
916 c.one();
917 while (n) {
918 if (n % 2) {
919 mult(b, c, d);
920 d.assign_to(c);
921 }
922 mult(b, b, d);
923 d.assign_to(b);
924 n >>= 1;
925 }
926 c.assign_to(a);
927}
928
931{
932 longinteger_object b, c, d;
933
934 a.assign_to(b);
935 c.one();
936 while (n) {
937 if (n % 2) {
938 mult_mod(b, c, d, m, 0);
939 d.assign_to(c);
940 }
941 mult_mod(b, b, d, m, 0);
942 d.assign_to(b);
943 n >>= 1;
944 }
945 c.assign_to(a);
946}
947
951 int verbose_level)
952{
953 int f_v = (verbose_level >= 1);
954 int f_vv = (verbose_level >= 2);
955 longinteger_object b, c, d, n1, N;
956 int r;
957
958 a.assign_to(b);
959 n.assign_to(N);
960 c.one();
961 if (f_v) {
962 cout << "longinteger_domain::power_longint_mod" << endl;
963 cout << "computing " << b << " to the power "
964 << n << " mod " << m << ":" << endl;
965 }
966 while (!N.is_zero()) {
967 if (f_vv) {
968 cout << "n=" << N << " : " << b << "^"
969 << N << " * " << c << endl;
970 }
971 integral_division_by_int(N, 2, n1, r);
972 if (f_vv) {
973 cout << "after division by 2, n1=" << n1
974 << " r=" << r << endl;
975 }
976 if (r) {
977 mult_mod(b, c, d, m, verbose_level);
978 if (f_vv) {
979 cout << b << " * " << c << " = " << d << endl;
980 }
981 d.assign_to(c);
982 }
983 mult_mod(b, b, d, m, verbose_level);
984 if (f_vv) {
985 cout << b << "^2 = " << d << endl;
986 }
987 d.assign_to(b);
988 n1.assign_to(N);
989 }
990 c.assign_to(a);
991}
992
993
994
995
996
997
1000 int verbose_level)
1001{
1002 int i, la, len;
1003 char c1;
1004 int f_v = (verbose_level >= 1);
1006
1007 if (a.is_zero()) {
1008 sqrt_a.create(0, __FILE__, __LINE__);
1009 return;
1010 }
1011 if (a.sign()) {
1012 cout << "longinteger_domain::square_root a is negative" << endl;
1013 exit(1);
1014 }
1015
1016 la = a.len();
1017 if (ODD(la)) {
1018 la++;
1019 }
1020 len = (la >> 1) + 1;
1021
1022 sqrt_a.freeself();
1023 sqrt_a.len() = len;
1024 sqrt_a.rep() = NEW_char(sqrt_a.len());
1025 for (i = 0; i < sqrt_a.len(); i++) {
1026 sqrt_a.rep()[i] = 0;
1027 }
1028
1029 if (f_v) {
1030 cout << "longinteger_domain::square_root a=";
1031 print_digits(a.rep(), a.len());
1032 }
1033
1034 for (i = len - 1; i >= 0; i--) {
1035 for (c1 = 9; c1 >= 0; c1--) {
1036 if (f_v) {
1037 cout << "trying a[" << i << "]=" << (int) c1 << endl;
1038 }
1039 sqrt_a.rep()[i] = c1;
1040 if (f_v) {
1041 cout << "sqrt_a = " << sqrt_a << endl;
1042 }
1043 if (c1) {
1044 mult(sqrt_a, sqrt_a, a2);
1045 if (f_v) {
1046 cout << "a2 = " << a2 << endl;
1047 }
1048 if (compare_unsigned(a2, a) <= 0) {
1049 if (f_v) {
1050 cout << "success with digit " << i
1051 << " : sqrt_a=" << sqrt_a << endl;
1052 }
1053 break;
1054 }
1055 }
1056 }
1057 if (f_v) {
1058 cout << "sqrt_a[" << i << "]=" << sqrt_a.rep()[i] << endl;
1059 }
1060 }
1061
1062 if (f_v) {
1063 cout << "longinteger_domain::square_root c=";
1064 print_digits(sqrt_a.rep(), sqrt_a.len());
1065 cout << endl;
1066 }
1067 sqrt_a.normalize();
1068 if (f_v) {
1069 cout << "longinteger_domain::square_root after normalize, sqrt_a=";
1070 print_digits(sqrt_a.rep(), sqrt_a.len());
1071 cout << endl;
1072 }
1073}
1074
1075
1076
1077int longinteger_domain::square_root_mod(int a, int p, int verbose_level)
1078// solves x^2 = a mod p. Returns x
1079{
1080 int f_v = (verbose_level >= 1);
1082 longinteger_object A, X, a2, a4, b, X2, Four, Two, mOne;
1083 int round;
1085
1086 if (f_v) {
1087 cout << "longinteger_domain::square_root_mod" << endl;
1088 }
1089 a = a % p;
1090 if (NT.Jacobi(a, p, 0 /* verbose_level*/) == -1) {
1091 cout << "longinteger_domain::square_root_mod a is not a square modulo p" << endl;
1092 cout << "a=" << a << endl;
1093 cout << "p=" << p << endl;
1094 exit(1);
1095 }
1096 Two.create(2, __FILE__, __LINE__);
1097 Four.create(4, __FILE__, __LINE__);
1098 A.create(a, __FILE__, __LINE__);
1099 P.create(p, __FILE__, __LINE__);
1100 mOne.create(p - 1, __FILE__, __LINE__);
1101 if (f_v) {
1102 cout << "longinteger_domain::square_root_mod A=" << A << endl;
1103 cout << "longinteger_domain::square_root_mod P=" << P << endl;
1104 cout << "longinteger_domain::square_root_mod mOne=" << mOne << endl;
1105 }
1106 if (p % 4 == 3) {
1107 A.assign_to(X);
1108 power_int_mod(X, (p + 1) >> 2, P);
1109 return X.as_int();
1110 }
1111 if (p % 8 == 5) {
1112 if (f_v) {
1113 cout << "longinteger_domain::square_root_mod p % 8 == 5" << endl;
1114 }
1115 A.assign_to(b);
1116 power_int_mod(b, (p - 1) >> 2, P);
1117 if (f_v) {
1118 cout << "longinteger_domain::square_root_mod a^((p-1)/4)=" << b << endl;
1119 }
1120 // cout << "A = " << A << endl;
1121 // cout << "b = A^(p-1)/4=" << b << endl;
1122 if (b.is_one()) {
1123 if (f_v) {
1124 cout << "longinteger_domain::square_root_mod a^((p-1)/4)=1" << endl;
1125 }
1126 A.assign_to(X);
1127 power_int_mod(X, (p + 3) >> 3, P);
1128 if (f_v) {
1129 cout << "longinteger_domain::square_root_mod done" << endl;
1130 }
1131 return X.as_int();
1132 }
1133 if (compare_unsigned(b, mOne) == 0) {
1134 if (f_v) {
1135 cout << "longinteger_domain::square_root_mod a^((p-1)/4)=1" << endl;
1136 }
1137
1138 //a2.add_mod(A, A, P);
1139 //a4.add_mod(a2, a2, P);
1140 //a4.power_int_mod((p - 5) >> 3, P);
1141 //X.mult_mod(a2, a4, P);
1142
1143 add_mod(A, A, a2, P, 0 /* verbose_level */);
1144 add_mod(a2, a2, a4, P, 0 /* verbose_level */);
1145 power_int_mod(a4, (p - 5) >> 3, P);
1146 mult_mod(a2, a4, X, P, 0 /* verbose_level */);
1147 if (f_v) {
1148 cout << "longinteger_domain::square_root_mod done" << endl;
1149 }
1150 return X.as_int();
1151 }
1152 else {
1153 cout << "longinteger_domain::square_root_mod p % 8 = 5 and power neq +-1" << endl;
1154 cout << "power = " << b << endl;
1155 exit(1);
1156 }
1157 }
1158 if (f_v) {
1159 cout << "longinteger_domain::square_root_mod p % 8 == 1" << endl;
1160 }
1161 // now p % 8 == 1
1162 // Tonelli / Shanks algorithm:
1163 int n, r = 0, q, e, m;
1164 longinteger_object Z, N, Y, B, T, d, AB, Ypower, Bpower, Tmp1;
1165
1166 if (f_v) {
1167 cout << "longinteger_domain::square_root_mod, Tonelli / Shanks:" << endl;
1168 }
1169 q = p - 1;
1170 if (f_v) {
1171 cout << "longinteger_domain::square_root_mod q=" << q << endl;
1172 }
1173 e = 0;
1174 while (EVEN(q)) {
1175 q >>= 1;
1176 e++;
1177 }
1178 if (f_v) {
1179 cout << "p - 1 = 2^" << e << " * " << q << endl;
1180 }
1181
1182 // pick n to be a nonsquare mod p:
1183 for (n = 1; n < p - 1; n++) {
1184 r = NT.Legendre(n, p, verbose_level - 1);
1185 if (r == -1) {
1186 break;
1187 }
1188 }
1189
1190 if (f_v) {
1191 cout << "n=" << n << " p=" << p << " Legendre(n,p)=" << r<< endl;
1192 }
1193 N.create(n, __FILE__, __LINE__);
1194 if (f_v) {
1195 cout << "longinteger_domain::square_root_mod N=" << N << endl;
1196 }
1197 N.assign_to(Z);
1198 power_int_mod(Z, q, P);
1199 Z.assign_to(Y);
1200 if (f_v) {
1201 cout << "longinteger_domain::square_root_mod Y=N^q=" << Y << endl;
1202 }
1203 r = e;
1204 A.assign_to(X);
1205 power_int_mod(X, (q - 1) >> 1, P);
1206 if (f_v) {
1207 cout << "longinteger_domain::square_root_mod X=" << X << endl;
1208 }
1209 mult_mod(X, X, d, P, 0 /* verbose_level */);
1210 mult_mod(A, d, B, P, 0 /* verbose_level */);
1211 mult_mod(A, X, Tmp1, P, 0 /* verbose_level */);
1212 Tmp1.assign_to(X);
1213 if (f_v) {
1214 cout << "initialization:" << endl;
1215 }
1216 round = 0;
1217 while (TRUE) {
1218 if (f_v) {
1219 cout << "Y=" << Y << endl;
1220 cout << "r=" << r << endl;
1221 cout << "X=" << X << endl;
1222 cout << "B=" << B << endl;
1223 }
1224
1225
1226 mult_mod(X, X, X2, P, 0 /* verbose_level */);
1227 if (f_v) {
1228 cout << "longinteger_domain::square_root_mod X2=" << X2 << endl;
1229 }
1230 mult_mod(A, B, AB, P, 0 /* verbose_level */);
1231 if (f_v) {
1232 cout << "longinteger_domain::square_root_mod AB=" << AB << endl;
1233 cout << "B=" << B << endl;
1234 }
1235
1236 if (compare_unsigned(AB, X2) != 0) {
1237 cout << "loop invariant violated: ab != x^2" << endl;
1238 cout << "ab=" << d << endl;
1239 cout << "x^2=" << X2 << endl;
1240 exit(1);
1241 }
1242
1243 Y.assign_to(Ypower);
1244 power_int_mod(Ypower, 1 << (r - 1), P);
1245 if (f_v) {
1246 cout << "longinteger_domain::square_root_mod Ypower=" << Ypower << endl;
1247 }
1248
1249 if (compare_unsigned(Ypower, mOne)) {
1250 cout << "loop invariant violated: Y^{2^{r-1}} != -1" << endl;
1251 exit(1);
1252 }
1253
1254
1255
1256 B.assign_to(Bpower);
1257 if (f_v) {
1258 cout << "longinteger_domain::square_root_mod Bpower (before)=" << Bpower << endl;
1259 }
1260 power_int_mod(Bpower, 1 << (r - 1), P);
1261 if (f_v) {
1262 cout << "longinteger_domain::square_root_mod Bpower=" << Bpower << endl;
1263 }
1264 if (!Bpower.is_one()) {
1265 cout << "loop invariant violated: B^{2^{r-1}} != 1" << endl;
1266 exit(1);
1267 }
1268
1269
1270
1271
1272
1273 if (remainder_mod_int(B, p) == 1) {
1274 m = -1;
1275 }
1276 else {
1277 for (m = 1; ; m++) {
1278 B.assign_to(d);
1279 power_int_mod(d, 1 << m, P);
1280 if (d.is_one()) {
1281 break;
1282 }
1283 if (m >= r) {
1284 cout << "sqrt_mod(), Tonelli / Shanks:" << endl;
1285 cout << "error: a is not a quadratic residue mod p" << endl;
1286 exit(1);
1287 }
1288 }
1289 }
1290
1291
1292 if (f_v) {
1293 cout << round << " & " << A << " & " << B << " & " << X << " & "
1294 << X2 << " & " << Y << " & " << r << " & " << AB
1295 << " & " << Ypower << " & " << Bpower << " & ";
1296 }
1297
1298 if (m == -1) {
1299 if (f_v) {
1300 cout << " & & & & \\\\" << endl;
1301 }
1302 }
1303 else {
1304 if (f_v) {
1305 cout << m;
1306 }
1307 }
1308
1309 //cout << "m=" << m << endl;
1310
1311 if (m == -1) {
1312 if (f_v) {
1313 cout << "longinteger_domain::square_root_mod done" << endl;
1314 }
1315 return X.as_int();
1316 }
1317
1318 if (f_v) {
1319 cout << "m=" << m << endl;
1320 }
1321 Y.assign_to(T);
1322 power_int_mod(T, 1 << (r - m - 1), P);
1323 mult_mod(T, T, Y, P, 0 /* verbose_level */);
1324 r = m; // integers
1325
1326 mult_mod(X, T, Tmp1, P, 0 /* verbose_level */);
1327 Tmp1.assign_to(X);
1328
1329 mult_mod(B, Y, Tmp1, P, 0 /* verbose_level */);
1330 Tmp1.assign_to(B);
1331
1332 if (f_v) {
1333 cout << " & " << Y << " & " << X << " & " << B << " & " << r;
1334 cout << "\\\\" << endl;
1335 }
1336 round++;
1337 }
1338 if (f_v) {
1339 cout << "longinteger_domain::square_root_mod done" << endl;
1340 }
1341}
1342
1344 longinteger_object &a, int q, int n)
1345// create (q^n - 1)
1346{
1347 a.create(q, __FILE__, __LINE__);
1348 power_int(a, n);
1349}
1350
1351
1353 longinteger_object &a, int q, int n)
1354// create (q^n - 1)
1355{
1356 longinteger_object b, c;
1357
1358 b.create(q, __FILE__, __LINE__);
1359 power_int(b, n);
1360 c.create(-1, __FILE__, __LINE__);
1361 add(b, c, a);
1362}
1363
1365// $M_n = 2^n - 1$
1366{
1367 longinteger_object a, b;
1368
1369 a.create(2, __FILE__, __LINE__);
1370 b.create(-1, __FILE__, __LINE__);
1371 power_int(a, n);
1372 add(a, b, M);
1373 // cout << "Mersenne number M_" << n << "=" << a << endl;
1374}
1375
1377// $F_n = 2^{2^n} + 1$
1378{
1379 longinteger_object a, b;
1380 int l;
1381
1382 a.create(2, __FILE__, __LINE__);
1383 b.create(1, __FILE__, __LINE__);
1384 l = 1 << n;
1385 // cout << "l=" << l << endl;
1386 power_int(a, l);
1387 add(a, b, F);
1388 // cout << "Fermat number F_" << n << "=" << a << endl;
1389}
1390
1391
1392
1393void longinteger_domain::Dedekind_number(longinteger_object &Dnq, int n, int q, int verbose_level)
1394{
1395 int f_v = (verbose_level >= 1);
1398 longinteger_object A, S, B;
1399
1400 if (f_v) {
1401 cout << "longinteger_domain::Dedekind_number n=" << n << " q=" << q << endl;
1402 }
1403 int *primes;
1404 int *exponents;
1405 int len, cnt;
1406 long int i, N, h, d, d_prime;
1407 int *v;
1408
1409 len = NT.factor_int(n, primes, exponents);
1410
1411 v = NEW_int(len);
1412
1413 S.create(0, __FILE__, __LINE__);
1414
1415 N = NT.i_power_j(2, len);
1416 if (f_v) {
1417 cout << "\\frac{1}{" << n << "} \\Big( ";
1418 }
1419
1420 int f_first = TRUE;
1421 for (i = 0; i < N; i++) {
1422 if (FALSE) {
1423 cout << "i=" << i << endl;
1424 }
1425 Gg.AG_element_unrank(2, v, 1, len, i);
1426 d = 1;
1427 cnt = 0;
1428 for (h = 0; h < len; h++) {
1429 if (v[h]) {
1430 d *= primes[h];
1431 cnt++;
1432 }
1433 }
1434 d_prime = n / d;
1435 //a = NT.i_power_j(q, d_prime);
1436 create_q_to_the_n(A, q, d_prime);
1437
1438 if (FALSE) {
1439 cout << "d=" << d << " d_prime=" << d_prime << " A=" << A << " S=" << S << endl;
1440 }
1441
1442 if (ODD(cnt)) {
1443 if (f_v) {
1444 cout << " - ";
1445 }
1446 subtract_in_place(S, A);
1447 }
1448 else {
1449 if (f_v) {
1450 if (!f_first) {
1451 cout << " + ";
1452 }
1453 }
1454 add_in_place(S, A);
1455 }
1456 if (f_first) {
1457 f_first = FALSE;
1458 }
1459 if (f_v) {
1460 cout << "q^{" << d_prime << "}";
1461 }
1462 }
1463 if (f_v) {
1464 cout << "\\Big) ";
1465 }
1466 if (f_v) {
1467 cout << endl;
1468 }
1469 B.create(n, __FILE__, __LINE__);
1470
1471 if (f_v) {
1472 cout << "S=" << S << endl;
1473 }
1474 integral_division_exact(S, B, Dnq);
1475
1476
1477
1478 FREE_int(v);
1479 FREE_int(primes);
1480 FREE_int(exponents);
1481
1482
1483 if (f_v) {
1484 cout << "longinteger_domain::Dedekind_number done" << endl;
1485 }
1486}
1487
1488
1489
1491{
1492 if (((a.rep()[0] % 2)) == 0)
1493 return TRUE;
1494 else
1495 return FALSE;
1496}
1497
1499{
1500 if (is_even(a))
1501 return FALSE;
1502 else
1503 return TRUE;
1504}
1505
1506
1507
1509{
1510 int r;
1512
1513 integral_division_by_int(a, p, q, r);
1514 return r;
1515}
1516
1518 longinteger_object &residue, int p)
1519{
1520 int r, n = 0;
1522
1523 if (a.is_zero()) {
1524 cout << "longinteger_domain::multiplicity_of_p a = 0" << endl;
1525 exit(1);
1526 }
1527 a.assign_to(residue);
1528 while (!residue.is_one()) {
1529 integral_division_by_int(residue, p, q, r);
1530 if (r)
1531 break;
1532 n++;
1533 q.assign_to(residue);
1534 }
1535 return n;
1536}
1537
1540 int p_min, int verbose_level)
1541{
1542 int f_v = (verbose_level >= 1);
1543 int f_vv = (verbose_level >= 2);
1544 longinteger_object n, n1, q, pp;
1545 long int p, r, cnt = 0;
1546
1547 if (f_v) {
1548 cout << "longinteger_domain::smallest_primedivisor " << a
1549 << " p_min=" << p_min << endl;
1550 }
1551 a.assign_to(n);
1552
1553 if (p_min == 0) {
1554 p_min = 2;
1555 }
1556 if (p_min < 0) {
1557 p_min = - p_min;
1558 }
1559 if (p_min <= 2) {
1560 if (is_even(n)) {
1561 return 2;
1562 }
1563 p_min = 3;
1564 }
1565 if (p_min <= 3) {
1566 if (remainder_mod_int(n, 3) == 0) {
1567 return 3;
1568 }
1569 p_min = 5;
1570 }
1571 if (EVEN(p_min)) {
1572 p_min--;
1573 }
1574 p = p_min;
1575 while (TRUE) {
1576 cnt++;
1577 if (f_vv) {
1578 cout << "longinteger_domain::smallest_primedivisor n=" << n
1579 << " trying p=" << p << endl;
1580 }
1581 n.assign_to(n1);
1582 integral_division_by_lint(n1, p, q, r);
1583 if (f_vv && (cnt % 1) == 0) {
1584 cout << "longinteger_domain::smallest_primedivisor n=" << n1
1585 << " trying p=" << p << " q=" << q
1586 << " r=" << r << endl;
1587 cnt = 0;
1588 }
1589 if (r == 0) {
1590 return p;
1591 }
1592 pp.create(p, __FILE__, __LINE__);
1593 if (compare(q, pp) < 0) {
1594 break;
1595 }
1596 p += 2;
1597 }
1598 if (f_v) {
1599 cout << "longinteger_domain::smallest_primedivisor "
1600 "the number is prime" << endl;
1601 }
1602 return 0;
1603}
1604
1607 int &nb_primes, longinteger_object *&primes,
1608 int *&exponents, int verbose_level)
1609{
1610 int f_v = (verbose_level >= 1);
1611 //int f_vv = (verbose_level >= 2);
1612 longinteger_object n, q, pp, r;
1614 long int p, last_prime = 0;
1615 int i;
1617
1618 if (f_v) {
1619 cout << "longinteger_domain::factor_into_longintegers factoring " << a << endl;
1620 }
1621 if (a.is_zero()) {
1622 cout << "longinteger_domain::factor_into_longintegers a is zero" << endl;
1623 exit(1);
1624 }
1625 if (a.is_one()) {
1626 nb_primes = 0;
1627 primes = NEW_OBJECTS(longinteger_object, 1);
1628 exponents = NEW_int(1);
1629 return;
1630 }
1631 a.assign_to(n);
1632 p = smallest_primedivisor(n, last_prime, verbose_level);
1633 if (p == 0) {
1634 p = n.as_lint();
1635 }
1636 pp.create(p, __FILE__, __LINE__);
1637 primes = NEW_OBJECTS(longinteger_object, 1);
1638 exponents = NEW_int(1);
1639 nb_primes = 1;
1640 pp.assign_to(primes[0]);
1641 exponents[0] = 1;
1642 last_prime = p;
1643 D.integral_division(n, pp, q, r, verbose_level - 1);
1644 if (!r.is_zero()) {
1645 cout << "longinteger_domain::factor_into_longintegers "
1646 "factor does not divide" << endl;
1647 }
1648 q.assign_to(n);
1649 while (!n.is_one()) {
1650 if (f_v) {
1651 cout << "longinteger_domain::factor_into_longintegers "
1652 "remaining factor: " << n << endl;
1653 }
1654 p = smallest_primedivisor(n, last_prime, verbose_level);
1655 // if p == 0: n is prime
1656
1657 if (p == 0) {
1658 p = n.as_lint();
1659 }
1660 if (p == last_prime) {
1661 exponents[nb_primes - 1]++;
1662 pp.create(p, __FILE__, __LINE__);
1663 }
1664 else {
1667 int *ex = NEW_int(nb_primes + 1);
1668 for (i = 0; i < nb_primes; i++) {
1669 primes[i].assign_to(pr[i]);
1670 ex[i] = exponents[i];
1671 }
1672 FREE_OBJECTS(primes);
1673 FREE_int(exponents);
1674 primes = pr;
1675 exponents = ex;
1676 if (p) {
1677 pp.create(p, __FILE__, __LINE__);
1678 }
1679 else {
1680 n.assign_to(pp);
1681 }
1682 pp.assign_to(primes[nb_primes]);
1683 exponents[nb_primes] = 1;
1684 nb_primes++;
1685 last_prime = p;
1686 }
1687
1688 D.integral_division(n, pp, q, r, verbose_level - 1);
1689 if (!r.is_zero()) {
1690 cout << "longinteger_domain::factor_into_longintegers "
1691 "factor does not divide" << endl;
1692 }
1693 q.assign_to(n);
1694 if (f_v) {
1695 cout << "partial factorization: " << a << " = ";
1696 NT.print_longfactorization(nb_primes, primes, exponents);
1697 cout << " * " << n;
1698 cout << endl;
1699 }
1700
1701 }
1702 if (f_v) {
1703 cout << "longinteger_domain::factor_into_longintegers "
1704 "prime factorization of " << a << " = ";
1705 NT.print_longfactorization(nb_primes, primes, exponents);
1706 cout << endl;
1707 }
1708}
1709
1711 int &nb_primes, int *&primes, int *&exponents,
1712 int verbose_level)
1713{
1714 int f_v = (verbose_level >= 1);
1715 longinteger_object n, q;
1716 int p, last_prime = 2, i, r;
1718
1719 if (f_v) {
1720 cout << "factoring " << a << endl;
1721 }
1722 if (a.is_zero()) {
1723 cout << "longinteger_domain::factor a is zero" << endl;
1724 exit(1);
1725 }
1726 if (a.is_one()) {
1727 nb_primes = 0;
1728 primes = NEW_int(1);
1729 exponents = NEW_int(1);
1730 return;
1731 }
1732 a.assign_to(n);
1733 p = smallest_primedivisor(n, last_prime, verbose_level);
1734 if (p == 0) {
1735 p = n.as_int();
1736 }
1737 primes = NEW_int(1);
1738 exponents = NEW_int(1);
1739 nb_primes = 1;
1740 primes[0] = p;
1741 exponents[0] = 1;
1742 last_prime = p;
1743 integral_division_by_int(n, p, q, r);
1744 q.assign_to(n);
1745 while (!n.is_one()) {
1746 if (f_v) {
1747 cout << "remaining factor: " << n << endl;
1748 }
1749 p = smallest_primedivisor(n, last_prime, verbose_level);
1750 // if p == 0: n is prime
1751
1752 if (p == 0) {
1753 p = n.as_int();
1754 }
1755
1756 if (p == last_prime) {
1757 exponents[nb_primes - 1]++;
1758 }
1759 else {
1760 int *pr = NEW_int(nb_primes + 1);
1761 int *ex = NEW_int(nb_primes + 1);
1762 for (i = 0; i < nb_primes; i++) {
1763 pr[i] = primes[i];
1764 ex[i] = exponents[i];
1765 }
1766 FREE_int(primes);
1767 FREE_int(exponents);
1768 primes = pr;
1769 exponents = ex;
1770 primes[nb_primes] = p;
1771 exponents[nb_primes] = 1;
1772 nb_primes++;
1773 last_prime = p;
1774 }
1775
1776 if (f_v) {
1777 cout << "dividing " << n << " by " << p << endl;
1778 }
1779 integral_division_by_int(n, p, q, r);
1780 q.assign_to(n);
1781 if (f_v) {
1782 cout << "partial factorization: " << a << " = ";
1783 NT.print_factorization(nb_primes, primes, exponents);
1784 cout << " * " << n;
1785 cout << endl;
1786 }
1787 }
1788 if (f_v) {
1789 cout << "factor(): " << a << " = ";
1790 NT.print_factorization(nb_primes, primes, exponents);
1791 cout << endl;
1792 }
1793}
1794
1796 longinteger_object &m, int verbose_level)
1797{
1798 int f_v = (verbose_level >= 1);
1799 int f_vv = (verbose_level >= 2);
1800 longinteger_object a1, m1, a2, m2, a3, m3;
1801 longinteger_object u, v, g, q, r, res, minus_one;
1802 int n, rr, r1, t1, t2;
1803
1804 if (f_v) {
1805 cout << "longinteger_domain::jacobi(" << a << " over " << m << ")" << endl;
1806 }
1807 a.assign_to(a1);
1808 m.assign_to(m1);
1809 r1 = 1;
1810
1811 minus_one.create(-1, __FILE__, __LINE__);
1812 extended_gcd(a1, m1, g, u, v, verbose_level - 2);
1813 if (!g.is_one_or_minus_one()) {
1814 return 0;
1815 }
1816
1817 while (TRUE) {
1818 // we now have
1819 // jacobi(a, m) = r1 * jacobi(a1, m1);
1820 integral_division(a1, m1, q, r, verbose_level - 2);
1821 if (f_vv) {
1822 cout << r1 << " * Jacobi(" << r << ", "
1823 << m1 << ")" << endl;
1824 }
1825 n = multiplicity_of_p(r, res, 2);
1826 res.assign_to(a1);
1827 if (f_vv) {
1828 cout << r1 << " * Jacobi( 2^" << n << " * "
1829 << a1 << ", " << m1 << ")" << endl;
1830 }
1831 if (ODD(n)) {
1832 // t = (m1 * m1 - 1) >> 3 = (m1 * m1 - 1) / 8
1833 // multiply r1 by (-1) to the power t:
1834 rr = remainder_mod_int(m1, 8);
1835 if (rr == 3 || rr == 5) {
1836 r1 = -r1; // note ABS(r1) == 1
1837 }
1838 }
1839 if (f_vv) {
1840 cout << r1 << " * Jacobi(" << a1 << ", " << m1 << ")" << endl;
1841 }
1842 if (a1.is_one_or_minus_one()) {
1843 break;
1844 }
1845 // reciprocity:
1846 add(a1, minus_one, a2);
1847 add(m1, minus_one, m2);
1848 integral_division_by_int(a2, 2, a3, rr);
1849 integral_division_by_int(m2, 2, m3, rr);
1850 integral_division_by_int(a3, 2, a2, t1);
1851 integral_division_by_int(m3, 2, m2, t2);
1852 a1.assign_to(a2);
1853 m1.assign_to(a1);
1854 a2.assign_to(m1);
1855 if (ODD(t1) && ODD(t2)) {
1856 r1 = -r1;
1857 }
1858 if (f_vv) {
1859 cout << r1 << " * Jacobi(" << a1 << ", " << m1 << ")" << endl;
1860 }
1861 }
1862 if (f_v) {
1863 cout << "jacobi(" << a << ", " << m << ") = " << r1 << endl;
1864 }
1865 return r1;
1866}
1867
1870{
1871 int i, l, rr;
1872 //char *n_rep;
1873 char *r_rep;
1875
1876 l = n.len();
1877 n.assign_to(r);
1878 //n_rep = n.rep();
1879 r_rep = r.rep();
1880 while (TRUE) {
1881 for (i = l - 1; i >= 0; i--) {
1882 rr = Os.random_integer(10);
1883 r_rep[i] = (char) rr;
1884 }
1885 r.normalize();
1886 if (compare_unsigned(r, n) < 0) {
1887 break;
1888 }
1889 }
1890}
1891
1893 longinteger_object &R, int n, int verbose_level)
1894{
1895 int f_v = (verbose_level >= 1);
1896 char *str;
1897 int i;
1899
1900 if (f_v) {
1901 cout << "longinteger_domain::random_number_with_n_decimals" << endl;
1902 }
1903 str = NEW_char(n + 1);
1904 for (i = 0; i <= n; i++) {
1905 str[n - i] = '0' + Os.random_integer(10);
1906 if (i == n) {
1907 str[n - i] = '1' + Os.random_integer(9);
1908 }
1909 }
1910 str[n] = 0;
1911
1912
1913 if (f_v) {
1914 cout << "longinteger_domain::random_number_with_n_decimals "
1915 "random number = " << str << endl;
1916 }
1917
1919
1920 FREE_char(str);
1921
1922 if (f_v) {
1923 cout << "longinteger_domain::random_number_with_n_decimals done" << endl;
1924 }
1925}
1926
1927
1930 longinteger_object *&C, int Am, int An, int Bn)
1931{
1932 int i, j, k;
1933 longinteger_object a, b, c;
1934
1935 for (i = 0; i < Am; i++) {
1936 for (j = 0; j < Bn; j++) {
1937 c.create(0, __FILE__, __LINE__);
1938 for (k = 0; k < An; k++) {
1939 mult(A[i * An + k], B[k * Bn + j], a);
1940 add(a, c, b);
1941 b.assign_to(c);
1942 }
1943 c.assign_to(C[i * Bn + j]);
1944 }
1945 }
1946}
1947
1950 int Am, int An)
1951{
1952 int i, j;
1953 longinteger_object q, r;
1954 int verbose_level = 0;
1955
1956 for (i = 0; i < Am; i++) {
1957 for (j = 0; j < An; j++) {
1958 integral_division(A[i * An + j], b, q, r, verbose_level);
1959 if (!r.is_zero()) {
1960 cout << "integral division: " << b
1961 << " does not divide " << A[i * An + j] << endl;
1962 cout << "i=" << i << " j=" << j << endl;
1963 exit(1);
1964 }
1965 q.assign_to(A[i * An + j]);
1966 }
1967 }
1968}
1969
1971 ostream &ost, longinteger_object *A,
1972 int Am, int An)
1973{
1974 int i, j;
1975
1976 ost << "[";
1977 for (i = 0; i < Am; i++) {
1978 ost << "[";
1979 for (j = 0; j < An; j++) {
1980 ost << A[i * An + j];
1981 if (j < An - 1) {
1982 ost << ",";
1983 }
1984 ost << " ";
1985 }
1986 ost << "]";
1987 if (i < An - 1) {
1988 ost << ",";
1989 }
1990 ost << endl;
1991 }
1992 ost << "];" << endl;
1993}
1994
1996 ostream &ost, longinteger_object *A,
1997 int Am, int An)
1998{
1999 int i, j;
2000
2001 ost << "\\begin{array}{*{" << An << "}{r}}" << endl;
2002 for (i = 0; i < Am; i++) {
2003 for (j = 0; j < An; j++) {
2004 ost << A[i * An + j];
2005 if (j < An - 1) {
2006 ost << " & ";
2007 }
2008 }
2009 ost << "\\\\" << endl;
2010 }
2011 ost << "\\end{array}" << endl;
2012}
2013
2015 char *aa, char *bb, char *nn,
2016 longinteger_object &result, int verbose_level)
2017{
2018 int f_v = (verbose_level >= 1);
2019 longinteger_object a, b, c, d, n;
2020
2026 power_longint_mod(c, d, n, verbose_level - 1);
2027 c.assign_to(result);
2028 if (f_v) {
2029 cout << "longinteger_domain::power_mod:" << aa
2030 << " ^ " << bb << " == " << result
2031 << " mod " << nn << endl;
2032 }
2033}
2034
2035
2037 longinteger_object &result, int n)
2038{
2039 int *x;
2040 int i;
2041
2042 x = NEW_int(n);
2043 for (i = 0; i < n; i++) {
2044 x[i] = i + 1;
2045 }
2046 multiply_up(result, x, n, 0 /* verbose_level */);
2047 FREE_int(x);
2048}
2049
2051 longinteger_object &result,
2052 int n, int q, int f_semilinear)
2053{
2054 long int *x;
2055 int i, l;
2056 int p, e;
2058
2059 NT.factor_prime_power(q, p, e);
2060 l = n;
2061 if (f_semilinear) {
2062 l++;
2063 }
2064
2065 x = NEW_lint(l);
2066 for (i = 0; i < n; i++) {
2067 x[i] = NT.i_power_j_lint(q, n) - NT.i_power_j_lint(q, i);
2068 if (i == 0) {
2069 x[i] = x[i] / (q - 1);
2070 }
2071 }
2072 if (f_semilinear) {
2073 x[n] = e;
2074 }
2075
2076#if 0
2077 cout << "longinteger_domain::group_order_PGL "
2078 "factors of |PGL(n,q)| = ";
2079 int_vec_print(cout, x, l);
2080 cout << endl;
2081#endif
2082
2083 multiply_up_lint(result, x, l, 0 /* verbose_level */);
2084 FREE_lint(x);
2085}
2086
2087
2088
2089
2090
2092 longinteger_object &x, int verbose_level)
2093{
2094 int f_v = (verbose_level >= 1);
2095
2096 if (f_v) {
2097 cout << "longinteger_domain::square_root_floor" << endl;
2098 }
2099 x.freeself();
2100 longinteger_object Y, YY;
2101 int la, l, len;
2102 char c1;
2103
2104 a.normalize();
2105 if (a.sign()) {
2106 cout << "longinteger_domain::square_root_floor "
2107 "no square root, the number is negative" << endl;
2108 exit(1);
2109 }
2110 if (a.is_zero()) {
2111 x.create(0, __FILE__, __LINE__);
2112 return;
2113 }
2114
2115 la = a.len();
2116 if (ODD(la)) {
2117 la++;
2118 }
2119 len = (la >> 1) + 1;
2120 Y.sign() = FALSE;
2121 Y.len() = len;
2122 Y.rep() = NEW_char(len);
2123
2124 //Y.allocate_empty(len);
2125 //Y.s_sign() = FALSE;
2126 for (l = 0; l < len; l++) {
2127 Y.ith(l) = (char) 0;
2128 }
2129
2130 for (l = len - 1; l >= 0; l--) {
2131 for (c1 = 9; c1 >= 0; c1--) {
2132 Y.ith(l) = c1;
2133 mult(Y, Y, YY);
2134
2135 if (compare_unsigned(YY, a) <= 0) {
2136 break;
2137 }
2138 }
2139 }
2140 Y.normalize();
2141 Y.swap_with(x);
2142 if (f_v) {
2143 cout << "longinteger_domain::square_root_floor done" << endl;
2144 }
2145}
2146
2147
2148
2149
2150void longinteger_domain::print_digits(char *rep, int len)
2151{
2152 for (int h = 0; h < len; h++) {
2153 cout << (char)('0' + rep[h]) << " ";
2154 }
2155}
2156
2157
2158
2159
2160}}}
2161
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
void print_longfactorization(int nb_primes, ring_theory::longinteger_object *primes, int *exponents)
void print_factorization(int nb_primes, int *primes, int *exponents)
domain to compute with objects of type longinteger
Definition: ring_theory.h:240
void extended_gcd(longinteger_object &a, longinteger_object &b, longinteger_object &g, longinteger_object &u, longinteger_object &v, int verbose_level)
int jacobi(longinteger_object &a, longinteger_object &m, int verbose_level)
int compare(longinteger_object &a, longinteger_object &b)
void integral_division_exact(longinteger_object &a, longinteger_object &b, longinteger_object &a_over_b)
void base_b_representation(longinteger_object &a, int b, int *&rep, int &len)
int quotient_as_int(longinteger_object &a, longinteger_object &b)
void power_mod(char *aa, char *bb, char *nn, longinteger_object &result, int verbose_level)
void multiply_up(longinteger_object &a, int *x, int len, int verbose_level)
void add_mod(longinteger_object &a, longinteger_object &b, longinteger_object &c, longinteger_object &m, int verbose_level)
long int quotient_as_lint(longinteger_object &a, longinteger_object &b)
int is_less_than(longinteger_object &a, longinteger_object &b)
void subtract_signless(longinteger_object &a, longinteger_object &b, longinteger_object &c)
int multiplicity_of_p(longinteger_object &a, longinteger_object &residue, int p)
void power_longint_mod(longinteger_object &a, longinteger_object &n, longinteger_object &m, int verbose_level)
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)
void mult(longinteger_object &a, longinteger_object &b, longinteger_object &c)
void group_order_PGL(longinteger_object &result, int n, int q, int f_semilinear)
long int smallest_primedivisor(longinteger_object &a, int p_min, int verbose_level)
void random_number_with_n_decimals(longinteger_object &R, int n, int verbose_level)
void integral_division_by_lint(longinteger_object &a, long int b, longinteger_object &q, long int &r)
void matrix_entries_integral_division_exact(longinteger_object *A, longinteger_object &b, int Am, int An)
void mult_in_place(longinteger_object &a, longinteger_object &b)
void square_root(longinteger_object &a, longinteger_object &sqrt_a, int verbose_level)
void mult_mod(longinteger_object &a, longinteger_object &b, longinteger_object &c, longinteger_object &m, int verbose_level)
void random_number_less_than_n(longinteger_object &n, longinteger_object &r)
void create_q_to_the_n(longinteger_object &a, int q, int n)
void square_root_floor(longinteger_object &a, longinteger_object &x, int verbose_level)
void matrix_product(longinteger_object *A, longinteger_object *B, longinteger_object *&C, int Am, int An, int Bn)
void integral_division(longinteger_object &a, longinteger_object &b, longinteger_object &q, longinteger_object &r, int verbose_level)
void subtract_in_place(longinteger_object &a, longinteger_object &b)
void factor(longinteger_object &a, int &nb_primes, int *&primes, int *&exponents, int verbose_level)
void multiply_up_lint(longinteger_object &a, long int *x, int len, int verbose_level)
void add_in_place(longinteger_object &a, longinteger_object &b)
void factor_into_longintegers(longinteger_object &a, int &nb_primes, longinteger_object *&primes, int *&exponents, int verbose_level)
void matrix_print_tex(std::ostream &ost, longinteger_object *A, int Am, int An)
void power_int_mod(longinteger_object &a, int n, longinteger_object &m)
void Dedekind_number(longinteger_object &Dnq, int n, int q, int verbose_level)
void subtract_signless_in_place(longinteger_object &a, longinteger_object &b)
void matrix_print_GAP(std::ostream &ost, longinteger_object *A, int Am, int An)
int compare_unsigned(longinteger_object &a, longinteger_object &b)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void create_from_base_10_string(const char *str, int verbose_level)
void create(long int i, const char *file, int line)
#define FREE_OBJECTS(p)
Definition: foundations.h:652
#define FREE_int(p)
Definition: foundations.h:640
#define NEW_char(n)
Definition: foundations.h:632
#define NEW_int(n)
Definition: foundations.h:625
#define NEW_OBJECTS(type, n)
Definition: foundations.h:639
#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
#define FREE_char(p)
Definition: foundations.h:646
#define FREE_lint(p)
Definition: foundations.h:642
#define NEW_lint(n)
Definition: foundations.h:628
#define MAXIMUM(x, y)
Definition: foundations.h:217
the orbiter library for the classification of combinatorial objects