1use crate::structs::{Certificate,Factorization};
2use crate::ntrait::{NumberTheory,MontArith,Reduction};
3use crate::primitive::factorprim::{poly_factor,drbg};
4use crate::data::primes::PRIMELIST;
5use crate::result::NTResult;
6
7impl NumberTheory for u64 {
8
9 fn is_unit(&self) -> bool{
10 if *self == 1{
11 return true;
12 }
13 false
14 }
15
16 fn rng() -> Self {
17 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
18 {
19 if is_x86_feature_detected!("rdrand"){let mut x: u64 = 0;
21 unsafe { core::arch::x86_64::_rdrand64_step(&mut x) };
22 return x;
23 }return drbg(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos() as u64)
25 }
26 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
27 {drbg(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos() as u64)
29 }
30 }
31
32 fn residue(&self, ring: Self) -> Self{
33 if ring == 0{
34 return *self
35 }
36 *self % ring
37 }
38
39 fn euclidean_div(&self, other: Self) -> (Self, Self) {
40 (*self / other, *self % other)
41 }
42
43 fn mul_inverse(&self, n: Self) -> NTResult<Self>{
44 let (gcd,inv,_) = self.extended_gcd(n);
45
46 if gcd != 1{
47 return NTResult::DNE
48 }
49 NTResult::Eval(inv)
50 }
51
52 fn fermat(&self,base: Self) -> bool{
53 if *self&1 == 1{
54 let one = self.n_identity();
55 let mbase = base.to_mont(*self);
56 let inv = self.inv_2();
57 return mbase.mont_pow(one,*self-1,inv,*self)==one;
58 }
59 base.exp_residue(*self-1,*self)==1
60
61 }
62
63 fn strong_fermat(&self, base: Self) -> bool {
64 if *self&1==0{
65 return self.fermat(base);
66 }
67 let inv = self.inv_2();let tzc = self.wrapping_sub(1).trailing_zeros();
69 let one = self.n_identity();
70 let oneinv = machine_prime::mont_prod(machine_prime::mont_sub(*self, one, *self), one, *self, inv);
71 let b = machine_prime::to_mont(base,*self);
72
73 machine_prime::strong_fermat(*self, tzc, b, one, oneinv, inv)
74 }
75
76 fn is_prime(&self) -> bool {
77 machine_prime::is_prime(*self)
78 }
79
80 fn prime_proof(&self) -> Certificate<Self> {
81
82 if *self == 2 {
83 return Certificate::new(*self,3,vec![]);
84 }
85
86 let x_minus = *self - 1;
87 let fctrs = x_minus.factor().unwrap()
88 .factor_iter().map(|x| x_minus/ *x)
89 .collect::<Vec<Self>>();
90
91 loop {
92 let mut witness = Self::rng() % (*self - 2) + 2;
95
96 'witness: loop {
97
98 if witness.coprime(*self) {
99
100 break 'witness;
101 }
102
103 witness += 1;
104 }
105
106 if !self.strong_fermat(witness){
107 return Certificate::new(*self,witness,fctrs)
108 }
109
110
111 'inner: for (idx, i) in fctrs.iter().enumerate() {
112 if witness.exp_residue(*i, *self).is_unit(){
113 break 'inner;
114 }
115 if idx == fctrs.len() - 1 {
116 return Certificate::new(*self,witness,fctrs);
117 }
118 }
119 }
120 }
121
122 fn prime_list(&self, sup: Self) -> Vec<Self> {
123
124 let inf = std::cmp::min(*self, sup);
125 let mut hi = std::cmp::max(*self, sup);
126
127 hi = hi.saturating_add(1);
128
129 let mut primevector = vec![];
130
131 for i in inf..hi {
132 if i.is_prime() {
133 primevector.push(i)
134 }
135 }
136 primevector
137 }
138
139 fn nth_prime(&self) -> NTResult<Self> {
140 let mut count = 0u64;
141 let mut start = 0u64;
142
143if *self > 425656284035217743{
148 return NTResult::Overflow
149 }
150
151 loop {
152 start += 1;
153
154 if start == Self::MAX {
155 return NTResult::Overflow;
156 }
157 if start.is_prime() {
158 count += 1;
159 }
160 if count == *self {
161 return NTResult::Eval(start);
162 }
163 }
164 }
165
166 fn pi(&self) -> Self {
167 if self.reducible(){
168 return (*self as u32).pi() as u64
169 }
170
171 let mut count = 203280221u64;
172 for i in (1u64<<32)..*self {
173 if i.is_prime() {
174 count += 1;
175 }
176 }
177 count
178 }
179
180 fn prime_gen(k: u32) -> NTResult<Self> {
181 if k > 64 {
182 return NTResult::Overflow;
183 }
184 if k < 33 {
185 return u32::prime_gen(k).map(|x| x as u64);
186 }
187 let form = (1 << (k - 1)) + 1;
188 let bitlength = form - 2;
189
190 loop {
191 let p = u64::rng();
192 if ((p & bitlength) | form).is_prime() {
193 return NTResult::Eval((p & bitlength) | form);
194 }
195 }
196 }
197
198 fn factor(&self) -> NTResult<Factorization<Self>> {
199 if *self == 0{
204 return NTResult::InfiniteSet;
205 }
206
207 if *self == 1{
208 return NTResult::DNE
209 }
210 let mut n = *self;
211 let twofactors = n.trailing_zeros();
212 n >>= twofactors;
213
214 let mut factors: Factorization<u64> = Factorization::new();
215
216 if twofactors > 0 {
217 factors.add_factor(2);
218 factors.add_power(twofactors as u64);
219 }
220
221 for i in PRIMELIST[1..128].iter() {
222 if n % *i as u64 == 0 {
224 factors.add_factor(*i as u64);
225 let mut count = 0u64;
226 while n % *i as u64 == 0 {
227 count += 1;
228 n /= *i as u64;
229 }
230 factors.add_power(count);
231 }
232 }
233
234 if n == 1 {
235 return NTResult::Eval(factors);
236 }
237
238 if n.is_prime() {
239 factors.add_factor(n);
240 factors.add_power(1);
241 return NTResult::Eval(factors);
242 }
243
244 while n != 1 {
245 let k = poly_factor(n);
246 factors.add_factor(k);
247 let mut count = 0u64;
248 while n % k == 0 {
249 count += 1;
250 n /= k;
251 }
252 factors.add_power(count);
253
254 if n.is_prime() {
255 factors.add_factor(n);
256 factors.add_power(1);
257 return NTResult::Eval(factors);
258 }
259
260 }
261 NTResult::Eval(factors)
262 }
263
264
265
266 fn sqrt(&self) -> (Self, Self) {
267 let mut est = (*self as f64).sqrt() as Self + 1;
271
272 loop {
273 let s = est;
274 let t = s + *self / s;
275 est = t >> 1;
276 if est >= s {
277 return (s, 0);
278 }
279 }
280 }
281
282 fn nth_root(&self, n: Self) -> (Self, Self) {
283 if n > 63 {
284 return (1, 0);
285 }
286
287 if n == 1 {
288 return (n, 0);
289 }
290
291 if n == 0 {
292 panic!("No integer is a zeroth factor ")
293 }
294
295 let mut est = (*self as f64).powf((n as f64).recip()) as Self + 1;
296
297 loop {
298 let s = est;
299 let t = (n - 1) * s + *self / s.pow(n as u32 - 1);
300 est = t / n;
301 if est >= s {
302 return (s, 0);
303 }
304 }
305 }
306
307 fn max_exp(&self) -> (Self,Self){
308
309 for i in 1..64{
310 let p = 64-i;
311 let base = self.nth_root(p).0;
312 if base.pow(p as u32) == *self{
313 return(base,p)
314 }
315 }
316 (*self,1)
317 }
318
319 fn radical(&self) -> NTResult<Self> {
320 if self.reducible(){
321 return (*self as u32).radical().map(|kishum| kishum as u64)
322 }
323 self.factor().map(|y| y.factor_iter().product::<Self>())
324 }
325
326 fn k_free(&self, k: Self) -> bool {
327 if self.reducible(){
328 return (*self as u32).k_free(k as u32)
329 }
330 let factors = self.factor().unwrap();
332 factors.k_free(k)
333 }
334
335 fn gcd(&self, other: Self) -> Self {
336 let mut a = *self;
337 let mut b = other;
338 if b == 0 {
339 return a;
340 } else if a == 0 {
341 return b;
342 }
343
344 let self_two_factor = a.trailing_zeros();
345 let other_two_factor = b.trailing_zeros();
346 let min_two_factor = std::cmp::min(self_two_factor, other_two_factor);
347 a >>= self_two_factor;
348 b >>= other_two_factor;
349 loop {
350 if b > a {
351 std::mem::swap(&mut b, &mut a);
352 }
353 a -= b;
354
355 if a == 0 {
356 return b << min_two_factor;
357 }
358 a >>= a.trailing_zeros();
359 }
360 }
361
362 fn extended_gcd(&self, other: Self) -> (Self, Self, Self) {
363 let mut gcd: u64 = *self;
364 let mut new_r: u64 = other;
365 let mut bezout_1: u64 = 1;
366 let mut new_s: u64 = 0;
367 let mut bezout_2: u64 = 0;
368 let mut new_t: u64 = 1;
369
370 while new_r != 0 {
371 let quotient = gcd / new_r;
372 let mut temp: u64 = new_r;
373 new_r = gcd - quotient * temp;
374 gcd = temp;
375
376 temp = new_s;
377 if bezout_1 < quotient.product_residue(temp, other) {
378 new_s = other - (quotient.product_residue(temp, other) - bezout_1)
380 } else {
381 new_s = bezout_1.wrapping_sub(quotient * temp);
382 }
383
384 bezout_1 = temp;
385
386 temp = new_t;
387 if bezout_2 < quotient.product_residue(temp, *self) {
388 new_t = *self - (quotient.product_residue(temp, *self) - bezout_2)
390 } else {
391 new_t = bezout_2.wrapping_sub(quotient.product_residue(temp, *self));
392 }
393 bezout_2 = temp
394 }
395 (gcd, bezout_1, bezout_2)
396 }
397fn lcm(&self, other: Self) -> NTResult<Self> {
403 if self == &0 && other == 0{
404 return NTResult::Eval(0)
405 }
406 let cf = self.gcd(other);
407 let (v, flag) = (*self / cf).overflowing_mul(other);
408 if flag {
409 return NTResult::Overflow;
410 }
411 NTResult::Eval(v)
412 }
413
414 fn euler_totient(&self) -> Self {
415 if self.reducible(){
416 return (*self as u32).euler_totient() as u64
417 }
418 let factors = self.factor().unwrap();
419 let numerator = factors.factor_iter().map(|x| x - 1u64).product::<u64>();
420 let denominator = factors.factor_iter().product::<u64>();
421 (self / denominator) * numerator
422 }
423
424 fn jordan_totient(&self, k: Self) -> NTResult<Self> {
425 if k > u32::MAX as u64 {
426 return NTResult::Overflow;
427 }
428
429 if *self < 2{
430 return NTResult::Eval(*self)
431 }
432
433 let (coef, flag) = self.overflowing_pow(k as u32);
434
435 if flag {
436 return NTResult::CompOverflow;
437 }
438
439 let mut denom = 1u64;
440 let mut numer = 1u64;
441
442 for i in self.factor().unwrap().factor_iter(){
443 let pow = i.pow(k as u32);
444
445 denom *= pow;
446
447 numer *= pow - 1;
448 }
449
450 NTResult::Eval(numer * (coef / denom))
451 }
452
453 fn exponent(&self) -> NTResult<Self>{
454
455 if self.reducible(){
456 return (*self as u32).exponent().map(|x| x as u64)
457 }
458
459 if *self == 0{
460 return NTResult::Infinite;
461 }
462 let fctr = self.factor().unwrap();
463 let mut result = 1;
464 for i in 0..fctr.base.len(){
465 if fctr.base[0] == 2 && fctr.power[0] > 2{
466 let phi = 2u64<<(fctr.power[0]-1);
467 result=phi;
468 }
469 else{
470 let el = fctr.base[i];
471 let phi = (el.pow(fctr.power[i] as u32)/el)*(el-1);
472 match result.lcm(phi){
473 NTResult::Overflow => {return NTResult::Overflow;},
474 NTResult::Eval(x) => result=x,
475 _=> (),
476 }
477 }
478 }
479 return NTResult::Eval(result);
480 }
481
482 fn dedekind_psi(&self, k: Self) -> NTResult<Self> {
483 if *self == 0{
484 return NTResult::Infinite
485 }
486
487 let (k2, flag) = k.overflowing_shl(1);
488 if flag {
489 return NTResult::Overflow;
490 }
491 self.jordan_totient(k2).map(|y| y/self.jordan_totient(k).unwrap())
492 }
493
494 fn quadratic_residue(&self, n: Self) -> Self {
495 if n == 0 {
496 return self.wrapping_mul(*self)
497 }
498 ((*self as u128 * *self as u128) % n as u128) as Self
499 }
500
501 fn checked_quadratic_residue(&self, n: Self) -> NTResult<Self> {
502 if n == 0 {
503 return NTResult::from_option(self.checked_mul(*self),NTResult::Overflow)
504 }
505 NTResult::Eval(((*self as u128 * *self as u128) % n as u128) as Self)
506 }
507
508
509 fn product_residue(&self, other: Self, n: Self) -> Self {
510 if n == 0 {
511 return self.wrapping_mul(other)
512 }
513 ((*self as u128 * other as u128) % n as u128) as Self
514 }
515
516 fn checked_product_residue(&self, other: Self, n: Self) -> NTResult<Self> {
517 if n == 0 {
518 return NTResult::from_option(self.checked_mul(*self),NTResult::Overflow)
519 }
520 NTResult::Eval(((*self as u128 * other as u128) % n as u128) as Self)
521 }
522
523 fn exp_residue(&self, p: Self, modulus: Self) -> Self {
524
525 if modulus == 0 {
526 return self.pow(p as u32);
527 }
528
529 if modulus & 1 == 0 {
530
531 let k = modulus.trailing_zeros() as u64;
532 let s = modulus >> k;
533
534 let reducer = (1 << k) - 1; let k_rem = self.even_pow(p,reducer);
537
538 let s_rem = self.odd_pow(p,s);
539
540 let s_inv = s.inv_2()&reducer;
541
542 let y = k_rem.wrapping_sub(s_rem).wrapping_mul(s_inv) & reducer;
543
544 s_rem + s * y } else {
546 self.odd_pow(p,modulus) }
548 }
549
550 fn checked_exp_residue(&self, p: Self, modulus: Self) -> NTResult<Self> {
551 if modulus == 0 {
552 if p > u32::MAX as u64 {
553 return NTResult::Overflow;
554 }
555 match self.checked_pow(p as u32) {
556 Some(x) => return NTResult::Eval(x),
557 None => return NTResult::Overflow,
558 };
559 }
560
561 NTResult::Eval(self.exp_residue(p,modulus))
562 }
563
564 fn legendre(&self, p: Self) -> i8 {
565 let k = self.exp_residue((p - 1) >> 1, p);
566 if k == 1 {
567 return 1;
568 };
569 if k == p - 1 {
570 return -1;
571 };
572 0i8
573 }
574
575 fn checked_legendre(&self, p: Self) -> NTResult<i8> {
576 if p == 2 || !p.is_prime() {
577 return NTResult::Undefined;
578 }
579 NTResult::Eval(self.legendre(p))
580 }
581
582 fn liouville(&self) -> i8 {
583 if self.reducible(){
584 return (*self as u32).liouville()
585 }
586 let primeomega = self.factor().unwrap().prime_omega();
587 if primeomega & 1 == 0 {
588 return 1;
589 }
590 -1
591 }
592
593 fn derivative(&self) -> NTResult<Self> {
594 if *self < 94 {
595 return (*self as u32).derivative().map(|y| y as Self)
596 }
597
598 let fctr = self.factor().unwrap();
599 let mut sum : u64 = 0;
600
601 for (power,base) in fctr.power_iter().zip(fctr.factor_iter()){
602 match sum.checked_add((*power as u64)*(*self/base)){
603 Some(x) => sum =x,
604 None => return NTResult::Overflow,
605 }
606 }
607 NTResult::Eval(sum)
608 }
609
610 fn mangoldt(&self) -> f64 {
611 if self.reducible(){
612 return (*self as u32).mangoldt()
613 }
614 let base = self.max_exp().0;
615 if base.is_prime(){
616 return (base as f64).ln()
617 }
618 0f64
619 }
620
621 fn mobius(&self) -> i8 {
622 let fctr = self.factor().unwrap();
626 if !fctr.k_free(2){
630 return 0;
631 }
632 let fctrsum = fctr.prime_omega();if fctrsum&1 == 1{return -1
635 }
636 1
637 }
638
639 fn jacobi(&self, k: Self) -> NTResult<i8> {
640 if k == 0 && k % 2 == 0 {
641 return NTResult::Undefined;
642 }
643 let mut n = *self;
644 let mut p = k;
645 let mut t = 1i8;
646 n %= p;
647
648 while n != 0 {
649 let zeros = n.trailing_zeros();
650 n >>= zeros;
651
652 if (p % 8 == 3 || p % 8 == 5) && (zeros % 2 == 1) {
653 t = -t
654 }
655
656 std::mem::swap(&mut n, &mut p);
657 if n % 4 == 3 && p % 4 == 3 {
658 t = -t;
659 }
660 n %= p;
661 }
662
663 if p == 1 {
664 NTResult::Eval(t)
665 } else {
666 NTResult::Eval(0)
667 }
668 }
669
670 fn kronecker(&self, k: Self) -> i8{
671 let x = *self;
672 if k == 0{
673 if x == 1{
674 return 1
675 }
676 return 0
677 }
678 if k == 1{
679 return 1
680 }
681 let fctr = k.factor().unwrap();
682 let mut start = 0;
683 let mut res = 1;
684
685 if fctr.base[0] == 2{
686 start = 1;
687 if x&1 == 0{
688 res = 0;
689 }
690 else if x % 8 == 1 || x % 8 == 7{
691 res=1
692 }
693 else{
694 res = (-1i8).pow(fctr.power[0] as u32)
695 }
696 }
697 if fctr.base[0] == 2 && fctr.base.len() == 1{
698 return res
699 }
700 for i in start..fctr.base.len(){
701 res*=self.legendre(fctr.base[i]).pow(fctr.power[i] as u32);
702 }
703 res
704}
705
706
707
708 fn smooth(&self) -> NTResult<Self> {
709 if *self == 0{
710 return NTResult::Infinite
711 }
712 if *self == 1{
713 return NTResult::DNE
714 }
715 self.factor().map(|x| x.max())
716
717 }
718
719
720
721 fn is_smooth(&self, b: Self) -> bool {
722 match self.smooth(){
723 NTResult::Infinite => false,
724 NTResult::Eval(x) => x <= b,
725 _=> false,
726 }
727 }
728
729 fn ord(&self, n: Self) -> NTResult<Self>{
730 let ord_2 = |a: u64, p: u64| -> u64{
731 let modulo = (1u64<<p)-1;
732 let mut b = a&modulo;
733
734 if b == 1{
735 return 1;
736 }
737 for i in 1..p{
738 b = b.wrapping_mul(b)&modulo;
739 if b == 1{
740 return 1<<i;
741 }
742 }
743 return p;
744 };
745
746let pp_ord = |a: u64, b: u64, p: u64, e: u32| -> u64{
748 for i in 0..e+1{
749 if a.exp_residue(b*p.pow(i),p.pow(e)) ==1{
750 return b*p.pow(i);
751 }
752 }
753 return b*p.pow(e);
754 };
755
756 let p_ord = |a: u64, p: u64| -> u64{
757
758 let fctr = (p-1).factor().unwrap();
759
760 let mut m = p-1;
761 for i in fctr.pair_iter(){
762 for _ in 0..*i.1{
763 if a.exp_residue(m/ *i.0,p) == 1{
764 m = m/ *i.0;
765 }
766 else{
767 break;
768 }
769 }
770 }
771 m
772};
773
774
775 if self.gcd(n) != 1{
776 return NTResult::DNE;
777 }
778 let fctr = n.factor().unwrap();
779 let mut fullord = 1u64;
780 for i in fctr.pair_iter(){
781 let mut ord : Self;
782 if *i.0 == 2{
783 ord = ord_2(*self,*i.1);
784 }
785 else{
786 ord = p_ord(*self,*i.0);
787 if *i.1 > 1{
788 ord=pp_ord(*self,ord,*i.0,*i.1 as u32);
789 }
790 }
791 fullord = fullord.lcm(ord).unwrap();
792 }
793 NTResult::Eval(fullord)
794 }
795
796}