number_theory/arithmetic/
mpz.rs1use crate::arithmetic::conversion::*;
2use crate::arithmetic::inlineops::*;
3
4use crate::arithmetic::sign::Sign;
5use crate::arithmetic::sliceops::*;
6use std::cmp::Ordering;
7use crate::primitive::factorprim::poly_factor_128;
8use crate::ntrait::NumberTheory;
9
10#[derive(Debug, Default, Clone, PartialEq)]
12pub struct Mpz {
13 pub(crate) sign: Sign,
14 pub(crate) limbs: Vec<u64>,
15}
16
17impl std::fmt::Display for Mpz{
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19
20 let out = to_string(self.sign.clone(), self.limbs.clone());
21 write!(f,"{}",out)
22 }
23}
24
25impl std::convert::From<u64> for Mpz{
26 fn from(val: u64) -> Self{
27 Mpz::unchecked_new(Sign::Positive, vec![val])
28 }
29}
30
31impl std::convert::From<u32> for Mpz{
32 fn from(val: u32) -> Self{
33 Mpz::unchecked_new(Sign::Positive, vec![val.into()])
34 }
35}
36
37impl std::convert::From<i64> for Mpz{
38 fn from(val: i64) -> Self{
39 if val < 0i64 {
40 return Mpz::unchecked_new(Sign::Negative, vec![val.unsigned_abs()]);
41 }
42 Mpz::unchecked_new(Sign::Positive, vec![val as u64])
43 }
44}
45
46impl std::convert::From<i32> for Mpz{
47 fn from(val: i32) -> Self{
48 if val < 0i32 {
49 return Mpz::unchecked_new(Sign::Negative, vec![val.unsigned_abs() as u64]);
50 }
51 Mpz::unchecked_new(Sign::Positive, vec![val as u64])
52 }
53}
54
55impl std::convert::From<u128> for Mpz{
56 fn from(val: u128) -> Self{
57 let (x_lo, x_hi) = split(val);
58 if x_hi == 0 {
59 return Mpz::unchecked_new(Sign::Positive, vec![x_lo]);
60 }
61 Mpz::unchecked_new(Sign::Positive, vec![x_lo, x_hi])
62 }
63}
64
65impl std::convert::From<i128> for Mpz{
66
67 fn from(val: i128) -> Self {
68 if val < 0i128 {
69 let (x_lo, x_hi) = split(val.unsigned_abs());
70 if x_hi == 0 {
71 return Mpz::unchecked_new(Sign::Negative, vec![x_lo]);
72 }
73 Mpz::unchecked_new(Sign::Negative, vec![x_lo, x_hi])
74 } else {
75 Mpz::from(val as u128)
76 }
77 }
78 }
79
80impl std::convert::TryFrom<Mpz> for u64{
81 type Error = &'static str;
82
83 fn try_from(x: Mpz) -> Result<Self, Self::Error>{
84
85 match x.len() {
86 0 => Ok(0u64),
87 1 => Ok(x.limbs[0]),
88 _=> Err("Multiprecision value exceeds 2^64"),
89 }
90 }
91
92}
93
94impl std::convert::TryFrom<Mpz> for i64{
95 type Error = &'static str;
96
97 fn try_from(x: Mpz) -> Result<Self,Self::Error>{
98
99 match x.len(){
100 0 => Ok(0i64),
101 1 => {
102 let value = x.limbs[0];
103 if (value>>63)==1{
104 return Err("Single precision value exceeds 2^63");
105 }
106 let mut res : i64 = value as i64;
107 if x.sign == Sign::Negative{
108 res = -res;
109 }
110 return Ok(res);
111 }
112 _=> Err("Multiprecision value exceeds 2^64"),
113 }
114 }
115}
116 impl Mpz {
123 pub fn u_new(limbs: Vec<u64>) -> Self {
149 Mpz::from_slice(Sign::Positive, &limbs[..])
150 }
151 pub fn new(sign: Sign, limbs: Vec<u64>) -> Self {
153 Mpz::from_slice(sign, &limbs[..])
154 }
155 pub fn unchecked_u_new(limbs: Vec<u64>) -> Self {
157 Mpz {
158 sign: Sign::Positive,
159 limbs,
160 }
161 }
162
163 pub fn unchecked_new(sign: Sign, limbs: Vec<u64>) -> Self {
165 Mpz { sign, limbs }
166 }
167pub fn from_slice(sign: Sign, x: &[u64]) -> Self {
169 let mut limbs = vec![];
170 limbs.extend_from_slice(&x[..sig_pos(x)]);
171 if limbs.is_empty() {
172 limbs.push(0u64)
173 }
174 Mpz { sign, limbs }
175 }
176
177 pub fn to_u32(&self) -> Option<u32>{
179 match self.len() {
180 0 => Some(0u32),
181 1 => {
182 if self.limbs[0] > u32::MAX as u64 {
183 return None
184 }
185 Some(self.limbs[0] as u32)
186 }
187 _ => None,
188 }
189 }
190
191 pub fn to_u128(&self) -> Option<u128> {
193 match self.len() {
194 0 => Some(0u128),
195 1 => Some(self.limbs[0] as u128),
196 2 => Some(fuse(self.limbs[1], self.limbs[0])),
197 _ => None,
198 }
199 }
200 pub fn to_vector(&self) -> Vec<u64> {
202 self.limbs.clone()
203 }
204
205 pub fn rand(len: usize) -> Self {
207 let mut k = len/64;
208 if len%64 != 0{
209 k+=1;
210 }
211 let mut interim = (0..k).map(|_| u64::rng()).collect::<Vec<u64>>();
212
213 interim[k-1] &= (1<<(len%64))-1;
214 let mut result = Mpz::unchecked_new(Sign::Positive, interim);
215 result.set_bit(len-1);
216 result
217
218
219 }
220
221
222 pub fn set_limbs(len: usize, gen: fn() -> u64) -> Self {
224 let interim = (0..len).map(|_| gen()).collect::<Vec<u64>>();
225 Mpz::unchecked_new(Sign::Positive, interim)
226 }
227 pub fn to_string(&self) -> String {
229 to_string(self.sign.clone(), self.limbs.clone())
230 }
231 pub fn to_hex_string(&self) -> String{
233 to_hex_string(self.sign.clone(),self.limbs.clone())
234 }
235 pub(crate) fn fix_zero(&mut self) {
237 if self.len() == 0 {
238 self.limbs.push(0u64)
239 }
240 if self.len() == 1 && self.limbs[0] == 0 && self.sign == Sign::Negative {
241 self.sign = Sign::Positive;
242 }
243 }
244 pub fn to_radix_vec(&self, radix: u64) -> Vec<u64> {
257 let mut k = vec![];
258 let mut x = self.clone().limbs;
259 loop {
260 let idx = sig_pos(&x[..]);
261
262 if idx == 0 {
263 break;
264 }
265
266 k.push(div_slice(&mut x[..idx], radix));
267 }
268 k.push(x[0] % radix);
269 remove_lead_zeros(&mut k);
270 k
271 }
272
273 pub fn from_string(x: &str) -> Option<Self> {
286 if x.is_empty() {
287 return None;
288 }
289
290 let ch = x.chars().next().unwrap();
291 let mut sign = Sign::Positive;
292 let mut k = x;
293 if ch == '-' {
294 sign = Sign::Negative;
295 let mut chars = x.chars();
296 chars.next();
297 k = chars.as_str();
298 }
299
300 if ch == '+' {
301 let mut chars = x.chars();
302 chars.next();
303 k = chars.as_str();
304 }
305
306 from_string(k).map(|y| Mpz::unchecked_new(sign, y))
307 }
308
309 pub fn zero() -> Self {
311 Mpz::unchecked_new(Sign::Positive, vec![0])
312 }
313 pub fn one() -> Self {
315 Mpz::unchecked_new(Sign::Positive, vec![1])
316 }
317 pub fn two() -> Self{
319 Mpz::unchecked_new(Sign::Positive, vec![2])
320 }
321 pub fn neg(&mut self) {
323 self.sign = self.sign.neg();
324 }
325 pub fn abs(&self) -> Self {
327 Self::new(Sign::Positive, self.limbs.clone())
328 }
329
330 pub fn is_zero(&self) -> bool {
332 if self.len() == 0{
333 return true
334 }
335 if self.len() == 1 && self.limbs[0] == 0{
336 return true
337 }
338 false
339 }
340 pub fn is_positive(&self) -> bool {
342 self.sign == Sign::Positive
343 }
344 pub fn is_even(&self) -> bool {
346 self.limbs[0] & 1 == 0
347 }
348 pub fn is_power_of_two(&self) -> bool {
350 if self.len() < 2 {
351 return self.to_u128().unwrap().is_power_of_two();
352 }
353 if !self.lead_digit().is_power_of_two() {
354 return false;
355 }
356 for i in self.limbs[..self.len() - 1].iter() {
357 if *i != 0 {
358 return false;
359 }
360 }
361 true
362 }
363
364 pub(crate) fn is_fermat(&self) -> bool {
365 if self.limbs[0] != 1 {
366 return false;
367 }
368
369 let lead = self.limbs[..].last().unwrap();
370
371 let mut flag = 0u64;
372 for i in 0..64 {
373 if *lead == 1u64 << i {
374 flag = 1; break; }
377 }
378
379 if flag == 0 {
380 return false;
381 } for i in self.limbs[1..self.len() - 1].iter() {
384 if *i != 0u64 {
385 return false;
386 }
387 }
388 true
389 }
390
391 pub(crate) fn is_mersenne(&self) -> Option<u64> {
392 let mut flag = 0u64;
393 let mut start = 1u64;
394 let lead = self.limbs.last().unwrap();
395 for i in 0..64 {
396 if *lead == start {
397 flag = i;
398 break;
399 }
400 start = (start << 1) + 1;
401 }
402 if flag == 0 {
403 return None;
404 }
405 for i in self.limbs[..self.len() - 2].iter() {
406 if *i != u64::MAX {
407 return None;
408 }
409 }
410
411 Some(flag + 1 + 64u64 * (self.len() - 1) as u64)
412 }
413 pub fn set_bit(&mut self, k: usize) {
415 self.limbs[k / 64usize] |= 1 << (k % 64)
416 }
417 pub fn flip_bit(&mut self, k: usize){
419 self.limbs[k / 64usize] ^= 1 << (k % 64)
420 }
421 pub fn check_bit(&self, index: usize) -> bool {
423 self.limbs[index / 64usize] & (1 << (index % 64)) > 0
424 }
425 pub fn set_sign(&mut self, sign: Sign) {
427 self.sign = sign
428 }
429 pub fn len(&self) -> usize {
431 self.limbs.len()
432 }
433 pub fn lead_digit(&self) -> u64 {
435 *self.limbs[..].last().unwrap()
436 }
437 pub fn trailing_zeros(&self) -> u64 {
439 let mut idx: u64 = 0;
441
442 for i in self.limbs.iter() {
443 if i == &0u64 {
444 idx += 1;
445 } else {
446 break;
447 }
448 }
449 if idx == self.len() as u64 {
450 64u64 * idx
451 } else {
452 self.limbs[idx as usize].trailing_zeros() as u64 + 64u64 * idx
453 }
454 }
455 pub fn leading_zeros(&self) -> u64 {
457 let mut idx: u64 = 0;
458
459 for i in self.limbs.iter().rev() {
460 if i == &0u64 {
461 idx += 1;
462 } else {
463 break;
464 }
465 }
466 if idx == self.len() as u64 {
467 64u64 * idx
468 } else {
469 self.limbs[self.len() - 1 - idx as usize].leading_zeros() as u64 + 64u64 * idx
470 }
471 }
472 pub fn bit_length(&self) -> u64 {
474 64u64 * self.len() as u64 - self.leading_zeros()
475 }
476 pub fn normalize(&mut self) {
478 remove_lead_zeros(&mut self.limbs);
479 if self.len() == 0 {
480 self.limbs.push(0u64)
481 };
482 }
483
484 pub fn u_cmp(&self, other: &Self) -> Ordering {
490 cmp_slice(&self.limbs[..], &other.limbs[..])
491 }
492 pub fn congruence_u64(&self, n: u64, c: u64) -> bool {
494 let mut interim = mod_slice(&self.limbs[..], n);
495 if self.sign == Sign::Negative {
496 interim = n - interim;
497 }
498 interim == c
499 }
500
501 pub(crate) fn add_modinv(&self, n: &Self) -> Self {
502 let mut k = n.clone();
504 let mut selfie = self.clone();
505
506 if self.u_cmp(n) == Ordering::Greater {
507 selfie = selfie.ref_euclidean(n).1;
508 }
509
510 sub_slice(&mut k.limbs, &selfie.limbs);
511 k.normalize();
512 k.sign = Sign::Positive;
513 k
514 }
515
516 pub fn successor(&mut self) {
532 if self.len() == 0 {
533 self.limbs.push(1)
534 }
535 let mut carry = 1u8;
536 for i in self.limbs.iter_mut() {
537 carry = adc(carry, *i, 0, i);
538 if carry == 0 {
539 break;
540 }
541 }
542 if carry > 0u8 {
543 self.limbs.push(1u64)
544 }
545 }
546 pub fn inc_by(&mut self, n: u64){
548 if self.len() == 0 {
549 self.limbs.push(n)
550 }
551
552 add_slice(&mut self.limbs[..],&[n]);
553 }
554
555 pub fn predecessor(&mut self) {
557 if self.len() == 0 {
558 panic!("Value already zero")
559 }
560 let mut carry = 1u8;
561 for i in self.limbs.iter_mut() {
562 carry = sbb(carry, *i, 0, i);
563 if carry == 0 {
564 break;
565 }
566 }
567 if carry > 0u8 {
568 panic!("Value already zero")
569 }
570 }
571
572 pub(crate) fn u_quadratic_residue(&self, n: &Self) -> Self {
577 self.ref_product(self).ref_euclidean(n).1
578 }
579
580 pub(crate) fn u_mul_mod(&self, other: &Self, n: &Self) -> Self {
581 self.ref_product(other).ref_euclidean(n).1
582 }
583
584 pub(crate) fn u_mod_pow(&self, y: &Self, modulo: &Self) -> Self {
585 if modulo == &Mpz::zero() {
586 return Mpz::zero();
587 }
588
589 let mut z = Mpz::one();
590 let mut base = self.clone().ref_euclidean(modulo).1;
591 let one = Mpz::one();
592
593 let mut pow = y.clone();
594
595 if pow == Mpz::zero(){
596 return z;
597 }
598
599 if pow == Mpz::one() {
600 return base;
601 }
602
603 while pow.u_cmp(&one) == Ordering::Greater {
604 if pow.len() == 0 {
605 break;
606 }
607
608 if pow.is_even() {
609 base = base.u_quadratic_residue(modulo);
610 pow.mut_shr(1);
611 remove_lead_zeros(&mut pow.limbs);
612 } else {
613 z = base.u_mul_mod(&z, modulo);
614 remove_lead_zeros(&mut base.limbs);
615 base = base.u_quadratic_residue(modulo);
616
617 sub_slice(&mut pow.limbs[..], &one.limbs[..]);
618 pow.mut_shr(1);
619 remove_lead_zeros(&mut pow.limbs);
620 }
621 }
622 base.u_mul_mod(&z, modulo)
623 }
624
625 pub fn pow(&self, x: u64) -> Self {
627 let mut z = Mpz::one();
628 let mut base = self.clone();
629 let mut pow = x;
630
631 if pow == 0 {
632 return z;
633 }
634
635 while pow > 1 {
636 if pow % 2 == 0 {
637 base = base.ref_product(&base);
638 pow >>= 1;
639 } else {
640 z = base.ref_product(&z);
641 base = base.ref_product(&base);
642 pow = (pow - 1) >> 1;
643 }
644 }
645
646 base.ref_product(&z)
647 }
648
649 pub(crate) fn word_div(&self, x: u64) -> (Self, u64) {
650 let mut quotient = self.clone();
651 let remainder = div_slice(&mut quotient.limbs[..], x);
652 (quotient, remainder)
653 }
654
655 fn delta(&self, other: &Self) -> Self {
656 if self.u_cmp(other) == Ordering::Greater {
657 let mut k = self.clone();
658 sub_slice(&mut k.limbs[..], &other.limbs[..]);
659 return k;
660 }
661 if self.u_cmp(other) == Ordering::Less {
662 let mut k = other.clone();
663 sub_slice(&mut k.limbs[..], &self.limbs[..]);
664 k
665 } else {
666 Mpz::zero()
667 }
668 }
669
670 fn mod_sqr_1(&self, n: &Self) -> Self {
671 let mut k = self.ref_product(self);
672 k.successor();
673 k.ref_euclidean(n).1
674 }
675
676 fn gcd(&self, other: &Self) -> Self {
677 let mut a = self.clone();
678 let mut b = other.clone();
679
680 while b != Mpz::zero() {
681 let t = b.clone();
682
683 b = a.ref_euclidean(&b).1;
684
685 b.normalize();
686 a = t;
687 }
688 a
689 }
690
691pub(crate) fn rho_mpz(&self) -> Self {
693
694 match self.to_u128(){
695 Some(x) => Mpz::from(poly_factor_128(x)),
696 None => {
697 let mut x = Mpz::two();
698 let mut y = Mpz::two();
699 let mut d = Mpz::one();
700 loop {
701 while d.is_unit(){
702 x = x.mod_sqr_1(self);
703 y = y.mod_sqr_1(self).mod_sqr_1(self).ref_euclidean(self).1;
704 d = x.delta(&y).gcd(self);
705 }
706
707 if d.is_prime() {
708 return d;
709 }
710 x = Mpz::from(u64::rng());
711 y = x.clone();
712 d = Mpz::one();
713 }
714
715 },
716 }
717 }
718
719 pub fn ln(&self) -> f64 {
721 let mut iter_sqrt = 1u64;
722 let mut n = self.sqrt().0;
723 while n.len() > 1 {
724 n = n.sqrt().0;
725 iter_sqrt += 1;
726 }
727
728 (u64::try_from(n).unwrap() as f64).ln() * 2f64.powf(iter_sqrt as f64)
729 }
730 pub fn log2(&self) -> f64 {
732 self.ln() * std::f64::consts::LOG2_E
733 }
734 pub fn log10(&self) -> f64 {
736 self.ln() * 0.43429448190325176
737 }
738 pub fn log(&self, log: f64) -> f64 {
740 self.ln() * log.ln().recip()
741 }
742 pub fn iter_log(&self, log: f64) -> u8 {
744 let mut first_log = self.log(log);
745 let mut count = 1u8;
746 while first_log > 1.0 {
749 first_log = first_log.log(log);
750 count += 1
751 }
752 count
753 }
754
755 pub fn eea(&self, other: Self) -> (Self, Self, Self) {
757
758 let (gcd, bezout_1, bezout_2) = self.extended_gcd(other.clone());
759
760 (gcd, bezout_1.residue(other.clone()), bezout_2.residue(self.clone()))
761
762 }
763
764 pub fn sirp(infimum: u64, supremum: u64, modulo: u64, residue: u64) -> Self {
783 let mut sirp = Mpz::one();
784 let mut acc = 1u64; for i in infimum..supremum + 1 {
787 if i % modulo == residue {
790 if i >= 4294967296 {
793 acc = i
794 }
795 if acc < 4294967296 {
796 acc *= i
797 }
798 if acc >= 4294967296 {
799 let carry = scale_slice(&mut sirp.limbs[..], acc);
800
801 if carry > 0 {
802 sirp.limbs.push(carry)
803 }
804 acc = 1u64;
805 } } }
808
809 let carry = scale_slice(&mut sirp.limbs[..], acc);
810 if carry > 0 {
811 sirp.limbs.push(carry)
812 }
813 sirp
814 }
815 pub fn cip(infimum: u64, supremum: u64, cond: fn(&u64) -> bool) -> Self {
832 let mut cip = Mpz::one();
833 let mut acc = 1u64; for i in infimum..supremum + 1 {
835 if cond(&i) {
836 if i >= 4294967296 {
837 acc = i
838 }
839 if acc < 4294967296 {
840 acc *= i
841 }
842 if acc >= 4294967296 {
843 let carry = scale_slice(&mut cip.limbs[..], acc);
844
845 if carry > 0 {
846 cip.limbs.push(carry)
847 }
848 acc = 1u64;
849 } } }
852
853 let carry = scale_slice(&mut cip.limbs[..], acc);
854 if carry > 0 {
855 cip.limbs.push(carry)
856 }
857 cip
858 }
859}