pub use num_traits::{
ConstOne, ConstZero, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr,
WrappingSub,
};
use crate::{Limb, NonZero, Odd, Reciprocal, modular::Retrieve};
use core::{
fmt::{self, Debug},
ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
SubAssign,
},
};
use subtle::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
CtOption,
};
#[cfg(feature = "rand_core")]
use rand_core::{RngCore, TryRngCore};
pub trait Bounded {
const BITS: u32;
const BYTES: usize;
}
pub trait ConstantTimeSelect: Clone {
fn ct_select(a: &Self, b: &Self, choice: Choice) -> Self;
#[inline]
fn ct_assign(&mut self, other: &Self, choice: Choice) {
*self = Self::ct_select(self, other, choice);
}
#[inline]
fn ct_swap(a: &mut Self, b: &mut Self, choice: Choice) {
let t: Self = a.clone();
a.ct_assign(b, choice);
b.ct_assign(&t, choice);
}
}
impl<T: ConditionallySelectable> ConstantTimeSelect for T {
#[inline(always)]
fn ct_select(a: &Self, b: &Self, choice: Choice) -> Self {
T::conditional_select(a, b, choice)
}
#[inline(always)]
fn ct_assign(&mut self, other: &Self, choice: Choice) {
self.conditional_assign(other, choice)
}
#[inline(always)]
fn ct_swap(a: &mut Self, b: &mut Self, choice: Choice) {
T::conditional_swap(a, b, choice)
}
}
pub trait Integer:
'static
+ Add<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ AddAssign<Self>
+ for<'a> AddAssign<&'a Self>
+ AsRef<[Limb]>
+ BitAnd<Output = Self>
+ for<'a> BitAnd<&'a Self, Output = Self>
+ BitAndAssign
+ for<'a> BitAndAssign<&'a Self>
+ BitOr<Output = Self>
+ for<'a> BitOr<&'a Self, Output = Self>
+ BitOrAssign
+ for<'a> BitOrAssign<&'a Self>
+ BitXor<Output = Self>
+ for<'a> BitXor<&'a Self, Output = Self>
+ BitXorAssign
+ for<'a> BitXorAssign<&'a Self>
+ CheckedAdd
+ CheckedSub
+ CheckedMul
+ CheckedDiv
+ Clone
+ ConstantTimeEq
+ ConstantTimeGreater
+ ConstantTimeLess
+ ConstantTimeSelect
+ Debug
+ Default
+ DivAssign<NonZero<Self>>
+ for<'a> DivAssign<&'a NonZero<Self>>
+ Eq
+ fmt::LowerHex
+ fmt::UpperHex
+ fmt::Binary
+ Mul<Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ MulAssign<Self>
+ for<'a> MulAssign<&'a Self>
+ Not<Output = Self>
+ One
+ Ord
+ Rem<NonZero<Self>, Output = Self>
+ for<'a> Rem<&'a NonZero<Self>, Output = Self>
+ RemAssign<NonZero<Self>>
+ for<'a> RemAssign<&'a NonZero<Self>>
+ Send
+ Sized
+ Shl<u32, Output = Self>
+ ShlAssign<u32>
+ ShlVartime
+ Shr<u32, Output = Self>
+ ShrAssign<u32>
+ ShrVartime
+ Sub<Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ SubAssign<Self>
+ for<'a> SubAssign<&'a Self>
+ Sync
+ WrappingAdd
+ WrappingSub
+ WrappingMul
+ WrappingNeg
+ WrappingShl
+ WrappingShr
+ Zero
{
fn nlimbs(&self) -> usize;
fn is_odd(&self) -> Choice {
self.as_ref()
.first()
.map(|limb| limb.is_odd())
.unwrap_or_else(|| Choice::from(0))
}
fn is_even(&self) -> Choice {
!self.is_odd()
}
}
pub trait Signed:
Div<NonZero<Self>, Output = CtOption<Self>>
+ for<'a> Div<&'a NonZero<Self>, Output = CtOption<Self>>
+ From<i8>
+ From<i16>
+ From<i32>
+ From<i64>
+ Integer
{
type Unsigned: Unsigned;
fn abs_sign(&self) -> (Self::Unsigned, Choice);
fn abs(&self) -> Self::Unsigned {
self.abs_sign().0
}
fn is_negative(&self) -> Choice;
fn is_positive(&self) -> Choice;
}
pub trait Unsigned:
AddMod<Output = Self>
+ BitOps
+ Div<NonZero<Self>, Output = Self>
+ for<'a> Div<&'a NonZero<Self>, Output = Self>
+ DivRemLimb
+ From<u8>
+ From<u16>
+ From<u32>
+ From<u64>
+ From<Limb>
+ Integer
+ MulMod<Output = Self>
+ NegMod<Output = Self>
+ RemLimb
+ SquareRoot
+ SquareMod<Output = Self>
+ SubMod<Output = Self>
{
type Monty: Monty<Integer = Self>;
fn from_limb_like(limb: Limb, other: &Self) -> Self;
}
pub trait Zero: ConstantTimeEq + Sized {
fn zero() -> Self;
#[inline]
fn is_zero(&self) -> Choice {
self.ct_eq(&Self::zero())
}
#[inline]
fn set_zero(&mut self) {
*self = Zero::zero();
}
fn zero_like(other: &Self) -> Self
where
Self: Clone,
{
let mut ret = other.clone();
ret.set_zero();
ret
}
}
pub trait One: ConstantTimeEq + Sized {
fn one() -> Self;
#[inline]
fn is_one(&self) -> Choice {
self.ct_eq(&Self::one())
}
#[inline]
fn set_one(&mut self) {
*self = One::one();
}
fn one_like(other: &Self) -> Self
where
Self: Clone,
{
let mut ret = other.clone();
ret.set_one();
ret
}
}
pub trait Constants: ConstZero + ConstOne {
const MAX: Self;
}
pub trait FixedInteger: Bounded + ConditionallySelectable + Constants + Copy + Integer {
const LIMBS: usize;
}
pub trait Gcd<Rhs = Self>: Sized {
type Output;
fn gcd(&self, rhs: &Rhs) -> Self::Output;
fn gcd_vartime(&self, rhs: &Rhs) -> Self::Output;
}
pub trait Xgcd<Rhs = Self>: Sized {
type Output;
fn xgcd(&self, rhs: &Rhs) -> Self::Output;
fn xgcd_vartime(&self, rhs: &Rhs) -> Self::Output;
}
#[cfg(feature = "rand_core")]
pub trait Random: Sized {
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
let Ok(out) = Self::try_random(rng);
out
}
fn try_random<R: TryRngCore + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
}
#[cfg(feature = "rand_core")]
#[derive(Debug)]
pub enum RandomBitsError<T> {
RandCore(T),
BitsPrecisionMismatch {
bits_precision: u32,
integer_bits: u32,
},
BitLengthTooLarge {
bit_length: u32,
bits_precision: u32,
},
}
#[cfg(feature = "rand_core")]
impl<T> fmt::Display for RandomBitsError<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::RandCore(err) => write!(f, "{err}"),
Self::BitsPrecisionMismatch {
bits_precision,
integer_bits,
} => write!(
f,
concat![
"The requested `bits_precision` ({}) does not match ",
"the size of the integer corresponding to the type ({})"
],
bits_precision, integer_bits
),
Self::BitLengthTooLarge {
bit_length,
bits_precision,
} => write!(
f,
"The requested `bit_length` ({bit_length}) is larger than `bits_precision` ({bits_precision}).",
),
}
}
}
#[cfg(feature = "rand_core")]
impl<T> core::error::Error for RandomBitsError<T> where T: Debug + fmt::Display {}
#[cfg(feature = "rand_core")]
pub trait RandomBits: Sized {
fn random_bits<R: TryRngCore + ?Sized>(rng: &mut R, bit_length: u32) -> Self {
Self::try_random_bits(rng, bit_length).expect("try_random_bits() failed")
}
fn try_random_bits<R: TryRngCore + ?Sized>(
rng: &mut R,
bit_length: u32,
) -> Result<Self, RandomBitsError<R::Error>>;
fn random_bits_with_precision<R: TryRngCore + ?Sized>(
rng: &mut R,
bit_length: u32,
bits_precision: u32,
) -> Self {
Self::try_random_bits_with_precision(rng, bit_length, bits_precision)
.expect("try_random_bits_with_precision() failed")
}
fn try_random_bits_with_precision<R: TryRngCore + ?Sized>(
rng: &mut R,
bit_length: u32,
bits_precision: u32,
) -> Result<Self, RandomBitsError<R::Error>>;
}
#[cfg(feature = "rand_core")]
pub trait RandomMod: Sized + Zero {
fn random_mod<R: RngCore + ?Sized>(rng: &mut R, modulus: &NonZero<Self>) -> Self {
let Ok(out) = Self::try_random_mod(rng, modulus);
out
}
fn try_random_mod<R: TryRngCore + ?Sized>(
rng: &mut R,
modulus: &NonZero<Self>,
) -> Result<Self, R::Error>;
}
pub trait AddMod<Rhs = Self, Mod = NonZero<Self>> {
type Output;
fn add_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
}
pub trait SubMod<Rhs = Self, Mod = NonZero<Self>> {
type Output;
fn sub_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
}
pub trait NegMod<Mod = NonZero<Self>> {
type Output;
#[must_use]
fn neg_mod(&self, p: &Mod) -> Self::Output;
}
pub trait MulMod<Rhs = Self, Mod = NonZero<Self>> {
type Output;
fn mul_mod(&self, rhs: &Rhs, p: &Mod) -> Self::Output;
}
pub trait SquareMod<Mod = NonZero<Self>> {
type Output;
fn square_mod(&self, p: &Mod) -> Self::Output;
}
#[deprecated(since = "0.7.0", note = "please use `InvertMod` instead")]
pub trait InvMod<Rhs = Self>: Sized {
type Output;
fn inv_mod(&self, p: &Rhs) -> CtOption<Self::Output>;
}
#[allow(deprecated)]
impl<T, Rhs> InvMod<Rhs> for T
where
T: InvertMod<Rhs>,
{
type Output = <T as InvertMod<Rhs>>::Output;
fn inv_mod(&self, p: &Rhs) -> CtOption<Self::Output> {
self.invert_mod(p)
}
}
pub trait InvertMod<Mod = NonZero<Self>>: Sized {
type Output;
fn invert_mod(&self, p: &Mod) -> CtOption<Self::Output>;
}
pub trait CheckedAdd<Rhs = Self>: Sized {
fn checked_add(&self, rhs: &Rhs) -> CtOption<Self>;
}
pub trait CheckedDiv<Rhs = Self>: Sized {
fn checked_div(&self, rhs: &Rhs) -> CtOption<Self>;
}
pub trait CheckedMul<Rhs = Self>: Sized {
fn checked_mul(&self, rhs: &Rhs) -> CtOption<Self>;
}
pub trait CheckedSub<Rhs = Self>: Sized {
fn checked_sub(&self, rhs: &Rhs) -> CtOption<Self>;
}
pub trait Concat: ConcatMixed<Self, MixedOutput = Self::Output> {
type Output: Integer;
fn concat(&self, hi: &Self) -> Self::Output {
self.concat_mixed(hi)
}
}
pub trait ConcatMixed<Hi: ?Sized = Self> {
type MixedOutput: Integer;
fn concat_mixed(&self, hi: &Hi) -> Self::MixedOutput;
}
pub trait Split: SplitMixed<Self::Output, Self::Output> {
type Output;
fn split(&self) -> (Self::Output, Self::Output) {
self.split_mixed()
}
}
pub trait SplitMixed<Lo, Hi> {
fn split_mixed(&self) -> (Lo, Hi);
}
pub trait Encoding: Sized {
type Repr: AsRef<[u8]>
+ AsMut<[u8]>
+ Copy
+ Clone
+ Sized
+ for<'a> TryFrom<&'a [u8], Error = core::array::TryFromSliceError>;
fn from_be_bytes(bytes: Self::Repr) -> Self;
fn from_le_bytes(bytes: Self::Repr) -> Self;
fn to_be_bytes(&self) -> Self::Repr;
fn to_le_bytes(&self) -> Self::Repr;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DecodeError {
Empty,
InvalidDigit,
InputSize,
Precision,
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Empty => write!(f, "empty value provided"),
Self::InvalidDigit => {
write!(f, "invalid digit character")
}
Self::InputSize => write!(f, "input size is too small to fit in the given precision"),
Self::Precision => write!(
f,
"the deserialized number is larger than the given precision"
),
}
}
}
impl core::error::Error for DecodeError {}
pub trait Square {
fn square(&self) -> Self;
}
pub trait SquareAssign {
fn square_assign(&mut self);
}
pub trait SquareRoot {
fn sqrt(&self) -> Self;
fn sqrt_vartime(&self) -> Self;
}
pub trait DivRemLimb: Sized {
fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
self.div_rem_limb_with_reciprocal(&Reciprocal::new(rhs))
}
fn div_rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> (Self, Limb);
}
pub trait RemMixed<Reductor>: Sized {
fn rem_mixed(&self, reductor: &NonZero<Reductor>) -> Reductor;
}
pub trait Reduce<T>: Sized {
fn reduce(value: &T) -> Self;
}
pub trait DivVartime: Sized {
fn div_vartime(&self, rhs: &NonZero<Self>) -> Self;
}
pub trait RemLimb: Sized {
fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
self.rem_limb_with_reciprocal(&Reciprocal::new(rhs))
}
fn rem_limb_with_reciprocal(&self, reciprocal: &Reciprocal) -> Limb;
}
pub trait BitOps {
fn bits_precision(&self) -> u32;
fn log2_bits(&self) -> u32 {
u32::BITS - self.bits_precision().leading_zeros() - 1
}
fn bytes_precision(&self) -> usize;
fn bit(&self, index: u32) -> Choice;
fn set_bit(&mut self, index: u32, bit_value: Choice);
fn bits(&self) -> u32 {
self.bits_precision() - self.leading_zeros()
}
fn trailing_zeros(&self) -> u32;
fn trailing_ones(&self) -> u32;
fn leading_zeros(&self) -> u32;
fn bit_vartime(&self, index: u32) -> bool;
fn bits_vartime(&self) -> u32;
fn set_bit_vartime(&mut self, index: u32, bit_value: bool);
fn leading_zeros_vartime(&self) -> u32 {
self.bits_precision() - self.bits_vartime()
}
fn trailing_zeros_vartime(&self) -> u32;
fn trailing_ones_vartime(&self) -> u32;
}
pub trait Pow<Exponent> {
fn pow(&self, exponent: &Exponent) -> Self;
}
impl<T: PowBoundedExp<Exponent>, Exponent: Bounded> Pow<Exponent> for T {
fn pow(&self, exponent: &Exponent) -> Self {
self.pow_bounded_exp(exponent, Exponent::BITS)
}
}
pub trait PowBoundedExp<Exponent> {
fn pow_bounded_exp(&self, exponent: &Exponent, exponent_bits: u32) -> Self;
}
pub trait MultiExponentiate<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
where
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
{
fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self;
}
impl<T, Exponent, BasesAndExponents> MultiExponentiate<Exponent, BasesAndExponents> for T
where
T: MultiExponentiateBoundedExp<Exponent, BasesAndExponents>,
Exponent: Bounded,
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
{
fn multi_exponentiate(bases_and_exponents: &BasesAndExponents) -> Self {
Self::multi_exponentiate_bounded_exp(bases_and_exponents, Exponent::BITS)
}
}
pub trait MultiExponentiateBoundedExp<Exponent, BasesAndExponents>: Pow<Exponent> + Sized
where
BasesAndExponents: AsRef<[(Self, Exponent)]> + ?Sized,
{
fn multi_exponentiate_bounded_exp(
bases_and_exponents: &BasesAndExponents,
exponent_bits: u32,
) -> Self;
}
pub trait Invert {
type Output;
fn invert(&self) -> Self::Output;
fn invert_vartime(&self) -> Self::Output {
self.invert()
}
}
#[deprecated(since = "0.7.0", note = "please use `ConcatenatingMul` instead")]
pub trait WideningMul<Rhs = Self>: Sized {
type Output: Integer;
fn widening_mul(&self, rhs: Rhs) -> Self::Output;
}
#[allow(deprecated)]
impl<T, Rhs> WideningMul<Rhs> for T
where
T: ConcatenatingMul<Rhs>,
{
type Output = <T as ConcatenatingMul<Rhs>>::Output;
fn widening_mul(&self, rhs: Rhs) -> Self::Output {
self.concatenating_mul(rhs)
}
}
pub trait ConcatenatingMul<Rhs = Self>: Sized {
type Output: Integer;
fn concatenating_mul(&self, rhs: Rhs) -> Self::Output;
}
pub trait ShlVartime: Sized {
fn overflowing_shl_vartime(&self, shift: u32) -> CtOption<Self>;
fn wrapping_shl_vartime(&self, shift: u32) -> Self;
}
pub trait ShrVartime: Sized {
fn overflowing_shr_vartime(&self, shift: u32) -> CtOption<Self>;
fn wrapping_shr_vartime(&self, shift: u32) -> Self;
}
pub trait Resize: Sized {
type Output;
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output;
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output>;
fn resize(self, at_least_bits_precision: u32) -> Self::Output {
self.try_resize(at_least_bits_precision).unwrap_or_else(|| {
panic!("The bit size of `self` is larger than `at_least_bits_precision`")
})
}
}
pub trait Monty:
'static
+ Clone
+ Debug
+ Eq
+ Sized
+ Send
+ Sync
+ Add<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ AddAssign
+ for<'a> AddAssign<&'a Self>
+ Sub<Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ SubAssign
+ for<'a> SubAssign<&'a Self>
+ Mul<Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ MulAssign
+ for<'a> MulAssign<&'a Self>
+ Neg<Output = Self>
+ PowBoundedExp<Self::Integer>
+ Retrieve<Output = Self::Integer>
+ Square
+ SquareAssign
{
type Integer: Unsigned<Monty = Self>;
type Multiplier<'a>: Debug + Clone + MontyMultiplier<'a, Monty = Self>;
type Params: 'static + Clone + Debug + Eq + Sized + Send + Sync;
fn new_params_vartime(modulus: Odd<Self::Integer>) -> Self::Params;
fn new(value: Self::Integer, params: Self::Params) -> Self;
fn zero(params: Self::Params) -> Self;
fn one(params: Self::Params) -> Self;
fn params(&self) -> &Self::Params;
fn as_montgomery(&self) -> &Self::Integer;
fn copy_montgomery_from(&mut self, other: &Self);
fn double(&self) -> Self;
fn div_by_2(&self) -> Self;
fn div_by_2_assign(&mut self) {
*self = self.div_by_2()
}
fn lincomb_vartime(products: &[(&Self, &Self)]) -> Self;
}
pub trait MontyMultiplier<'a>: From<&'a <Self::Monty as Monty>::Params> {
type Monty: Monty;
fn mul_assign(&mut self, lhs: &mut Self::Monty, rhs: &Self::Monty);
fn square_assign(&mut self, lhs: &mut Self::Monty);
}