Orbiter 2022
Combinatorial Objects
longinteger.cpp
Go to the documentation of this file.
1// longinteger.cpp
2//
3// Anton Betten
4// 19.11.1999
5// moved from D2 to ORBI Nov 15, 2007
6
8#include "discreta.h"
9
10using namespace std;
11
12
13#undef DEBUG_LONGINTEGER_DIVISION
14#undef DEBUG_LONGINTEGER_COMPARE
15
16namespace orbiter {
17namespace layer2_discreta {
18
19
20static void subtract_signless(longinteger &x, longinteger &y, longinteger &z);
21static int do_division(longinteger& r, longinteger *d);
22
24{
25 k = LONGINTEGER;
26 clearself();
27}
28
30{
31 int l;
32 char *p;
33 ostringstream s;
34
35 s << a << ends;
36 l = s.str().length();
37 p = new char [l + 1];
38 s.str().copy(p, l, 0);
39 p[l] = 0;
40 longinteger x(p);
41 swap(x);
42 delete [] p;
43}
44
46{
47 // cout << "longinteger::longinteger(char *s)" << s << endl;
48 k = LONGINTEGER;
49 clearself();
50 if (s[0] == '-')
51 allocate(TRUE, s + 1);
52 else
53 allocate(FALSE, s);
55}
56
58 // copy constructor: this := x
59{
60 cout << "longinteger::copy constructor for object: "
61 << const_cast<discreta_base &>(x) << "\n";
62 clearself();
63 const_cast<discreta_base &>(x).copyobject_to(*this);
64}
65
67 // copy assignment
68{
69 // cout << "longinteger::operator = (copy assignment)" << endl;
70 copyobject(const_cast<discreta_base &>(x));
71 return *this;
72}
73
75{
76 new(this) longinteger;
77 k = LONGINTEGER;
78}
79
81{
82 // cout << "~longinteger()\n";
84}
85
87{
88 // cout << "longinteger::freeself_longinteger()\n";
89 if (s_rep())
90 delete (char *) s_rep();
91 self.longinteger_rep = NULL;
92}
93
95{
96 return LONGINTEGER;
97}
98
100{
101 // cout << "longinteger::copyobject_to()\n";
102 x.freeself();
103
105 xx.allocate_internal(s_sign(), s_len(), &s_p(0));
107}
108
109ostream& longinteger::print(ostream& ost)
110{
111 int i, l;
112 char c;
113
114#ifdef PRINT_WITH_TYPE
115 ost << "(LONGINTEGER, ";
116#endif
117 if (s_rep() == NULL) {
118 ost << "NULL";
119 }
120 else {
121 if (s_sign())
122 ost << "-";
123 l = s_len();
124 for (i = l - 1; i >= 0; i--) {
125 c = '0' + s_rep()->p[i];
126 ost << c;
127#ifdef LONGINTEGER_PRINT_DOTS
128 if (i && (i % LONGINTEGER_DIGITS_FOR_DOT) == 0)
129 ost << ".";
130#endif
131 }
132 }
133#ifdef PRINT_WITH_TYPE
134 ost << ")";
135#endif
136 return ost;
137}
138
140{
141 return self.longinteger_rep;
142}
143
145{
146 return self.longinteger_rep->sign;
147}
148
150{
151 return self.longinteger_rep->len;
152}
153
155{
156 return self.longinteger_rep->p[i];
157}
158
159void longinteger::allocate(int sign, const char *p)
160{
161 int i, l;
162
163 l = strlen(p);
164 if (s_kind() != LONGINTEGER) {
165 cout << "longinteger::allocate() s_kind() != LONGINTEGER\n";
166 exit(1);
167 }
169 s_sign() = sign;
170 s_len() = l;
171 for (i = 0; i < l; i++) {
172 s_p(i) = p[l - 1 - i] - '0';
173 }
174}
175
176void longinteger::allocate_internal(int sign, int len, const char *p)
177{
178 int i;
179
180 if (s_kind() != LONGINTEGER) {
181 cout << "longinteger::allocate_internal() s_kind() != LONGINTEGER\n";
182 exit(1);
183 }
184 allocate_empty(len);
185 s_sign() = sign;
186 for (i = 0; i < len; i++) {
187 s_p(i) = p[i];
188 }
189}
190
192{
193 int i;
194
195 if (s_kind() != LONGINTEGER) {
196 cout << "longinteger::allocate_empty() s_kind() != LONGINTEGER\n";
197 exit(1);
198 }
200 new char[sizeof(LONGINTEGER_REPRESENTATION) + len];
201 s_sign() = FALSE;
202 s_len() = len;
203 for (i = 0; i < len; i++) {
204 s_p(i) = (char) 0;
205 }
206}
207
209{
210 int i, l;
211
212 l = s_len();
213 for (i = l - 1; i > 0; i--) {
214 if (s_p(i) != 0)
215 break;
216 }
217 s_len() = i + 1;
218}
219
220
222{
223 int sa, sb;
224
225 if (s_kind() != LONGINTEGER) {
226 cout << "longinteger::compare_with() s_kind() != LONGINTEGER\n";
227 exit(1);
228 }
229 if (b.s_kind() != LONGINTEGER) {
230 if (b.s_kind() != INTEGER) {
231 cout << "longinteger::compare_with() "
232 "b is neither longinteger nor integer\n";
233 exit(1);
234 }
235 longinteger b1;
236
237 b1.homo_z(b.s_i_i());
238 return compare_with(b1);
239 }
241 int r;
242
243 sa = s_sign();
244 sb = B.s_sign();
245 if (sa != sb) {
246 if (sa)
247 return -1;
248 else
249 return 1;
250 }
252#ifdef DEBUG_LONGINTEGER_COMPARE
253 cout << "longinteger::compare_with_unsigned() returns " << r << "\n";
254#endif
255 if (sa)
256 return -1 * r;
257 else
258 return r;
259}
260
262{
263 int la, lb, l, i, d1, d2;
264
265 la = s_len();
266 lb = b.s_len();
267 l = MAXIMUM(la, lb);
268#ifdef DEBUG_LONGINTEGER_COMPARE
269 cout << "longinteger::compare_with_unsigned()\n";
270 cout << "la=" << la << " lb=" << lb << endl;
271#endif
272
273 for (i = l - 1; i >= 0; i--) {
274 if (i < la)
275 d1 = s_p(i);
276 else
277 d1 = 0;
278 if (i < lb)
279 d2 = b.s_p(i);
280 else
281 d2 = 0;
282#ifdef DEBUG_LONGINTEGER_COMPARE
283 cout << "i=" << i << "d1=" << d1 << "d2=" << d2 << endl;
284#endif
285 if (d1 < d2)
286 return -1;
287 else if (d1 > d2)
288 return 1;
289 }
290 return 0;
291}
292
294{
295 longinteger Y;
296 int len;
297
298 if (s_kind() != LONGINTEGER) {
299 cout << "longinteger::mult_to() this is not a longinteger\n";
300 exit(1);
301 }
302 if (x.s_kind() == INTEGER) {
303 longinteger x1;
304
305 x1.homo_z(x.s_i_i());
306 mult_to(x1, y);
307 return;
308 }
309 if (x.s_kind() != LONGINTEGER) {
310 cout << "longinteger::mult_to() x is not a longinteger\n";
311 exit(1);
312 }
314
315 len = s_len() + X.s_len() + 2;
316 Y.allocate_empty(len);
317 if ((s_sign() && X.s_sign()) || (!s_sign() && !X.s_sign())) {
318 Y.s_sign() = FALSE;
319 }
320 else {
321 Y.s_sign() = TRUE;
322 }
323
324 int la, lb;
325 char cb, c1, carry;
326
327 for (lb = 0; lb < X.s_len(); lb++) {
328 cb = X.s_p(lb);
329 carry = 0;
330 for (la = 0; la < s_len(); la++) {
331 c1 = s_p(la) * cb + carry + Y.s_p(la + lb);
332 if (c1 > 100) {
333 cout << "longinteger:mult_to() error: c1 >= 100\n";
334 exit(1);
335 }
336 carry = c1 / 10;
337 Y.s_p(la + lb) = c1 % 10;
338 }
339 if (carry) {
340 if (Y.s_p(lb + s_len()) != 0) {
341 cout << "longinteger:mult_to() error: "
342 "carry && Y.s_p(lb + s_len()) != 0\n";
343 exit(1);
344 }
345 Y.s_p(lb + s_len()) = carry;
346 }
347 }
349 y.freeself();
350 Y.swap(y);
351}
352
354{
355 if (s_kind() != LONGINTEGER) {
356 cout << "longinteger::invert_to() this is not a longinteger\n";
357 exit(1);
358 }
359 cout << "longinteger::invert_to() not yet implemented\n";
360 return FALSE;
361}
362
364{
365 longinteger Y;
366 int len, sign_a, sign_b, cmp_a_b, l;
367 char ca, cb, c1, carry;
368
369 if (s_kind() != LONGINTEGER) {
370 cout << "longinteger::add_to() this is not a longinteger\n";
371 exit(1);
372 }
373 if (x.s_kind() == INTEGER) {
374 longinteger x1;
375
376 x1.homo_z(x.s_i_i());
377 add_to(x1, y);
378 return;
379 }
380 if (x.s_kind() != LONGINTEGER) {
381 cout << "longinteger::add_to() x is not a longinteger\n";
382 exit(1);
383 }
385 len = MAXIMUM(s_len(), X.s_len()) + 1;
386 Y.allocate_empty(len);
387 sign_a = s_sign();
388 sign_b = X.s_sign();
389 if ((sign_a && sign_b) || (!sign_a && !sign_b)) {
390 Y.s_sign() = sign_a;
391 }
392 else {
393 // mixed signs: subtraction */
394 cmp_a_b = compare_with_unsigned(X);
395 if (cmp_a_b < 0) {
396 // |this| < |X|
397
398 subtract_signless(X, *this, Y);
399 Y.s_sign() = X.s_sign();
400 goto l_exit;
401 }
402 else if (cmp_a_b > 0) {
403 // |this| > |X|
404
405 subtract_signless(*this, X, Y);
406 Y.s_sign() = s_sign();
407 goto l_exit;
408 }
409 else {
410 // |a| = |b|
411 Y.s_len() = 1;
412 Y.s_sign() = FALSE;
413 Y.s_p(0) = 0;
414 goto l_exit;
415 }
416 }
417 carry = 0;
418 for (l = 0; l < len; l++) {
419 if (l < s_len())
420 ca = s_p(l);
421 else
422 ca = 0;
423 if (l < X.s_len())
424 cb = X.s_p(l);
425 else
426 cb = 0;
427 c1 = ca + cb + carry;
428 if (c1 >= 10)
429 carry = 1;
430 else
431 carry = 0;
432 Y.s_p(l) = c1 % 10;
433 }
434l_exit:
436 y.freeself();
437 Y.swap(y);
438}
439
440static void subtract_signless(longinteger &x, longinteger &y, longinteger &z)
441// z := x - y (signless)
442// assumes |x| > |y|
443{
444 int len, l;
445 char ca, cb, carry;
446
447 len = x.s_len();
449 z.allocate_empty(len);
450 z.s_sign() = FALSE;
451 carry = 0;
452 for (l = 0; l < len; l++) {
453 if (l < y.s_len())
454 cb = y.s_p(l);
455 else
456 cb = 0;
457 cb += carry;
458 ca = x.s_p(l);
459 if (cb > ca) {
460 ca += 10;
461 carry = 1;
462 }
463 else
464 carry = 0;
465 z.s_p(l) = ca - cb;
466 }
468}
469
471{
472 if (s_kind() != LONGINTEGER) {
473 cout << "longinteger::negate_to() this not an integer\n";
474 exit(1);
475 }
476 x.freeself();
478
479 X = *this;
480 if (X.is_zero())
481 return;
482 if (X.s_sign())
483 X.s_sign() = FALSE;
484 else
485 X.s_sign() = TRUE;
486}
487
489{
490 longinteger x("0");
491 swap(x);
492}
493
495{
496 longinteger x("1");
497 swap(x);
498}
499
501{
502 longinteger x("-1");
503 swap(x);
504}
505
507{
508 char str[1000];
509
510 snprintf(str, 1000, "%d", z);
511
512 longinteger x(str);
513 swap(x);
514}
515
517{
518 longinteger x = ("1");
519 *this += x;
520}
521
523{
524 longinteger x = ("-1");
525 *this += x;
526}
527
529{
530 longinteger x = ("0");
531
532 if (compare_with(x) == 0)
533 return TRUE;
534 return FALSE;
535}
536
538{
539 longinteger x = ("1");
540
541 if (compare_with(x) == 0)
542 return TRUE;
543 return FALSE;
544}
545
547{
548 longinteger x = ("-1");
549
550 if (compare_with(x) == 0)
551 return TRUE;
552 return FALSE;
553}
554
556{
557 int d = (int) s_p(0);
558
559 return EVEN(d);
560}
561
563{
564 int d = (int) s_p(0);
565
566 return ODD(d);
567}
568
570{
571 if (s_kind() != LONGINTEGER) {
572 cout << "longinteger::compare_with_euclidean "
573 "s_kind() != LONGINTEGER\n";
574 exit(1);
575 }
576 if (b.s_kind() != LONGINTEGER) {
577 if (b.s_kind() != INTEGER) {
578 cout << "longinteger::compare_with_euclidean "
579 "b is neither longinteger nor integer\n";
580 exit(1);
581 }
582 longinteger b1;
583
584 b1.homo_z(b.s_i_i());
585 return compare_with_euclidean(b1);
586 }
588 int r;
590 // cout << "longinteger::compare_with_unsigned() returns " << r << "\n";
591 return r;
592}
593
595 discreta_base &q, discreta_base &r, int verbose_level)
596{
597 if (s_kind() != LONGINTEGER) {
598 cout << "longinteger::integral_division "
599 "this is not a longinteger\n";
600 exit(1);
601 }
602 if (x.s_kind() == INTEGER) {
603 longinteger x1;
604
605 x1.homo_z(x.s_i_i());
606 integral_division(x1, q, r, verbose_level);
607 return;
608 }
609 if (x.s_kind() != LONGINTEGER) {
610 cout << "longinteger::integral_division "
611 "x is not a longinteger\n";
612 exit(1);
613 }
615 longinteger Q, R, r1, r2, d[10], dm[10];
616 int len, sign_x, sign_r, i, l1, l, idx;
617
620 len = s_len() - X.s_len() + 1;
621 if (len <= 0) {
622 Q.zero();
623 R = *this;
624 q.freeself();
625 r.freeself();
626 Q.swap(q);
627 R.swap(r);
628 return;
629 }
630 Q.allocate_empty(len);
631 Q.s_sign() = FALSE;
632
633 if (s_sign() == X.s_sign()) {
634 Q.s_sign() = FALSE;
635 sign_r = s_sign();
636 }
637 else {
638 Q.s_sign() = TRUE;
639 sign_r = s_sign();
640 }
641
642 sign_x = X.s_sign();
643 X.s_sign() = FALSE;
644 for (i = 0; i < 10; i++) {
645#ifdef DEBUG_LONGINTEGER_DIVISION
646 cout << "i = " << i << " ";
647#endif
648 r1.homo_z(i);
649#ifdef DEBUG_LONGINTEGER_DIVISION
650 cout << "r1 = " << r1 << " ";
651#endif
652 d[i].mult(X, r1);
653#ifdef DEBUG_LONGINTEGER_DIVISION
654 cout << "d[i] = " << d[i] << " ";
655#endif
656 d[i].negate_to(dm[i]);
657#ifdef DEBUG_LONGINTEGER_DIVISION
658 cout << "dm[i] = " << dm[i] << endl;
659#endif
660 }
661 X.s_sign() = sign_x;
662
663 // load r1 with leading X.s_len() digits of this:
664 len = X.s_len();
665 r1.freeself();
666 r1.allocate_empty(len);
667 l1 = s_len() - len;
668 for (l = 0; l < len; l++) {
669 r1.s_p(l) = s_p(l1 + l);
670 }
671#ifdef DEBUG_LONGINTEGER_DIVISION
672 cout << "r1 = " << r1 << endl;
673#endif
674
675
676 // main loop containing all divisions:
677 for ( ; l1 >= 0; l1--) {
678#ifdef DEBUG_LONGINTEGER_DIVISION
679 cout << "dividing r1=" << r1 << endl;
680#endif
681 idx = do_division(r1, d);
682#ifdef DEBUG_LONGINTEGER_DIVISION
683 cout << "do_division, idx = " << idx << endl;
684 cout << "Q[" << l1 << "]=" << idx << endl;
685#endif
686
687 Q.s_p(l1) = (char) idx;
688#ifdef DEBUG_LONGINTEGER_DIVISION
689 cout << "calling r2.add()" << endl;
690#endif
691 r2.add(r1, dm[idx]);
692#ifdef DEBUG_LONGINTEGER_DIVISION
693 cout << "r2=" << r2 << endl;
694#endif
695 if (l1 == 0)
696 break;
697
698 // put r2 into r1, shift up by one digit
699 // and append the next digit l1 - 1 of this.
701 len = r2.s_len() + 1;
702 r1.allocate_empty(len);
703 for (l = 0; l < r2.s_len(); l++) {
704 r1.s_p(l + 1) = r2.s_p(l);
705 }
706 r1.s_p(0) = s_p(l1 - 1);
708 }
711 r2.s_sign() = sign_r;
712 q.freeself();
713 r.freeself();
714 Q.swap(q);
715 r2.swap(r);
716}
717
718static int do_division(longinteger& r, longinteger *d)
719{
720 int i, cmp;
721
722 for (i = 9; i >= 0; i--) {
723#ifdef DEBUG_LONGINTEGER_DIVISION
724 cout << "do_division, i = " << i << " r=" << r << " d[i]=" << d[i] << endl;
725#endif
726 cmp = r.compare_with(d[i]);
727 if (cmp >= 0)
728 return i;
729 }
730 cout << "longinteger do_division() not found\n";
731 exit(1);
732}
733
735{
736 if (s_kind() != LONGINTEGER) {
737 cout << "longinteger::square_root_floor "
738 "this is not a longinteger\n";
739 exit(1);
740 }
741 x.freeself();
743 longinteger Y, YY;
744 int la, l, len;
745 char c1;
746
748 if (s_sign()) {
749 cout << "longinteger::square_root_floor "
750 "no square root, the number is negative\n";
751 exit(1);
752 }
753 if (is_zero()) {
754 X.allocate(FALSE, "0");
755 return;
756 }
757
758 la = s_len();
759 if (ODD(la))
760 la++;
761 len = (la >> 1) + 1;
762 Y.allocate_empty(len);
763 Y.s_sign() = FALSE;
764 for (l = 0; l < len; l++) {
765 Y.s_p(l) = (char) 0;
766 }
767
768 for (l = len - 1; l >= 0; l--) {
769 for (c1 = 9; c1 >= 0; c1--) {
770 Y.s_p(l) = c1;
771 YY.mult(Y, Y);
772 if (YY.compare_with(*this) <= 0)
773 break;
774 }
775 }
777 Y.swap(X);
778}
779
781// $M_n = 2^n - 1$
782{
783 longinteger a = "2", b = "-1";
784
785 a.power_int(n);
786 a += b;
787 // cout << "Mersenne number M_" << n << "=" << a << endl;
788 swap(a);
789 return *this;
790}
791
793// $F_n = 2^{2^n} + 1$
794{
795 longinteger a = "2", b = "1", l = "2";
796
797 l.power_int(n);
798 // cout << "l=" << l << endl;
800 a += b;
801 // cout << "Fermat number F_" << n << "=" << a << endl;
802 swap(a);
803 return *this;
804}
805
807{
808 char *p;
809 int x, l;
810 ostringstream s;
811
812 s << *this << ends;
813 // cout << "str=(" << str << ")" << endl;
814 l = s.str().length();
815 p = new char [l + 1];
816 s.str().copy(p, l, 0);
817 p[l] = 0;
818 sscanf(p, "%d", &x);
819 delete [] p;
820 return x;
821
822}
823
825{
826 if (s_len() < 6) {
827 int i = s_i();
828 x.m_i(i);
829 return TRUE;
830 }
831 else
832 return FALSE;
833}
834
836{
837 longinteger P, Q, R;
838
839 P.homo_z(p);
840 integral_division(P, Q, R, 0);
841 return R.s_i();
842}
843
845{
846 longinteger P, Q, R;
847 int n = 0;
848
849 P.homo_z(p);
850 while (TRUE) {
851 integral_division(P, Q, R, 0);
852 if (!R.is_zero())
853 break;
854 n++;
855 swap(Q);
856 }
857 return n;
858}
859
861{
862 longinteger D, Q, R;
863
864 D.homo_z(d);
865 integral_division(D, Q, R, 0);
866 swap(Q);
867}
868
869int longinteger::Lucas_test_Mersenne(int m, int verbose_level)
870{
871 int f_v = (verbose_level >= 1);
872 int i;
873 longinteger s("4"), m2("-2"), t;
874
875 Mersenne(m);
876 if (f_v)
877 cout << "s_0 = " << s << endl;
878 for (i = 1; i <= m - 2; i++) {
879 t.mult(s, s);
880 t += m2;
881 t.modulo(*this);
882 s = t;
883 if (f_v)
884 cout << "s_" << i << " = " << s << endl;
885 }
886 if (s.is_zero())
887 return TRUE;
888 else
889 return FALSE;
890}
891
892}}
893
DISCRETA base class. All DISCRETA classes are derived from this class.
Definition: discreta.h:382
void add(discreta_base &x, discreta_base &y)
Definition: base.cpp:674
void mult(discreta_base &x, discreta_base &y)
Definition: base.cpp:367
void swap(discreta_base &a)
Definition: base.cpp:179
void modulo(discreta_base &p)
Definition: base.cpp:964
void copyobject(discreta_base &x)
Definition: base.cpp:194
discreta_base & power_int(int l)
Definition: base.cpp:447
discreta_base & power_longinteger(longinteger &l)
Definition: base.cpp:526
DISCRETA integer class.
Definition: discreta.h:667
DISCRETA class for integers of arbitrary magnitude.
Definition: discreta.h:727
std::ostream & print(std::ostream &)
void integral_division(discreta_base &x, discreta_base &q, discreta_base &r, int verbose_level)
longinteger & operator=(const discreta_base &x)
Definition: longinteger.cpp:66
int compare_with_unsigned(longinteger &b)
void allocate_internal(int sign, int len, const char *p)
void mult_to(discreta_base &x, discreta_base &y)
int compare_with_euclidean(discreta_base &b)
void copyobject_to(discreta_base &x)
Definition: longinteger.cpp:99
void add_to(discreta_base &x, discreta_base &y)
void square_root_floor(discreta_base &x)
LONGINTEGER_REPRESENTATION * s_rep()
int Lucas_test_Mersenne(int m, int verbose_level)
void allocate(int sign, const char *p)
#define LONGINTEGER_DIGITS_FOR_DOT
Definition: discreta.h:717
#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 MAXIMUM(x, y)
Definition: foundations.h:217
@ LONGINTEGER
LONGINTEGER.
Definition: discreta.h:65
the orbiter library for the classification of combinatorial objects
DISCRETA internal class to represent long integers.
Definition: discreta.h:365
LONGINTEGER_REPRESENTATION * longinteger_rep
Definition: discreta.h:359