1 //==============================================================================================
2 //
3 // This file is part of LiDIA --- a library for computational number theory
4 //
5 // Copyright (c) 1994--2001 the LiDIA Group. All rights reserved.
6 //
7 // See http://www.informatik.tu-darmstadt.de/TI/LiDIA/
8 //
9 //----------------------------------------------------------------------------------------------
10 //
11 // $Id$
12 //
13 // Author : Andreas Mueller (AM), Volker Mueller (VM)
14 // Changes : See CVS log
15 //
16 //==============================================================================================
17
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 #include "LiDIA/rational_factorization.h"
23
24
25
26 #ifdef LIDIA_NAMESPACE
27 namespace LiDIA {
28 #endif
29
30
31
32 const unsigned int rf_single_factor::dont_know = 2;
33 const unsigned int rf_single_factor::prime = 1;
34 const unsigned int rf_single_factor::not_prime = 0;
35
36 int rational_factorization::info = 0;
37
38
39
40 rf_single_factor &
operator =(const rf_single_factor & x)41 rf_single_factor::operator = (const rf_single_factor & x)
42 {
43 single_base.assign(x.single_base);
44 single_exponent = x.single_exponent;
45 factor_state = x.factor_state;
46 return *this;
47 }
48
49
50
51 bool
operator <(const rf_single_factor & a,const rf_single_factor & b)52 operator < (const rf_single_factor & a, const rf_single_factor & b)
53 {
54 return (a.single_base < b.single_base);
55 }
56
57
58
59 bool
operator <=(const rf_single_factor & a,const rf_single_factor & b)60 operator <= (const rf_single_factor & a, const rf_single_factor & b)
61 {
62 return (a.single_base <= b.single_base);
63 }
64
65
66
67 bool
operator ==(const rf_single_factor & a,const rf_single_factor & b)68 operator == (const rf_single_factor & a, const rf_single_factor & b)
69 {
70 return (a.single_base == b.single_base);
71 }
72
73
74
75 void
swap(rf_single_factor & a,rf_single_factor & b)76 swap (rf_single_factor & a, rf_single_factor & b)
77 {
78 rf_single_factor c;
79
80 c = a;
81 a = b;
82 b = c;
83 }
84
85
86
87 std::istream &
operator >>(std::istream & in,rf_single_factor & f)88 operator >> (std::istream &in, rf_single_factor &f)
89 {
90 bigint hb;
91 int he;
92 char c;
93
94 in >> c;
95
96 if (c != '(') {
97 lidia_error_handler("rational_factorization", "operator >>::(expected");
98 return (in);
99 }
100 else {
101 in >> hb >> c;
102 if (c != ',') {
103 lidia_error_handler("rational_factorization", "operator >>::, expected");
104 return (in);
105 }
106 in >> he >> c;
107 while (c != ')') in >> c;
108 }
109
110 if (!he) {
111 f.single_exponent = 1;
112 f.single_base = 1;
113 f.factor_state = rf_single_factor::prime;
114 }
115 else {
116 f.factor_state = rf_single_factor::dont_know;
117 f.single_exponent = he;
118
119 if (hb.is_zero()) {
120 lidia_error_handler("rational_factorization", "factor 0 not allowed");
121 return (in);
122 }
123
124 f.single_base = hb;
125 }
126
127 return in;
128 }
129
130
131
132 void
pretty_print(std::ostream & out)133 rational_factorization::pretty_print (std::ostream &out)
134 {
135 int i;
136
137 int length = no_of_comp()-1;
138 factors.sort();
139
140 for (i = 0; i < length; i++) {
141 out << factors[i].single_base;
142
143 if (factors[i].single_exponent != 1) {
144 out << "^" << factors[i].single_exponent;
145 }
146
147 out << " * ";
148 }
149
150 out << factors[length].single_base;
151
152 if (factors[length].single_exponent != 1) {
153 out << "^" << factors[length].single_exponent;
154 }
155
156 }
157
158
159
160 std::ostream &
operator <<(std::ostream & out,const rf_single_factor & f)161 operator << (std::ostream &out, const rf_single_factor &f)
162 {
163 out << "(";
164 out << f.single_base;
165 out << ",";
166 out << f.single_exponent;
167 out << ")";
168
169 return out;
170 }
171
172
173
rational_factorization()174 rational_factorization::rational_factorization ()
175 {
176 factors.set_mode(EXPAND);
177 isign = 0;
178 decomp_state = rf_single_factor::dont_know;
179 }
180
181
182
rational_factorization(int n,int exp)183 rational_factorization::rational_factorization (int n, int exp)
184 {
185 factors.set_mode(EXPAND);
186
187 if (n == 0) {
188 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
189 return;
190 }
191
192 if (n > 0) {
193 isign = 1;
194 factors[0].single_base = bigint(n);
195 }
196 else {
197 isign = -1;
198 factors[0].single_base = bigint(-n);
199 }
200 if (!(exp & 1))
201 isign = 1;
202
203 if (factors[0].single_base.is_one() || exp == 0) {
204 factors[0].single_base.assign_one();
205 exp = 1;
206 factors[0].factor_state = rf_single_factor::prime;
207 decomp_state = rf_single_factor::prime;
208 }
209 else {
210 decomp_state = rf_single_factor::dont_know;
211 factors[0].factor_state = rf_single_factor::dont_know;
212 }
213
214 factors[0].single_exponent = exp;
215 }
216
217
218
rational_factorization(unsigned int n,int exp)219 rational_factorization::rational_factorization (unsigned int n, int exp)
220 {
221 factors.set_mode(EXPAND);
222
223 if (n == 0) {
224 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
225 return;
226 }
227
228 isign = 1;
229
230 if (n == 1 || exp == 0) {
231 factors[0]. single_base.assign_one();
232 exp = 1;
233 factors[0].factor_state = rf_single_factor::prime;
234 decomp_state = rf_single_factor::prime;
235 }
236 else {
237 factors[0].factor_state = rf_single_factor::dont_know;
238 decomp_state = rf_single_factor::dont_know;
239 }
240 factors[0].single_base = bigint(static_cast<unsigned long>(n));
241 factors[0].single_exponent = exp;
242 }
243
244
245
rational_factorization(long n,int exp)246 rational_factorization::rational_factorization (long n, int exp)
247 {
248 factors.set_mode(EXPAND);
249
250 if (n == 0) {
251 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
252 return;
253 }
254
255 if (n > 0) {
256 isign = 1;
257 factors[0].single_base = bigint(n);
258 }
259 else {
260 isign = -1;
261 factors[0].single_base = bigint(-n);
262 }
263 if (!(exp & 1))
264 isign = 1;
265
266 if (factors[0].single_base.is_one() || exp == 0) {
267 factors[0].single_base.assign_one();
268 exp = 1;
269 factors[0].factor_state = rf_single_factor::prime;
270 decomp_state = rf_single_factor::prime;
271 }
272 else {
273 decomp_state = rf_single_factor::dont_know;
274 factors[0].factor_state = rf_single_factor::dont_know;
275 }
276
277 factors[0].single_exponent = exp;
278 }
279
280
281
rational_factorization(unsigned long n,int exp)282 rational_factorization::rational_factorization (unsigned long n, int exp)
283 {
284 factors.set_mode(EXPAND);
285
286 if (n == 0) {
287 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
288 return;
289 }
290 isign = 1;
291 if (n == 1 || exp == 0) {
292 factors[0].single_base.assign_one();
293 exp = 1;
294 decomp_state = rf_single_factor::prime;
295 factors[0].factor_state = rf_single_factor::prime;
296 }
297 else {
298 decomp_state = rf_single_factor::dont_know;
299 factors[0].factor_state = rf_single_factor::dont_know;
300 }
301 factors[0].single_base = bigint(n);
302 factors[0].single_exponent = exp;
303 }
304
305
306
rational_factorization(const bigint & n,int expo)307 rational_factorization::rational_factorization (const bigint & n, int expo)
308 {
309 factors.set_mode(EXPAND);
310
311 if (n.is_zero()) {
312 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
313 return;
314 }
315
316 if (expo == 0) {
317 assign(1);
318 return;
319 }
320
321 if (n.is_gt_zero()) {
322 isign = 1;
323 factors[0].single_base = n;
324 }
325 else {
326 isign = -1;
327 factors[0].single_base = -n;
328 }
329
330 if (!(expo & 1)) // exponent is even
331 isign = 1;
332
333 if (factors[0].single_base.is_one()) {
334 factors[0].factor_state = rf_single_factor::prime;
335 factors[0].single_exponent = 1;
336 decomp_state = rf_single_factor::prime;
337 }
338 else {
339 decomp_state = rf_single_factor::dont_know;
340 factors[0].factor_state = rf_single_factor::dont_know;
341 factors[0].single_exponent = expo;
342 }
343 }
344
345
346
rational_factorization(const bigrational & n,int expo)347 rational_factorization::rational_factorization (const bigrational & n, int expo)
348 {
349 factors.set_mode(EXPAND);
350
351 if (!(expo & 1))
352 isign = 1;
353 else
354 isign = n.sign();
355 decomp_state = rf_single_factor::dont_know;
356
357 if (expo == 0) {
358 assign(1);
359 return;
360 }
361
362 if (!n.denominator().is_one()) {
363 factors[0].single_base = n.denominator();
364 factors[0].single_exponent = -expo;
365 factors[0].factor_state = rf_single_factor::dont_know;
366 }
367
368 if (!abs(n.numerator()).is_one()) {
369 factors[1].single_base = abs(n.numerator());
370 factors[1].single_exponent = expo;
371 factors[1].factor_state = rf_single_factor::dont_know;
372 }
373
374 compose();
375 }
376
377
378
rational_factorization(const rational_factorization & f,int exp)379 rational_factorization::rational_factorization (const rational_factorization & f,
380 int exp)
381 {
382 int i, l = f.no_of_comp();
383
384 if (exp == 0) {
385 assign(1);
386 return;
387 }
388
389 factors.set_mode(EXPAND);
390 factors = f.factors;
391 for (i = 0; i < l; i++)
392 factors[i].single_exponent *= exp;
393 isign = f.isign;
394 decomp_state = f.decomp_state;
395 }
396
397
398
~rational_factorization()399 rational_factorization::~rational_factorization ()
400 {
401 }
402
403
404 rational_factorization &
operator =(const rational_factorization & f)405 rational_factorization::operator = (const rational_factorization & f)
406 {
407 factors = f.factors;
408 isign = f.isign;
409 decomp_state = f.decomp_state;
410
411 return *this;
412 }
413
414
415
416 void
assign(long n,int exp)417 rational_factorization::assign (long n, int exp)
418 {
419 if (n == 0) {
420 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
421 return;
422 }
423
424 factors.set_size(1);
425
426 if (n > 0) {
427 isign = 1;
428 factors[0].single_base = bigint(n);
429 }
430 else {
431 isign = -1;
432 factors[0].single_base = bigint(-n);
433 }
434
435 if (!(exp & 1))
436 isign = 1;
437
438 if (exp == 0)
439 factors[0].single_base = bigint(1);
440
441 if (factors[0].single_base.is_one()) {
442 factors[0].factor_state = rf_single_factor::prime;
443 exp = 1;
444 decomp_state = rf_single_factor::prime;
445 }
446 else {
447 decomp_state = rf_single_factor::dont_know;
448 factors[0].factor_state = rf_single_factor::dont_know;
449 }
450 factors[0].single_exponent = exp;
451 }
452
453
454
455 void
assign(const bigint & n,int expo)456 rational_factorization::assign (const bigint & n, int expo)
457 {
458 if (n.is_zero()) {
459 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
460 return;
461 }
462
463 if (expo == 0) {
464 assign(1L);
465 return;
466 }
467
468 factors.set_size(1);
469
470 if (n.is_gt_zero()) {
471 isign = 1;
472 factors[0].single_base = n;
473 }
474 else {
475 isign = -1;
476 factors[0].single_base = -n;
477 }
478
479 if (!expo & 1) // exponent is even
480 isign = 1;
481
482
483 if (factors[0].single_base.is_one()) {
484 factors[0].factor_state = rf_single_factor::prime;
485 decomp_state = rf_single_factor::prime;
486 factors[0].single_exponent = 1;
487 }
488 else {
489 decomp_state = rf_single_factor::dont_know;
490 factors[0].factor_state = rf_single_factor::dont_know;
491 factors[0].single_exponent = expo;
492 }
493 }
494
495
496
497 void
convert(base_vector<bigint> & basis,base_vector<int> & exponent)498 rational_factorization::convert(base_vector< bigint > & basis, base_vector< int > & exponent)
499 {
500 lidia_size_t i, len;
501
502 if (basis.size() != exponent.size()) {
503 lidia_error_handler("rational_factorization", "different sizes of basis and exponent vectors");
504 return;
505 }
506 else {
507 len = basis.size();
508 factors.set_size(len);
509 for (i = 0; i < len; i++) {
510 factors[i].single_base = basis[i];
511 factors[i].single_exponent = exponent[i];
512 factors[i].factor_state = rf_single_factor::dont_know;
513 }
514 compose();
515 }
516 }
517
518
519
520 void
assign(const bigrational & n,int expo)521 rational_factorization::assign (const bigrational & n, int expo)
522 {
523 if (n.is_zero()) {
524 lidia_error_handler("rational_factorization", "factorization of 0 not allowed");
525 return;
526 }
527
528 if (expo == 0) {
529 assign(1L);
530 return;
531 }
532
533 if (n.denominator().is_one()) {
534 assign(n.numerator(), expo);
535 return;
536 }
537
538 if (!(expo & 1))
539 isign = 1;
540 else
541 isign = n.sign();
542
543 decomp_state = rf_single_factor::dont_know;
544
545 factors.set_size (2);
546
547 factors[0].single_base = n.denominator();
548 factors[0].single_exponent = -expo;
549 factors[0].factor_state = rf_single_factor::dont_know;
550
551 factors[1].single_base = abs(n.numerator());
552 factors[1].single_exponent = expo;
553 factors[1].factor_state = rf_single_factor::dont_know;
554
555 compose();
556 }
557
558
559
560 void
assign(const rational_factorization & f,int exp)561 rational_factorization::assign (const rational_factorization &f, int exp)
562 {
563 int i, l = f.no_of_comp();
564
565 if (exp == 0) {
566 assign(1L);
567 return;
568 }
569
570 factors = f.factors;
571
572 for (i = 0; i < l; i++)
573 factors[i].single_exponent *= exp;
574 isign = f.isign;
575 decomp_state = f.decomp_state;
576 }
577
578
579
580 bigint
base(lidia_size_t index) const581 rational_factorization::base (lidia_size_t index) const
582 {
583 if ((index< 0) || (index >= no_of_comp())) {
584 lidia_error_handler("rational_factorization", "base::index out of range");
585 return (0);
586 }
587
588 return bigint(factors[index].single_base);
589 }
590
591
592
593 int
exponent(lidia_size_t index) const594 rational_factorization::exponent (lidia_size_t index) const
595 {
596 if ((index< 0) || (index >= no_of_comp())) {
597 lidia_error_handler("rational_factorization", "exponent::index out of range");
598 return (0);
599 }
600
601 return factors[index].single_exponent;
602 }
603
604
605
606 void
set_exponent(lidia_size_t index,int expo)607 rational_factorization::set_exponent (lidia_size_t index, int expo)
608 {
609 if ((index< 0) || (index >= no_of_comp())) {
610 lidia_error_handler("rational_factorization", "set_exponent::index out of range");
611 return;
612 }
613
614 factors[index].single_exponent = expo;
615
616 if (expo == 0) {
617 compose();
618 }
619 }
620
621
622
623 bool
is_prime_factor(lidia_size_t index)624 rational_factorization::is_prime_factor (lidia_size_t index)
625 {
626 if (index< 0 || index >= no_of_comp()) {
627 lidia_error_handler("rational_factorization", "is_prime_factor::index out of range");
628 return false;
629 }
630
631 if (rf_single_factor::state(factors[index].factor_state) == rf_single_factor::prime)
632 return true;
633
634 if (rf_single_factor::state(factors[index].factor_state) == rf_single_factor::not_prime)
635 return false;
636
637 if (is_prime(factors[index].single_base, 8)) {
638 factors[index].factor_state = rf_single_factor::prime;
639 return true;
640 }
641 else {
642 factors[index].factor_state = rf_single_factor::not_prime;
643 return false;
644 }
645 }
646
647
648
649 bool
is_prime_factorization()650 rational_factorization::is_prime_factorization ()
651 {
652
653 if (decomp_state == rf_single_factor::prime)
654 return true;
655
656 for (lidia_size_t i = no_of_comp()-1; i >= 0; i--) {
657 if (rf_single_factor::state(factors[i].factor_state) == rf_single_factor::not_prime) {
658 decomp_state = rf_single_factor::not_prime;
659 return false;
660 }
661
662 if (rf_single_factor::state(factors[i].factor_state) == rf_single_factor::dont_know) {
663 if (is_prime(factors[i].single_base, 8))
664 factors[i].factor_state = rf_single_factor::prime;
665 else {
666 decomp_state = rf_single_factor::not_prime;
667 factors[i].factor_state = rf_single_factor::not_prime;
668 return false;
669 }
670 }
671 }
672
673 decomp_state = rf_single_factor::prime;
674 return true;
675 }
676
677
678
679 void
compose()680 rational_factorization::compose ()
681 {
682 lidia_size_t i, j, len = no_of_comp() - 1;
683
684 sort();
685
686 for (i = 0; i < len; i++) {
687 j = i+1;
688 while ((j <= len) && (factors[i].single_base == factors[j].single_base)) {
689 factors[i].single_exponent += factors[j].single_exponent;
690 j++;
691 }
692
693 if ((j = j - i - 1) > 0) {
694 factors.remove_from(i+1, j);
695 len = no_of_comp() - 1;
696 }
697 if (factors[i].single_exponent == 0 || factors[i].single_base.is_one()) {
698 factors.remove_from(i);
699 len --;
700 i --;
701 }
702 }
703
704 if (factors[len].single_exponent == 0 || factors[len].single_base.is_one()) {
705 factors.remove_from(len);
706 }
707
708 if (no_of_comp() == 0) {
709 factors[0].single_base.assign(1);
710 factors[0].single_exponent = 1;
711 factors[0].factor_state = rf_single_factor::prime;
712 decomp_state = rf_single_factor::prime;
713 }
714 }
715
716
717
718 void
compose(sort_vector<rf_single_factor> & v)719 rational_factorization::compose (sort_vector< rf_single_factor > & v)
720 {
721 lidia_size_t i, j, len = v.size() - 1;
722
723 v.sort();
724
725 for (i = 0; i < len; i++) {
726 j = i+1;
727 while ((j <= len) && (v[i].single_base == v[j].single_base)) {
728 v[i].single_exponent += v[j].single_exponent;
729 j++;
730 }
731
732 if ((j = j - i - 1) > 0) {
733 v.remove_from(i+1, j);
734 len = v.size() - 1;
735 }
736 if (v[i].single_exponent == 0 || v[i].single_base.is_one()) {
737 v.remove_from(i);
738 len --;
739 }
740 }
741
742 if (v[len].single_exponent == 0 || v[len].single_base.is_one()) {
743 v.remove_from(len);
744 }
745
746 if (v.size() == 0) {
747 v[0].single_base.assign(1);
748 v[0].single_exponent = 1;
749 v[0].factor_state = rf_single_factor::prime;
750 }
751 v.sort(); // Testing
752 }
753
754
755
756 std::istream &
operator >>(std::istream & in,rational_factorization & f)757 operator >> (std::istream & in, rational_factorization & f)
758 {
759 lidia_size_t n = 0;
760 int sg = 1;
761 char c;
762
763 f.decomp_state = rf_single_factor::dont_know;
764
765 f.factors.set_size (0);
766
767 in >> c;
768
769 if (c != '[') {
770 lidia_error_handler("rational_factorization", "operator >>::[ expected");
771 return(in);
772 }
773
774 in >> c;
775
776 while (c != ']') {
777 in.putback(c);
778
779 in >> f.factors[n];
780
781 n++;
782
783 in >> c;
784 }
785
786 for (lidia_size_t i = 0; i < n; i++) {
787 if (f.factors[i].single_base.is_lt_zero()) {
788 if (f.factors[i].single_exponent & 1)
789 sg = -sg;
790 f.factors[i].single_base.negate();
791 }
792
793 if ((f.factors[i].single_base).is_one()) {
794 f.factors.remove_from(i);
795 n--;
796 i--;
797 }
798 }
799
800 f.isign = sg;
801
802 f.compose();
803
804 return in;
805 }
806
807
808
809 std::ostream &
operator <<(std::ostream & out,const rational_factorization & f)810 operator << (std::ostream & out, const rational_factorization & f)
811 {
812 lidia_size_t i, sz = f.no_of_comp();
813 rational_factorization g(f);
814
815 g.factors.sort();
816
817 out << " [";
818
819 if (g.isign == -1)
820 out << "(-1, 1)";
821
822 for (i = 0; i < sz; i++)
823 out << g.factors[i];
824
825 out << "]";
826
827 return out;
828 }
829
830
831
832 void
invert()833 rational_factorization::invert ()
834 {
835 lidia_size_t i, len = no_of_comp();
836
837 for (i = 0; i < len; i++)
838 factors[i].single_exponent = - factors[i].single_exponent;
839 }
840
841
842
843 void
square()844 rational_factorization::square ()
845 {
846 lidia_size_t i, len = no_of_comp();
847
848 for (i = 0; i < len; i++)
849 factors[i].single_exponent <<= 1;
850 }
851
852
853
854 void
multiply(rational_factorization & f,const rational_factorization & a,const rational_factorization & b)855 multiply (rational_factorization & f,
856 const rational_factorization & a,
857 const rational_factorization & b)
858 {
859 f.factors.concat(a.factors, b.factors);
860
861 if (a.decomp_state == rf_single_factor::prime && b.decomp_state == rf_single_factor::prime)
862 f.decomp_state = rf_single_factor::prime;
863 else
864 f.decomp_state = rf_single_factor::dont_know;
865
866 f.isign = a.isign * b.isign;
867 f.compose();
868 }
869
870
871
872 void
divide(rational_factorization & f,const rational_factorization & a,const rational_factorization & b)873 divide (rational_factorization & f,
874 const rational_factorization & a,
875 const rational_factorization & b)
876 {
877 rational_factorization h(b);
878 h.invert();
879 f.factors.concat(a.factors, h.factors);
880
881 if (a.decomp_state == rf_single_factor::prime && b.decomp_state == rf_single_factor::prime)
882 f.decomp_state = rf_single_factor::prime;
883 else
884 f.decomp_state = rf_single_factor::dont_know;
885
886 f.isign = a.isign * b.isign;
887 f.compose();
888 }
889
890
891 #if 0
892 void gcd(rational_factorization & f,
893 const rational_factorization & a,
894 const rational_factorization & b)
895 {
896 rational_factorization ha(a), hb(b);
897 lidia_size_t i, j;
898
899 f.assign(1L);
900
901 ha.refine();
902 hb.refine();
903
904 for (i = 0; i < ha.no_of_comp(); i++)
905 if (ha.exponent(i) < 0)
906 lidia_error_handler("rational_factorization", "gcd::negative exponent");
907
908 for (j = 0; j < hb.no_of_comp(); j++)
909 if (hb.exponent(j) < 0)
910 lidia_error_handler("rational_factorization", "gcd::negative exponent");
911
912 for (i = 0; i < ha.no_of_comp(); i++)
913 for (j = 0; j < hb.no_of_comp(); j++)
914 if (ha.base(i) == hb.base(j))
915 multiply(f, f, rational_factorization(ha.base(i), min(ha.exponent(i), hb.exponent(j))));
916 }
917
918
919 void lcm (rational_factorization & f,
920 const rational_factorization & a,
921 const rational_factorization & b)
922 {
923 rational_factorization h;
924
925 multiply(h, a, b);
926 gcd(f, a, b);
927 divide(f, h, f);
928 }
929 #endif
930
931
932
933 void
refine2(sort_vector<rf_single_factor> & v,rf_single_factor & SF,const rf_single_factor & a,const rf_single_factor & b)934 rational_factorization::refine2 (sort_vector< rf_single_factor > & v , rf_single_factor & SF ,
935 const rf_single_factor & a, const rf_single_factor & b)
936
937 // we assume vector v to be of expanding size !!!
938
939 // compute refinement of {a,b} and store the
940 // last rf_single_factor of this factorization individually
941 // in SF
942 // thus {v[0],...,v[n],SF} represents the refinement of {a,b}
943 {
944 debug_handler ("rational_factorization" , "refine2()");
945
946 lidia_size_t i = 0, last_index = 2;
947 int j;
948 rf_single_factor sf;
949 bigint q, r;
950
951 v.set_size (2);
952 v[0] = a;
953 v[1] = b;
954
955 while (i < last_index-1) {
956 sf.single_base = gcd(v[i].single_base, v[i+1].single_base);
957
958 if (sf.single_base.is_one())
959 i++;
960 else {
961 div_rem(v[i].single_base, r, v[i].single_base, sf.single_base);
962 j = 0;
963 while (r.is_zero()) {
964 div_rem(q, r, v[i].single_base, sf.single_base);
965 if (r.is_zero())
966 v[i].single_base.assign(q);
967 j++;
968 }
969 sf.single_exponent = j * v[i].single_exponent;
970
971 div_rem(v[i+1].single_base, r, v[i+1].single_base, sf.single_base);
972 j = 0;
973 while (r.is_zero()) {
974 div_rem(q, r, v[i+1].single_base, sf.single_base);
975 if (r.is_zero())
976 v[i+1].single_base.assign(q);
977 j++;
978 }
979 sf.single_exponent += j * v[i+1].single_exponent;
980
981 if (is_prime(v[i].single_base, 8))
982 v[i].factor_state = rf_single_factor::prime;
983 else v[i].factor_state = rf_single_factor::not_prime;
984
985 if (is_prime(v[i+1].single_base, 8))
986 v[i+1].factor_state = rf_single_factor::prime;
987 else v[i+1].factor_state = rf_single_factor::not_prime;
988
989 if (sf.single_exponent != 0) {
990 if (is_prime(sf.single_base, 8))
991 sf.factor_state = rf_single_factor::prime;
992 else sf.factor_state = rf_single_factor::not_prime;
993
994 if (v[i+1].single_base.is_one())
995 v[i+1] = sf;
996 else {
997 v.insert_at (sf , i+1);
998 last_index ++;
999 }
1000 }
1001 }
1002 }
1003
1004 // extract last element and return it as an individual
1005
1006 i = v.size()-1;
1007 SF = v[i];
1008 v.set_size(i);
1009
1010 compose(v);
1011 }
1012
1013
1014
1015 void
refine()1016 rational_factorization::refine ()
1017 {
1018 debug_handler ("rational_factorization" , "refine()");
1019
1020 sort_vector< rf_single_factor > v(0, EXPAND), w(0, EXPAND);
1021 rf_single_factor b, c, sf;
1022
1023 lidia_size_t i, j, k, l = factors.size();
1024
1025 if (l >= 2) {
1026 refine2 (v , sf , factors[0] , factors[1]);
1027
1028 k = v.size();
1029 v[k] = sf;
1030
1031 for (i = 2; i < l; i++) {
1032 j = 0;
1033 b = v[0];
1034 c = factors[i];
1035
1036 do
1037 {
1038 // compute refinement of {b,c}
1039 refine2 (w , sf , b , c);
1040
1041
1042 // insert w into v and proceed with {..,sf}
1043 k = w.size();
1044
1045 v.shift_right (j+1 , k-1);
1046
1047 v.assign (j , w , 0 , k-1);
1048
1049 j += k;
1050
1051 if (j < v.size()) {
1052 b = v[j];
1053 c = sf;
1054 }
1055 else if (! sf.single_base.is_one()) {
1056 v[j] = sf;
1057 j++;
1058 }
1059 }
1060 while (j < v.size() && ! sf.single_base.is_one());
1061 }
1062
1063 swap (v , factors);
1064 compose ();
1065 }
1066 }
1067
1068
1069
1070 bool
refine(const bigint & x)1071 rational_factorization::refine (const bigint & x)
1072 {
1073 lidia_size_t i, j, len = no_of_comp();
1074 int e_akt;
1075
1076 bool rc = false;
1077
1078 bigint old, n, res, d;
1079
1080 rf_single_factor sf;
1081
1082 j = len;
1083
1084 for (i = 0; i < len; i++) {
1085 e_akt = 0;
1086 old = base(i);
1087 d = gcd (old , x);
1088
1089 if (! d.is_one() && d != old) {
1090 rc = true;
1091
1092 div_rem(n, res, old, d);
1093
1094 while (res.is_zero()) {
1095 e_akt++;
1096 old = n;
1097
1098 div_rem(n, res, old, d);
1099 }
1100
1101 sf.single_base = d;
1102 sf.single_exponent = e_akt * exponent(i);
1103
1104 if (is_prime(d, 8))
1105 sf.factor_state = rf_single_factor::prime;
1106 else
1107 sf.factor_state = rf_single_factor::not_prime;
1108
1109
1110 if (! old.is_one()) {
1111 factors[i].single_base = old;
1112
1113 if (is_prime(old, 8))
1114 factors[i].factor_state = rf_single_factor::prime;
1115 else
1116 factors[i].factor_state = rf_single_factor::not_prime;
1117
1118 // * * * append sf to the end of factors * * *
1119
1120 factors[j] = sf;
1121 j ++;
1122 }
1123 else {
1124 factors[i] = sf;
1125 }
1126 }
1127 }
1128
1129 compose();
1130
1131 return rc;
1132 }
1133
1134
1135
1136 bool
refine_comp(lidia_size_t index,const bigint & x)1137 rational_factorization::refine_comp (lidia_size_t index, const bigint & x)
1138 {
1139 int e = 0;
1140 bigint old, n, res, d;
1141
1142 rf_single_factor sf;
1143
1144 bool rc = false;
1145
1146 if ((index< 0) || (index >= no_of_comp())) {
1147 lidia_error_handler("rational_factorization", "refine_comp(int, const bigint &)::index out of range");
1148 return (false);
1149 }
1150
1151 old = base(index);
1152 d = gcd (old , x);
1153
1154 if (! d.is_one() && d != old) {
1155 rc = true;
1156
1157 div_rem(n, res, old, d);
1158
1159 while (res.is_zero()) {
1160 e++;
1161 old = n;
1162 div_rem(n, res, old, x);
1163 }
1164
1165 sf.single_base = d;
1166 sf.single_exponent = e * exponent(index);
1167
1168 if (is_prime(d, 8))
1169 sf.factor_state = rf_single_factor::prime;
1170 else
1171 sf.factor_state = rf_single_factor::not_prime;
1172
1173 if (! old.is_one()) {
1174 factors[index].single_base = old;
1175
1176 if (is_prime(old, 8))
1177 factors[index].factor_state = rf_single_factor::prime;
1178 else
1179 factors[index].factor_state = rf_single_factor::not_prime;
1180
1181 factors[no_of_comp()] = sf;
1182 }
1183 else {
1184 factors[index] = sf;
1185 }
1186
1187 compose();
1188 }
1189
1190 return rc;
1191 }
1192
1193
1194
1195 bool
operator ==(const rational_factorization & a,const rational_factorization & b)1196 operator == (const rational_factorization & a,
1197 const rational_factorization & b)
1198 {
1199 rational_factorization f;
1200
1201 divide(f, a, b);
1202 f.refine();
1203
1204 if (f.no_of_comp() == 1 && f.base(0).is_one() && f.isign == 1)
1205 return 1;
1206 else
1207 return 0;
1208 }
1209
1210
1211
1212 void
factor_comp(lidia_size_t index,int upper_bound)1213 rational_factorization::factor_comp (lidia_size_t index, int upper_bound)
1214 {
1215 if ((index< 0) || (index >= no_of_comp())) {
1216 lidia_error_handler("rational_factorization", "factor_comp::index out of range");
1217 return;
1218 }
1219
1220 if (is_prime_factor(index)) {
1221 if (info)
1222 std::cout << "prime number " << factors[index].single_base << "\n";
1223 return;
1224 }
1225
1226 if (upper_bound > 34) {
1227 lidia_warning_handler("rational_factorization", "factor_comp::incorrect parameters");
1228 upper_bound = 34;
1229 }
1230
1231 int D, job_buffer[30][5], strategy[30];
1232 int jobs_avail, k;
1233 int n = (factors[index].single_base.bit_length() / 3) + 10;
1234
1235 // try to factor component using TD
1236 if (upper_bound == 34) {
1237 char *n_string;
1238 n_string = new char[n];
1239 upper_bound = static_cast<int>(bigint_to_string(factors[index].single_base, n_string) * .28) + 1;
1240 delete [] n_string;
1241
1242 if (upper_bound > 34)
1243 upper_bound = 34;
1244 if (upper_bound < 6)
1245 upper_bound = 6;
1246 }
1247
1248 if ((D = ecm_read_max(upper_bound)) < 1000000)
1249 D = 1000000;
1250
1251 ecm_primes prim(1, D+200, 200000);
1252 trialdiv(index, 1, 1000000, prim);
1253
1254 if (is_prime_factor(index)) {
1255 if (info)
1256 std::cout << "prime number " << factors[index].single_base << "\n";
1257
1258 compose();
1259 return;
1260 }
1261 // check whether base[index] is an exact power
1262 bigint N;
1263
1264 do {
1265 k = static_cast<int>(is_power(N, factors[index].single_base));
1266
1267 if (k > 0) {
1268 factors[index].single_base.assign(N);
1269 factors[index].single_exponent *= k;
1270
1271 if (is_prime(N, 8)) {
1272 factors[index].factor_state = rf_single_factor::prime;
1273 compose();
1274 return;
1275 }
1276 else
1277 factors[index].factor_state = rf_single_factor::not_prime;
1278 }
1279 } while (k > 0);
1280
1281 // try to factor component using ECM
1282 if (!(rf_single_factor::state(factors[index].factor_state) == rf_single_factor::prime)) {
1283 k = 0; n = 6; // lower_bound = 6
1284
1285 while (n < upper_bound) {
1286 strategy[k++] = n;
1287 n += 3;
1288 }
1289
1290 strategy[k] = upper_bound;
1291 strategy[k+1] = 0;
1292
1293 jobs_avail = ecm_job_planing(strategy, job_buffer);
1294
1295 N.assign(factors[index].single_base);
1296 int ecm_restlength = static_cast<int>(N.bit_length()*0.177);
1297 // *0.30 wegen Dezimalstellen und * 0.59 wegen Restlaenge
1298
1299 if (ecm_restlength < 20) // always use ecm completely
1300 ecm_restlength = 1;
1301
1302 ecm(index, ecm_restlength, jobs_avail, job_buffer, prim);
1303 }
1304
1305 if (!(is_prime_factor(index))) {
1306 prim.resetprimes(1);
1307 mpqs(index, prim);
1308 }
1309
1310 compose();
1311 }
1312
1313
1314
1315 void
factor(int upper_bound)1316 rational_factorization::factor (int upper_bound)
1317 {
1318 if (is_prime_factorization())
1319 return;
1320
1321 if (upper_bound > 34) {
1322 lidia_warning_handler("rational_factorization", "factor::upper_bound > 34");
1323 upper_bound = 34;
1324 }
1325
1326 lidia_size_t k = no_of_comp(), index;
1327
1328 int D, job_buffer[30][5], strategy[30];
1329 int jobs_avail;
1330 int n = (factors[k-1].single_base.bit_length() / 3) + 10;
1331
1332 // try to factor component using TD
1333 if (upper_bound == 34) {
1334 char *n_string;
1335 n_string = new char[n];
1336 upper_bound = static_cast<int>(bigint_to_string(factors[k-1].single_base, n_string) * .28) + 1;
1337 delete [] n_string;
1338
1339 if (upper_bound > 34)
1340 upper_bound = 34;
1341 if (upper_bound < 6)
1342 upper_bound = 6;
1343 }
1344
1345 if ((D = ecm_read_max(upper_bound)) < 1000000)
1346 D = 1000000;
1347
1348 ecm_primes prim(1, D+200, 200000);
1349 bigint N;
1350
1351 D = 0; n = 6; // lower_bound = 6
1352
1353 while (n < upper_bound) {
1354 strategy[D++] = n;
1355 n += 3;
1356 }
1357
1358 strategy[D] = upper_bound;
1359 strategy[D+1] = 0;
1360
1361 jobs_avail = ecm_job_planing(strategy, job_buffer);
1362
1363 for (index = 0; index < k; index++) {
1364 if (info) {
1365 std::cout << "\nworking on index " << index;
1366 std::cout << "\n==================\n";
1367 std::cout.flush();
1368 }
1369
1370 if (rf_single_factor::state(factors[index].factor_state) == rf_single_factor::dont_know)
1371 if (is_prime_factor(index) == rf_single_factor::prime) {
1372 if (info)
1373 std::cout << "prime number " << factors[index].single_base << "\n";
1374 continue;
1375 }
1376
1377 int ecm_restlength = static_cast<int>(factors[index].single_base.bit_length()*0.177); // *0.30 wegen Dezimalstellen und * 0.59 wegen Restlaenge
1378
1379 if (ecm_restlength < 20)
1380 ecm_restlength = 1;
1381
1382 trialdiv(index, 1, 1000000, prim);
1383
1384 if (is_prime_factor(index)) {
1385 if (info)
1386 std::cout << "prime number " << factors[index].single_base << "\n";
1387 continue;
1388 }
1389
1390 // check whether base[index] is an exact power
1391 do {
1392 D = static_cast<int>(is_power(N, factors[index].single_base));
1393
1394 if (D > 0) {
1395 factors[index].single_base.assign(N);
1396 factors[index].single_exponent *= D;
1397
1398 if (is_prime(N, 8)) {
1399 factors[index].factor_state = rf_single_factor::prime;
1400 D = -1;
1401 }
1402 else
1403 factors[index].factor_state = rf_single_factor::not_prime;
1404 }
1405 } while (D > 0);
1406
1407 // try to factor component using ECM
1408 if (!(rf_single_factor::state(factors[index].factor_state) == rf_single_factor::prime)) {
1409 if (info) std::cout << "ECM ";
1410
1411 ecm(index, ecm_restlength, jobs_avail, job_buffer, prim);
1412 }
1413
1414 for (D = 0; D < jobs_avail; D++)
1415 job_buffer[D][3] = job_buffer[D][4];
1416
1417 if (!(is_prime_factor(index))) {
1418 prim.resetprimes(1);
1419 mpqs(index, prim);
1420 }
1421 }
1422
1423 compose();
1424
1425 if (is_prime_factorization())
1426 return;
1427
1428 int trials = 0;
1429
1430 k = no_of_comp();
1431
1432 for (index = 0; index < k; index++) {
1433 if (rf_single_factor::state(factors[index].factor_state) == rf_single_factor::not_prime) {
1434 N.assign(factors[index].single_base);
1435
1436 if (info)
1437 std::cout << "\nindex " << index << " not prime: to factor " << N;
1438
1439 for (n = 0; n < jobs_avail; n++)
1440 job_buffer[n][3] = job_buffer[n][4];
1441
1442 ecm(index, jobs_avail, job_buffer, prim);
1443 compose();
1444
1445 if (N == factors[index].single_base)
1446 trials ++;
1447 else trials = 0;
1448 k = no_of_comp();
1449 index = -1;
1450
1451 if (trials >= 2) return;
1452 }
1453 }
1454 }
1455
1456
1457
1458 rational_factorization
factor(const bigint & N)1459 factor (const bigint &N)
1460 {
1461 rational_factorization f(N);
1462
1463 f.factor();
1464
1465 return f;
1466 }
1467
1468
1469
1470 rational_factorization
factor_completely(const bigint & N)1471 factor_completely (const bigint &N)
1472 {
1473 rational_factorization f(N);
1474
1475 f.factor_completely();
1476
1477 return f;
1478 }
1479
1480
1481
1482 //********** NEW *********************************************
1483
1484 bigrational
evaluate(const rational_factorization & r)1485 evaluate (const rational_factorization & r)
1486 {
1487 bigrational x(1);
1488 bigint h;
1489 int i, j;
1490
1491 for (i = 0; i < r.no_of_comp(); i++) {
1492 j = r.exponent(i);
1493
1494 if (j > 0) {
1495 if (j > 1) {
1496 power(h, r.base(i), j);
1497 multiply(x, x, h);
1498 }
1499 else
1500 multiply(x, x, r.base(i));
1501 }
1502 else {
1503 j = -j;
1504 if (j > 1) {
1505 power(h, r.base(i), j);
1506 divide(x, x, h);
1507 }
1508 else
1509 divide(x, x, r.base(i));
1510 }
1511 }
1512 if (r.sign() == -1)
1513 negate(x, x);
1514
1515 return x;
1516 }
1517
1518
1519
1520 bigint
evaluate_to_bigint(const rational_factorization & r)1521 evaluate_to_bigint (const rational_factorization & r)
1522 {
1523 bigrational x;
1524
1525 x = evaluate(r);
1526
1527 if (!x.denominator().is_one()) {
1528 lidia_error_handler("rational_factorization", "evaluate::rational_factorization does not evaluate to bigint");
1529 return 1;
1530 }
1531
1532 return x.numerator();
1533 }
1534
1535
1536
1537 #ifdef LIDIA_NAMESPACE
1538 } // end of namespace LiDIA
1539 #endif
1540