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