use std::fmt::Display;
pub trait MulInverse {
type Output;
fn mul_inverse(self) -> Self::Output;
}
pub trait AsSlice<T> {
type Output;
fn as_slice(self, t: T) -> Self::Output;
}
pub trait KaratsubaMul<Rhs> {
type Output;
fn karatsuba_mul(self, rhs: Rhs, min_size: usize) -> Self::Output;
}
pub(crate) trait LnVarFree {
type Output;
fn ln_var_free(self) -> Self::Output;
}
pub(crate) trait ExpCoeff {
type Output;
fn exp_coeff(&self) -> Self::Output;
}
pub trait SplitSign<'a> {
type Signless;
fn split_sign(&'a self) -> (Sign, Self::Signless);
}
impl<'a, T: SplitSign<'a>> SplitSign<'a> for &'a T {
type Signless = <T as SplitSign<'a>>::Signless;
fn split_sign(&'a self) -> (Sign, Self::Signless) {
(*self).split_sign()
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Sign {
Plus,
Minus,
}
impl Display for Sign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Sign::Plus => '+',
Sign::Minus => '-',
}
.fmt(f)
}
}
macro_rules! impl_split_sign_signed_int {
($($t:ty), *) => {
$(
impl<'a> SplitSign<'a> for $t {
type Signless = $t;
fn split_sign(&'a self) -> (Sign, Self::Signless) {
if *self > 0 {
(Sign::Plus, *self)
} else {
(Sign::Minus, -self)
}
}
}
)*
};
}
impl_split_sign_signed_int!(i8, i16, i32, i64, i128, isize);
macro_rules! impl_split_sign_unsigned_int {
($($t:ty), *) => {
$(
impl<'a> SplitSign<'a> for $t {
type Signless = $t;
fn split_sign(&'a self) -> (Sign, Self::Signless) {
(Sign::Plus, *self)
}
}
)*
};
}
impl_split_sign_unsigned_int!(u8, u16, u32, u64, u128, usize);
macro_rules! impl_split_sign_float {
($($t:ty), *) => {
$(
impl<'a> SplitSign<'a> for $t {
type Signless = $t;
fn split_sign(&'a self) -> (Sign, Self::Signless) {
if *self < 0.0 {
(Sign::Minus, -self)
} else {
(Sign::Plus, *self)
}
}
}
)*
};
}
impl_split_sign_float!(f32, f64);
pub trait NeedsCoeffBracket {
fn needs_coeff_bracket(&self) -> bool;
}
impl<T: NeedsCoeffBracket> NeedsCoeffBracket for &T {
fn needs_coeff_bracket(&self) -> bool {
(*self).needs_coeff_bracket()
}
}
macro_rules! impl_never_needs_coeff_bracket {
($($t:ty), *) => {
$(
impl NeedsCoeffBracket for $t {
fn needs_coeff_bracket(&self) -> bool {
false
}
}
)*
};
}
impl_never_needs_coeff_bracket!(
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64
);