use crate::algebra::*;
use core::iter::Iterator;
pub trait Distributive<T=Self> {}
pub trait Divisibility: Sized {
fn divides(self, rhs: Self) -> bool;
fn divide(self, rhs: Self) -> Option<Self>;
fn unit(&self) -> bool;
fn inverse(self) -> Option<Self>;
}
pub trait Primality: Divisibility {
fn irreducible(&self) -> bool;
fn prime(&self) -> bool;
}
pub trait NoZeroDivisors {}
pub trait GCD: Sized {
fn gcd(self, rhs: Self) -> Self;
fn lcm(self, rhs: Self) -> Self;
}
pub trait Bezout: GCD {
#[inline]
fn bezout_coefficients(self, rhs: Self) -> (Self, Self) {
let (a,b,_) = self.bezout_with_gcd(rhs);
(a,b)
}
fn bezout_with_gcd(self, rhs: Self) -> (Self, Self, Self);
}
pub trait UniquelyFactorizable: Sized {}
pub trait Factorizable: Sized {
type Factors: Iterator<Item=Self>;
fn factors(self) -> Self::Factors;
}
pub trait EuclideanDiv: Sized {
type Naturals: Natural;
fn euclid_norm(&self) -> Self::Naturals;
fn div_euc(self, rhs: Self) -> Self;
fn rem_euc(self, rhs: Self) -> Self;
fn div_alg(self, rhs: Self) -> (Self, Self);
}
pub trait Exponential: Sized {
fn exp(self) -> Self;
fn try_ln(self) -> Option<Self>;
}
pub trait Semiring = Distributive + AddMonoid + AddCommutative + MulSemigroup;
pub trait UnitalSemiring = Semiring + MulMonoid;
pub trait CommutativeSemiring = UnitalSemiring + MulCommutative;
pub trait DivisionSemiring = UnitalSemiring + MulGroup;
pub trait Ring = Distributive + AddAbelianGroup + MulSemigroup;
pub trait UnitalRing = Ring + MulMonoid;
pub trait CommutativeRing = UnitalRing + MulCommutative;
pub trait DivisionRing = UnitalRing + MulGroup;
pub trait ExponentialRing = UnitalRing + Exponential;
pub trait Semidomain = UnitalSemiring + Divisibility + NoZeroDivisors;
pub trait IntegralSemidomain = Semidomain + MulCommutative;
pub trait GCDSemidomain = IntegralSemidomain + GCD;
pub trait UFSemidomain = GCDSemidomain + UniquelyFactorizable;
pub trait EuclideanSemidomain = UFSemidomain + EuclideanDiv;
pub trait Domain = UnitalRing + Divisibility + NoZeroDivisors;
pub trait IntegralDomain = Domain + MulCommutative;
pub trait GCDDomain = IntegralDomain + GCD;
pub trait BezoutDomain = GCDDomain + Bezout;
pub trait UFD = GCDDomain + UniquelyFactorizable;
pub trait PID = UFD + BezoutDomain;
pub trait EuclideanDomain = PID + EuclideanDiv;
pub trait Field = CommutativeRing + MulGroup;
pub trait ExponentialField = Field + Exponential;
macro_rules! impl_dist {
($($t:ty)*) => {
$(
impl Distributive for $t{}
impl Distributive for ::core::num::Wrapping<$t>{}
)*
};
}
impl_dist!(usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64);
macro_rules! impl_for_field {
($($t:ty)*) => {
$(
impl Divisibility for $t {
#[inline(always)] fn divides(self, _rhs: Self) -> bool {true}
#[inline(always)] fn divide(self, rhs: Self) -> Option<Self> {Some(rhs / self)}
#[inline(always)] fn unit(&self) -> bool {true}
#[inline(always)] fn inverse(self) -> Option<Self> {Some(self.inv())}
}
impl NoZeroDivisors for $t {}
impl UniquelyFactorizable for $t {}
)*
}
}
impl_for_field!(f32 f64);
pub fn euclidean<T>(lhs: T, rhs: T) -> T where T:CommutativeSemiring+EuclideanDiv {
fn euclid<U>(a: U, b: U) -> U where U:CommutativeSemiring+EuclideanDiv
{
let r = a.rem_euc(b.clone());
if r.is_zero() {
b
}else{
euclid(b, r)
}
}
if lhs.is_zero() || rhs.is_zero() {return T::zero()}
if lhs.euclid_norm() >= rhs.euclid_norm() {
euclid(lhs, rhs)
} else {
euclid(rhs, lhs)
}
}
pub fn extended_euclidean<T>(lhs: T, rhs: T) -> (T, T, T) where T:CommutativeRing+EuclideanDiv {
fn euclid<U>(a: U, b: U) -> (U, U, U) where U:CommutativeRing+EuclideanDiv
{
let (q, r) = a.div_alg(b.clone());
if r.is_zero() {
(U::zero(), U::one(), b)
}else{
let (x1, y1, g) = euclid(b, r);
(y1.clone(), x1 - q * y1, g)
}
}
if lhs.is_zero() || rhs.is_zero() {
return (T::zero(), T::zero(), T::zero())
}
if lhs.euclid_norm() >= rhs.euclid_norm() {
euclid(lhs, rhs)
} else {
let (y, x, g) = euclid(rhs, lhs);
(x, y, g)
}
}
pub fn miller_rabin<Z:Natural>(n:Z) -> bool {
if n <= Z::one() { return false; }
if n == Z::two() { return true; }
if n.even() { return false; }
let mut d = n.clone() - Z::one();
let mut s = Z::zero();
while d.even() {
s = s + Z::one();
d = d.div_two();
}
#[inline]
fn witness<N:Natural>(witness:u128, d:N, s:N, n:N) -> bool {
_witness(N::try_from(witness).unwrap_or(N::zero()), d, s, n)
}
fn _witness<N:Natural>(mut a:N, mut d:N, mut s:N, n:N) -> bool {
let mut r = a.clone();
d = d - N::one();
while d > N::zero() {
if d.even() {
d = d.div_two();
a = (a.clone() * a) % n.clone();
} else {
d = d - N::one();
r = (r * a.clone()) % n.clone();
}
}
if r.is_one() {
true
} else {
loop {
if r == n.clone() - N::one() { return true; }
if s.is_zero() {
break;
} else {
s = s - N::one();
r = (r.clone() * r) % n.clone();
}
}
false
}
}
let b1 = Z::from_u32(2047u32);
let b2 = Z::from_u32(1373653u32);
let b3 = Z::from_u32(9080191u32);
let b4 = Z::from_u32(25326001u32);
let b5 = Z::from_u64(3215031751u64);
let b6 = Z::from_u64(4759123141u64);
let b7 = Z::from_u64(1122004669633u64);
let b8 = Z::from_u64(2152302898747u64);
let b9 = Z::from_u64(3474749660383u64);
let b10 = Z::from_u64(341550071728321u64);
let b11 = Z::from_u64(3825123056546413051u64);
let b12 = Z::from_u128(318665857834031151167461u128);
let b13 = Z::from_u128(3317044064679887385961981u128);
if b1.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone())
} else if b2.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(3, d.clone(), s.clone(), n.clone())
} else if b3.map_or(true, |x| n < x) {
witness(31, d.clone(), s.clone(), n.clone()) &&
witness(73, d.clone(), s.clone(), n.clone())
} else if b4.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(3, d.clone(), s.clone(), n.clone()) &&
witness(5, d.clone(), s.clone(), n.clone())
} else if b5.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(3, d.clone(), s.clone(), n.clone()) &&
witness(5, d.clone(), s.clone(), n.clone()) &&
witness(7, d.clone(), s.clone(), n.clone())
} else if b6.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(7, d.clone(), s.clone(), n.clone()) &&
witness(61, d.clone(), s.clone(), n.clone())
} else if b7.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(13, d.clone(), s.clone(), n.clone()) &&
witness(23, d.clone(), s.clone(), n.clone()) &&
witness(1662803, d.clone(), s.clone(), n.clone())
} else if b13.map_or(true, |x| n < x) {
witness(2, d.clone(), s.clone(), n.clone()) &&
witness(3, d.clone(), s.clone(), n.clone()) &&
witness(5, d.clone(), s.clone(), n.clone()) &&
witness(7, d.clone(), s.clone(), n.clone()) &&
witness(11, d.clone(), s.clone(), n.clone()) &&
if b8.map_or(false, |x| n >= x) { witness(13, d.clone(), s.clone(), n.clone()) } else {true} &&
if b9.map_or(false, |x| n >= x) { witness(17, d.clone(), s.clone(), n.clone()) } else {true} &&
if b10.map_or(false, |x| n >= x) {
witness(19, d.clone(), s.clone(), n.clone()) &&
witness(23, d.clone(), s.clone(), n.clone())
} else {true} &&
if b11.map_or(false, |x| n >= x) {
witness(29, d.clone(), s.clone(), n.clone()) &&
witness(31, d.clone(), s.clone(), n.clone()) &&
witness(37, d.clone(), s.clone(), n.clone())
} else {true} &&
if b12.map_or(false, |x| n >= x) { witness(41, d.clone(), s.clone(), n.clone()) } else {true}
} else {
let mut a = Z::two();
while Z::try_from(3.pow_n(a.clone().div_two())).unwrap_or(n.clone()) < n.clone().mul_two() {
if !_witness(a.clone(), d.clone(), s.clone(), n.clone()) {return false}
a = a + Z::one();
}
true
}
}
#[cfg(test)]
mod tests {
use crate::algebra::*;
#[test]
fn primality() {
assert!(18446744073709551557u64.prime());
assert!(!18446744073709551559u64.prime());
assert!(!18446744073709551555u64.prime());
assert!(2147483647u32.prime());
assert!(!2147483649u32.prime());
assert!(!2147483645u32.prime());
assert!(65521u16.prime());
assert!(65519u16.prime());
assert!(!65523u16.prime());
assert!(251u8.prime());
assert!(!253u8.prime());
assert!(!249u8.prime());
assert!(13u8.prime());
assert!(!15u8.prime());
}
#[test]
fn factor() {
#[cfg(feature = "std")] {
assert_eq!(91u8.factors().collect::<Vec<_>>(), vec![7,13] );
assert_eq!((-91i8).factors().collect::<Vec<_>>(), vec![-1,7,13] );
assert_eq!(360u16.factors().collect::<Vec<_>>(), vec![2,2,2,3,3,5] );
assert_eq!((-360i16).factors().collect::<Vec<_>>(), vec![-1,2,2,2,3,3,5] );
assert_eq!(1971813u32.factors().collect::<Vec<_>>(), vec![3,17,23,41,41] );
assert_eq!((-1971813i32).factors().collect::<Vec<_>>(), vec![-1,3,17,23,41,41] );
assert_eq!(1971813u32.factors().collect::<Vec<_>>(), vec![3,17,23,41,41] );
assert_eq!((-1971813i32).factors().collect::<Vec<_>>(), vec![-1,3,17,23,41,41] );
assert_eq!(0x344CAF57AB24A9u64.factors().collect::<Vec<_>>(), vec![101,101,103,103,107,107,109,109]);
assert_eq!((-0x344CAF57AB24A9i64).factors().collect::<Vec<_>>(), vec![-1,101,101,103,103,107,107,109,109]);
}
fn factors_slice<Z:IntegerSubset+Factorizable>(x:Z, dest: &mut [Z]) -> usize {
let mut i = 0;
for f in x.factors() {
if i<dest.len() {
dest[i] = f;
i += 1;
} else {
return i;
}
}
return i;
}
let mut factors = [0xFF; 3];
assert_eq!(factors_slice(0u8, &mut factors), 1);
assert_eq!(&factors, &[0,0xFF,0xFF]);
assert_eq!(factors_slice(1u8, &mut factors), 0);
assert_eq!(&factors, &[0,0xFF,0xFF]);
assert_eq!(factors_slice(210u8, &mut factors), 3);
assert_eq!(&factors, &[2,3,5]);
let mut factors = [0;10];
assert_eq!(factors_slice(-1i64, &mut factors), 1);
assert_eq!(&factors, &[-1,0,0,0,0,0,0,0,0,0]);
assert_eq!(factors_slice(-0x344CAF57AB24A9i64, &mut factors), 9);
assert_eq!(&factors, &[-1,101,101,103,103,107,107,109,109,0]);
assert_eq!(factors_slice(0x344CAF57AB24A9i64, &mut factors), 8);
assert_eq!(&factors, &[101,101,103,103,107,107,109,109,109,0]);
}
}