#![cfg(feature = "cross-scale-ops")]
use crate::support::rounding::{DEFAULT_ROUNDING_MODE, RoundingMode};
use crate::types::unified::D;
#[inline]
pub const fn max_const(a: u32, b: u32) -> u32 {
if a >= b { a } else { b }
}
#[inline]
pub fn mul<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Mul<Output = D<W, { max_const(S1, S2) }>>,
{
let a_t = <D<W, S1> as WidenScale<W, S1, { max_const(S1, S2) }>>::widen_scale(a);
let b_t = <D<W, S2> as WidenScale<W, S2, { max_const(S1, S2) }>>::widen_scale(b);
a_t * b_t
}
#[inline]
pub fn mul_with<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>, _mode: RoundingMode,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Mul<Output = D<W, { max_const(S1, S2) }>>,
{
mul(a, b)
}
#[inline]
pub fn add<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Add<Output = D<W, { max_const(S1, S2) }>>,
{
let a_t = <D<W, S1> as WidenScale<W, S1, { max_const(S1, S2) }>>::widen_scale(a);
let b_t = <D<W, S2> as WidenScale<W, S2, { max_const(S1, S2) }>>::widen_scale(b);
a_t + b_t
}
#[inline]
pub fn sub<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Sub<Output = D<W, { max_const(S1, S2) }>>,
{
let a_t = <D<W, S1> as WidenScale<W, S1, { max_const(S1, S2) }>>::widen_scale(a);
let b_t = <D<W, S2> as WidenScale<W, S2, { max_const(S1, S2) }>>::widen_scale(b);
a_t - b_t
}
#[inline]
pub fn div<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Div<Output = D<W, { max_const(S1, S2) }>>,
{
let a_t = <D<W, S1> as WidenScale<W, S1, { max_const(S1, S2) }>>::widen_scale(a);
let b_t = <D<W, S2> as WidenScale<W, S2, { max_const(S1, S2) }>>::widen_scale(b);
a_t / b_t
}
#[inline]
pub fn rem<W, const S1: u32, const S2: u32>(
a: D<W, S1>, b: D<W, S2>,
) -> D<W, { max_const(S1, S2) }>
where
W: Copy,
D<W, S1>: WidenScale<W, S1, { max_const(S1, S2) }>,
D<W, S2>: WidenScale<W, S2, { max_const(S1, S2) }>,
D<W, { max_const(S1, S2) }>: core::ops::Rem<Output = D<W, { max_const(S1, S2) }>>,
{
let a_t = <D<W, S1> as WidenScale<W, S1, { max_const(S1, S2) }>>::widen_scale(a);
let b_t = <D<W, S2> as WidenScale<W, S2, { max_const(S1, S2) }>>::widen_scale(b);
a_t % b_t
}
pub trait WidenScale<W, const S_FROM: u32, const S_TO: u32> {
fn widen_scale(self) -> D<W, S_TO>;
}
macro_rules! impl_widen_scale {
($Storage:ty) => {
impl<const S_FROM: u32, const S_TO: u32> WidenScale<$Storage, S_FROM, S_TO>
for D<$Storage, S_FROM>
{
#[inline]
fn widen_scale(self) -> D<$Storage, S_TO> {
<D<$Storage, S_FROM>>::rescale_with::<S_TO>(self, DEFAULT_ROUNDING_MODE)
}
}
};
}
impl_widen_scale!(i32);
impl_widen_scale!(i64);
impl_widen_scale!(i128);
#[cfg(any(feature = "d57", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int192);
#[cfg(any(feature = "d76", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int256);
#[cfg(any(feature = "d115", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int384);
#[cfg(any(feature = "d153", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int512);
#[cfg(any(feature = "d230", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int768);
#[cfg(any(feature = "d307", feature = "wide"))]
impl_widen_scale!(crate::wide_int::Int1024);
#[cfg(any(feature = "d462", feature = "x-wide"))]
impl_widen_scale!(crate::wide_int::Int1536);
#[cfg(any(feature = "d616", feature = "x-wide"))]
impl_widen_scale!(crate::wide_int::Int2048);
#[cfg(any(feature = "d924", feature = "xx-wide"))]
impl_widen_scale!(crate::wide_int::Int3072);
#[cfg(any(feature = "d1232", feature = "xx-wide"))]
impl_widen_scale!(crate::wide_int::Int4096);