#![no_std]
#[cfg(any(feature = "std", test))]
extern crate std;
use core::ops::{Add, Mul, Neg, Sub};
pub trait ModularCoreOps<Rhs = Self, Modulus = Self> {
type Output;
fn addm(self, rhs: Rhs, m: Modulus) -> Self::Output;
fn subm(self, rhs: Rhs, m: Modulus) -> Self::Output;
fn mulm(self, rhs: Rhs, m: Modulus) -> Self::Output;
}
pub trait ModularUnaryOps<Modulus = Self> {
type Output;
fn negm(self, m: Modulus) -> Self::Output;
fn invm(self, m: Modulus) -> Option<Self::Output>;
fn dblm(self, m: Modulus) -> Self::Output;
fn sqm(self, m: Modulus) -> Self::Output;
}
pub trait ModularPow<Exp = Self, Modulus = Self> {
type Output;
fn powm(self, exp: Exp, m: Modulus) -> Self::Output;
}
pub trait ModularSymbols<Modulus = Self> {
#[inline]
fn legendre(&self, n: Modulus) -> i8 {
self.checked_legendre(n).expect("n shoud be a prime")
}
fn checked_legendre(&self, n: Modulus) -> Option<i8>;
#[inline]
fn jacobi(&self, n: Modulus) -> i8 {
self.checked_jacobi(n)
.expect("the Jacobi symbol is only defined for non-negative odd integers")
}
fn checked_jacobi(&self, n: Modulus) -> Option<i8>;
fn kronecker(&self, n: Modulus) -> i8;
}
pub trait ModularOps<Rhs = Self, Modulus = Self, Output = Self>:
ModularCoreOps<Rhs, Modulus, Output = Output>
+ ModularUnaryOps<Modulus, Output = Output>
+ ModularPow<Rhs, Modulus, Output = Output>
+ ModularSymbols<Modulus>
{
}
impl<T, Rhs, Modulus> ModularOps<Rhs, Modulus> for T where
T: ModularCoreOps<Rhs, Modulus, Output = T>
+ ModularUnaryOps<Modulus, Output = T>
+ ModularPow<Rhs, Modulus, Output = T>
+ ModularSymbols<Modulus>
{
}
pub trait ModularRefOps: for<'r> ModularOps<&'r Self, &'r Self> + Sized {}
impl<T> ModularRefOps for T where T: for<'r> ModularOps<&'r T, &'r T> {}
pub trait ModularAbs<Modulus> {
fn absm(self, m: &Modulus) -> Modulus;
}
pub trait ModularInteger:
Sized
+ PartialEq
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Neg<Output = Self>
+ Mul<Self, Output = Self>
{
type Base;
fn modulus(&self) -> Self::Base;
fn residue(&self) -> Self::Base;
fn is_zero(&self) -> bool;
fn convert(&self, n: Self::Base) -> Self;
fn double(self) -> Self;
fn square(self) -> Self;
}
pub trait DivExact<Rhs, Precompute>: Sized {
type Output;
fn div_exact(self, d: Rhs, pre: &Precompute) -> Option<Self::Output>;
}
pub trait Reducer<T> {
fn new(m: &T) -> Self;
fn transform(&self, target: T) -> T;
fn check(&self, target: &T) -> bool;
fn modulus(&self) -> T;
fn residue(&self, target: T) -> T;
fn is_zero(&self, target: &T) -> bool;
fn add(&self, lhs: &T, rhs: &T) -> T;
#[inline]
fn add_in_place(&self, lhs: &mut T, rhs: &T) {
*lhs = self.add(lhs, rhs)
}
fn dbl(&self, target: T) -> T;
fn sub(&self, lhs: &T, rhs: &T) -> T;
#[inline]
fn sub_in_place(&self, lhs: &mut T, rhs: &T) {
*lhs = self.sub(lhs, rhs);
}
fn neg(&self, target: T) -> T;
fn mul(&self, lhs: &T, rhs: &T) -> T;
#[inline]
fn mul_in_place(&self, lhs: &mut T, rhs: &T) {
*lhs = self.mul(lhs, rhs);
}
fn inv(&self, target: T) -> Option<T>;
fn sqr(&self, target: T) -> T;
fn pow(&self, base: T, exp: &T) -> T;
}
mod barret;
mod double;
mod mersenne;
mod monty;
mod preinv;
mod prim;
mod reduced;
mod word;
pub use barret::{
Normalized2by1Divisor, Normalized3by2Divisor, PreMulInv1by1, PreMulInv2by1, PreMulInv3by2,
};
pub use double::{udouble, umax};
pub use mersenne::FixedMersenne;
pub use monty::Montgomery;
pub use preinv::PreModInv;
pub use reduced::{ReducedInt, Vanilla, VanillaInt};
pub type MontgomeryInt<T> = ReducedInt<T, Montgomery<T>>;
pub type FixedMersenneInt<const P: u8, const K: umax> = ReducedInt<umax, FixedMersenne<P, K>>;
#[cfg(feature = "num-bigint")]
mod bigint;