number_theory/
ntrait.rs

1use crate::result::NTResult;
2use crate::structs::{Factorization,Certificate};
3
4pub(crate) trait MontArith{
5
6  fn to_mont(self,ring: Self) -> Self;
7  
8  fn to_z(self, inv: Self, ring: Self) -> Self; 
9  
10  fn inv_2(self) -> Self;
11  
12  fn n_identity(self) -> Self;
13  
14  fn mont_sub(self,subtrahend: Self, ring: Self) -> Self;
15  
16  fn mont_add(self,addend: Self, ring: Self) -> Self;
17  
18  fn mont_prod(self, multiplicand: Self, inv: Self, ring: Self) -> Self;
19  
20  fn mont_sqr(self, inv: Self, ring: Self) -> Self;
21  
22  fn mont_pow(self,one: Self,p: Self, inv: Self, ring: Self) -> Self;
23  
24  fn odd_pow(self, p: Self, ring: Self) -> Self; 
25  
26  fn even_pow(self, p: Self, twofactor: Self) -> Self;
27}
28
29/// Trait for number-theory functions across all integer types
30pub trait NumberTheory : Default + Clone + Sized + std::fmt::Display + std::cmp::Ord{
31    /// Random number generation, generally high-quality
32    fn rng() -> Self;
33
34    ///Euclidean function, normally called euclidean division, returns Q,R such that Q*y + R = x
35    /// # Panic
36    /// y == 0
37    fn euclidean_div(&self, other: Self) -> (Self, Self)
38    where
39        Self: Sized;
40
41    /// Returns true if 1 or -1
42    fn is_unit(&self) -> bool;
43        
44    /// Returns the representation of x in the ring Z\[n\]     
45    fn residue(&self, ring: Self) -> Self;
46    
47    /// Returns x^-1 := x^-1*x mod n = 1 
48    /// # DNE
49    /// Multiplicative inverse doesn't exist
50    fn mul_inverse(&self,n: Self)  -> NTResult<Self>;
51
52    /// base^x-1 mod x == 1
53    fn fermat(&self, base: Self) -> bool;
54    /** Strong probable prime test.Performs Selfridge test exactly which means that if gcd(x,base) > 1 and x is a prime 
55    then it will be flagged as composite
56
57    Correct primality tests account for this, so it is up to the user to account for them as well.
58    */
59    fn strong_fermat(&self, base: Self) -> bool;
60    /**
61    Optimized for the average case. Although speed is valued over
62    determinism, the probability of failure is extremely small and never deterministic beyond 2^128 (i.e repeating the test will
63    almost certainly fail a previous composite that passed).
64
65     N < 2^64 + 2^49 Provably correct deterministic test, uniquely uses a maximum of 2 strong fermat tests giving it the lowest average
66     complexity publicly known. Average complexity 0.3  tests, worst-case 2.6 sprp checks (against 2^64-59)
67     
68     2^64 < N < 2^128 Deterministic BPSW variant, no known counterexamples but they may exist. 
69
70     N > 2^128  Weighted to ensure 2^-64 probability of failure against a random input.Performs a minimum of 3 sprp checks. 
71     Strongest counterexamples are of the form n = p(x(p-1)+1)(y(p-1)+1) where p is prime and gcd(x,y,p) = 1 and n > 2^512, passing at 
72     a rate of approximately 25%. Any other equally strong counterexamples are encouraged to be reported. Further strengthening the test 
73     should be by calling [sprp_check](struct.Mpz.html#method.sprp_check) afterwards **not** by calling is_prime again. Average complexity 0.18
74      worst case 12 sprp checks (typical worst case is around 3.1, 12 is the absolute worst case against a very narrow interval). 
75
76
77     Mersenne : Deterministic, not computed
78
79     Fermat : Deterministic, not computed,  assumed to not exist beyond 65537 .
80    */
81    /* {undocumented comment} 
82        One might be curious as to why 3 sprp tests are selected,  this is due to a  special configuration of checks that makes them 
83        equivalent to around 5 standard tests, so in reality not only does is_prime meet the advertised requirements it far exceeds it, being
84        fully deterministic against nearly half of all pseudoprimes. Additionally Lucas sequence and quadratic Frobenius tests are not used
85        because the current configuration is trivially parallelizable to the cost of only a single sprp test. (versus two for a lucas and
86         3 for a Frobenius). As stated in the documented comment is_prime is configured to be optimal in the average case, the Carmichael 
87         numbers that do pass with a relatively high probability are statistically so rare that they are inconsequential.
88    */    
89    fn is_prime(&self) -> bool;
90
91    /**
92       Checks primality for the integer and returns the evaluation in addition to a vector of the witness
93       followed by the factors of n-1. For instance  269u64.prime_proof may return (true, [238, 2,67]).
94        Verification requires checking that 238.exp_residue(269-1, 269) == 1
95        and 238.exp_residue((269-1)/2, 269) != 1 and 238.exp_residue((269-1)/67, 269) != 1. See prime_proof in examples to see how.
96        Unable to construct a proof for Carmichael numbers. 
97    */
98    fn prime_proof(&self) -> Certificate<Self>
99    where
100        Self: Sized;
101
102    /**
103         Enumerates the primes between self and sup values. If sup < self then it enumerates up to self from sup.
104         Note that while evaluation is possible for any interval it becomes infeasible with very large numbers
105          (>10^6000) or very large intervals (>10^12).
106    */
107    fn prime_list(&self, sup: Self) -> Vec<Self>
108    where
109        Self: Sized;
110
111    /**
112    N-th prime, exact evaluation for less than 2^64, approximation beyond that.  Not currently feasible beyond 10^12
113     */
114     /// # DNE
115     /// n == 0  (there is no zeroth prime)
116     /// # Overflow
117     /// Pn > datatype MAX
118
119    fn nth_prime(&self) -> NTResult<Self>
120    where
121        Self: Sized + Clone;
122        
123        
124    /// Generates an odd positive prime in the interval 2^(k-1);2^k 
125    /// # DNE
126    /// x == 0
127    /// # Overflow
128    /// x > datatype length in bits 
129    fn prime_gen(k: u32) -> NTResult<Self>
130    where 
131        Self : Sized + Clone;
132 
133 
134    /// Prime-counting function, exact evaluation for less than 2^64, approximation beyond that. Not currently feasible beyond 10^12
135    fn pi(&self) -> Self;
136
137    /// Factorizes 
138    
139    /// # InfiniteSet 
140    /// x == 0
141    /// # DNE
142    /// x == 1
143    fn factor(&self) -> NTResult<Factorization<Self>>
144    where
145        Self: Sized+Clone;
146        
147    /// Returns the integer component of at least one solution to the equation x*x = n where x in Z\[i\] (aka the Gaussian integers).
148    /// When   x  < 0 the result is (sqrt(x),1) otherwise it is the (sqrt(x),0)
149    fn sqrt(&self) -> (Self, Self)
150    where
151        Self: Sized;
152        
153    /// Returns the integer component of one of the solutions to the equation x*x..*x where x in Z\[i\]
154    fn nth_root(&self, n: Self) -> (Self, Self)
155    where
156        Self: Sized;
157        
158    /** Returns the representation of x as a base and exponent biasing towards high exponents. E.g 81 -> 3^4 
159        If no higher representation of the number exists then it will return the trivial solution of x^1
160    */
161    fn max_exp(&self) -> (Self, Self)
162    where 
163        Self: Sized;
164        
165    /// Binary gcd, Computes the greatest common divisor of two numbers
166    fn gcd(&self, other: Self) -> Self;
167
168    /**
169     Extended Euclidean GCD algorithm.
170     The behavior of this function varies depending on if the type is in Z or N.
171
172     Z : returns the GCD and Bezout coefficients (x,y) such that gcd(a,b) = ax + by
173
174     N : returns the GCD and Bezout coefficients such that ax + by = gcd(a,b) over Z\[lcm(a,b)\]
175
176     Note that if gcd(a,b) != a OR b this is equivalent to ax mod b  = gcd(a,b)  and by mod a = gcd(a,b).
177     In the case of gcd(a,b) =1 these coefficients are the multiplicative inverses of a over Z\[b\]
178      and b over Z\[a\], respectively
179
180
181    */
182    fn extended_gcd(&self, other: Self) -> (Self, Self, Self)
183    where
184        Self: Sized;
185    
186    /// Determines if a gcd(a,b) == 1
187    fn coprime(&self, other: Self) -> bool{
188          self.gcd(other).is_unit()
189	}
190    
191    /// Computes the least common multiple checking for overflow, and zeroes
192    /// # Overflow
193    /// lcm(x,y) > datatype MAX
194    fn lcm(&self, other: Self) -> NTResult<Self>;
195
196   //  Exponent of the multiplicative group Z/nZ, also called the Carmichael totient of n
197   //  # Infinite
198   //   x == 0 As the infinite group of Z/0Z has no exponent 
199    fn exponent(&self) -> NTResult<Self>
200    where
201        Self: Sized + Clone;
202    
203    /// Counts the number of coprimes from 0 to self
204    fn euler_totient(&self) -> Self;
205
206    /// Counts the Jordan's totient
207    ///# Overflow
208    /// Jordan_totient(x,k) > datatype MAX
209    /// # CompOverflow
210    /// Computation overflowed
211    fn jordan_totient(&self, k: Self) -> NTResult<Self>
212    where
213        Self: Sized + Clone;
214
215    ///  Higher-order Dedekind psi
216    /// # Overflow
217    /// dedekind_psi(x,k) > datatype MAX
218    /// # CompOverflow
219    /// Computational overflow
220    fn dedekind_psi(&self, k: Self) -> NTResult<Self>
221    where
222        Self: Sized + Clone;
223
224    /// Returns x*y mod n
225    /// # Failure
226    /// if x * y > datatype MAX  AND n == 0 
227    fn product_residue(&self, other: Self, n: Self) -> Self;
228    
229    /// Returns x*y mod n
230    /// # Overflow
231    /// if x * y > datatype MAX  AND n == 0 
232    fn checked_product_residue(&self, other: Self, n: Self) -> NTResult<Self>
233    where
234        Self: Sized + Clone;
235     
236    /// Returns x*x mod n, similar to product_residue except more optimized squaring.
237    /// # Failure
238    /// if x * x > datatype MAX  AND n == 0
239    fn quadratic_residue(&self, n: Self) -> Self;
240
241    /// Returns x*x mod n, similar to product_residue except more optimized squaring.
242    /// # Overflow
243    /// if x * x > datatype MAX  AND n == 0
244    fn checked_quadratic_residue(&self, n: Self) -> NTResult<Self>
245    where
246        Self: Sized + Clone;
247        
248    /** Returns x^y mod n, generally called mod_pow in other libraries. If y < 0 returns -x^|y| mod n,
249    aka the exponentiation of the multiplicative inverse, analogous to the behavior in the Reals.
250   */ 
251    /// # Failure
252    /// If y < 0 and gcd(x,n) > 1, or n = 0 and x^y > datatype MAX
253    
254    fn exp_residue(&self, pow: Self, n: Self) -> Self;
255
256    /// Exponential residue x^y mod n
257    /// # DNE 
258    ///  y < 0 AND gcd(x,n) > 1
259    /// # Overflow
260    /// n == 0 AND x^y > datatype MAX 
261    fn checked_exp_residue(&self, pow: Self, n: Self) -> NTResult<Self>
262    where
263        Self: Sized + Clone;
264
265    // Returns an x such that x*x = a over Z/nZ    
266    // # None
267    // If x does not exist
268 //   fn sqrt_residue(&self, n: Self) -> Option<Self>
269 //   where 
270 //       Self: Sized;
271        
272    /// Determines of a number is k-free, i.e square-free, cube-free etc. . .
273    fn k_free(&self, k: Self) -> bool;
274/*
275    fn partition(&self) -> Option<Self>
276    where
277        Self: Sized;
278  */
279    
280    /// Returns the product of each prime such that p | n AND p > 0
281    /// # Infinite
282    ///  x == 0
283    fn radical(&self) -> NTResult<Self>
284    where
285        Self: Sized + Clone;
286
287    /// Returns the smoothness bound of n, this is the largest prime factor of n.
288    /// # Infinite
289    /// x == 0 
290    fn smooth(&self) -> NTResult<Self>
291    where
292        Self: Sized + Clone;
293
294
295    /// Checks if the smoothness bound is at least b
296    fn is_smooth(&self, b: Self) -> bool;
297
298    /// Legendre symbol of a,p.
299    /// # Failure
300    /// P is not an odd prime
301    fn legendre(&self, p: Self) -> i8;
302    
303    /// Legendre symbol of a,p. 
304    /// # Undefined 
305    /// P is not an odd prime
306    fn checked_legendre(&self, p: Self) -> NTResult<i8>;
307
308    /// Liouville function
309    fn liouville(&self) -> i8;
310    
311    /// Lagarias derivative
312    /// # Overflow
313    /// D(x) > datatype MAX
314    fn derivative(&self) -> NTResult<Self>
315    where 
316        Self : Sized + Clone;
317
318    ///Von Mangoldt function, returns the natural logarithm of self if it is a prime-power
319    fn mangoldt(&self) -> f64;
320
321    ///  Mobius function
322    fn mobius(&self) -> i8;
323
324    /// Jacobi symbol of x,p. 
325    /// # Undefined
326    /// P is not an odd, positive integer
327    fn jacobi(&self, p: Self) -> NTResult<i8>;
328    
329    /// Kronecker symbol
330    fn kronecker(&self, k: Self) -> i8;
331    
332    /// Multiplicative order of a mod N
333    /// # DNE
334    /// Multiplicative order does not exist
335    fn ord(&self,n: Self) -> NTResult<Self>;
336}
337
338// ENT maps to 32-bit as modular arithmetic requires promoting to 64-bit
339
340pub(crate) trait Reduction{
341  fn reducible(&self) -> bool;
342}
343
344macro_rules! reducer(
345  ($($t:ty; $s:ty),* $(,)*) => {$(
346  
347  impl Reduction for $t{
348  #[inline]
349  fn reducible(&self) -> bool{
350    if *self < <$s>::MAX as $t{
351      return true
352    }
353    return false
354  } 
355  }
356    )*}
357);
358
359reducer!(u64;u32, i64;i32, u128;u64, i128;i64);
360/*
361impl Reduction for Mpz{
362  fn reducible(&self) -> bool{
363    if self.len() < 3{
364      return true
365    }
366    false
367  }
368}
369*/
370/*
371pub(crate) trait NumberTheory{
372    fn fermat
373    fn strong_fermat
374    fn gcd
375    fn jacobi
376    fn legendre
377    fn kronecker
378    fn prime_proof
379    fn is_prime
380    fn sqrt_residue
381    fn exp_residue
382    fn extended_gcd
383    fn nth_prime
384    fn pi
385    fn prime_list
386    fn prime_gen
387    fn factor
388    fn lcm
389    fn exponent
390    fn euler
391    fn jordan
392    fn dedekind
393    fn radical
394    fn k_free
395    fn mangoldt
396    fn mobius
397    fn power_residue
398    fn ind
399    fn ord
400    fn partition
401    fn primitive_root
402}
403*/
404
405