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