use core::ops::{Add, Div, Mul, Neg, Sub};
use crate::bool_mask::HasBoolMask;
#[cfg(all(not(feature = "std"), feature = "libm"))]
mod libm;
#[cfg(feature = "wide")]
mod wide;
pub trait Real {
#[must_use]
fn from_f64(n: f64) -> Self;
}
pub trait FromScalar {
type Scalar;
#[must_use]
fn from_scalar(scalar: Self::Scalar) -> Self;
}
pub trait FromScalarArray<const N: usize>: FromScalar {
#[must_use]
fn from_array(scalars: [Self::Scalar; N]) -> Self;
}
pub trait IntoScalarArray<const N: usize>: FromScalar {
#[must_use]
fn into_array(self) -> [Self::Scalar; N];
}
pub trait Zero {
#[must_use]
fn zero() -> Self;
}
pub trait One {
#[must_use]
fn one() -> Self;
}
pub trait Arithmetics
where
Self: Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Neg<Output = Self>
+ Sized,
for<'a> Self: Add<&'a Self, Output = Self>
+ Sub<&'a Self, Output = Self>
+ Mul<&'a Self, Output = Self>
+ Div<&'a Self, Output = Self>,
{
}
impl<T> Arithmetics for T
where
T: Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Neg<Output = Self>
+ Sized,
for<'a> Self: Add<&'a Self, Output = Self>
+ Sub<&'a Self, Output = Self>
+ Mul<&'a Self, Output = Self>
+ Div<&'a Self, Output = Self>,
{
}
pub trait MinMax: Sized {
#[must_use]
fn min(self, other: Self) -> Self;
#[must_use]
fn max(self, other: Self) -> Self;
#[must_use]
fn min_max(self, other: Self) -> (Self, Self);
}
pub trait Trigonometry: Sized {
#[must_use]
fn sin(self) -> Self;
#[must_use]
fn cos(self) -> Self;
#[must_use]
fn sin_cos(self) -> (Self, Self);
#[must_use]
fn tan(self) -> Self;
#[must_use]
fn asin(self) -> Self;
#[must_use]
fn acos(self) -> Self;
#[must_use]
fn atan(self) -> Self;
#[must_use]
fn atan2(self, other: Self) -> Self;
}
pub trait Abs {
#[must_use]
fn abs(self) -> Self;
}
pub trait Sqrt {
#[must_use]
fn sqrt(self) -> Self;
}
pub trait Cbrt {
#[must_use]
fn cbrt(self) -> Self;
}
pub trait Powf {
#[must_use]
fn powf(self, exp: Self) -> Self;
}
pub trait Powi {
#[must_use]
fn powi(self, exp: i32) -> Self;
}
pub trait Powu {
#[must_use]
fn powu(self, exp: u32) -> Self;
}
pub trait Recip {
#[must_use]
fn recip(self) -> Self;
}
pub trait Exp {
#[must_use]
fn exp(self) -> Self;
}
pub trait IsValidDivisor: HasBoolMask {
#[must_use]
fn is_valid_divisor(&self) -> Self::Mask;
}
pub trait Hypot {
#[must_use]
fn hypot(self, other: Self) -> Self;
}
pub trait Round {
#[must_use]
fn round(self) -> Self;
#[must_use]
fn floor(self) -> Self;
#[must_use]
fn ceil(self) -> Self;
}
pub trait Clamp {
#[must_use]
fn clamp(self, min: Self, max: Self) -> Self;
#[must_use]
fn clamp_min(self, min: Self) -> Self;
#[must_use]
fn clamp_max(self, max: Self) -> Self;
}
pub trait ClampAssign {
fn clamp_assign(&mut self, min: Self, max: Self);
fn clamp_min_assign(&mut self, min: Self);
fn clamp_max_assign(&mut self, max: Self);
}
pub trait MulAdd {
#[must_use]
fn mul_add(self, m: Self, a: Self) -> Self;
}
pub trait MulSub {
#[must_use]
fn mul_sub(self, m: Self, s: Self) -> Self;
}
pub trait SaturatingAdd<Rhs = Self> {
type Output;
#[must_use]
fn saturating_add(self, other: Rhs) -> Self::Output;
}
pub trait SaturatingSub<Rhs = Self> {
type Output;
#[must_use]
fn saturating_sub(self, other: Rhs) -> Self::Output;
}
pub trait Signum {
fn signum(self) -> Self;
}
pub trait Ln {
fn ln(self) -> Self;
}
macro_rules! impl_uint {
($($ty: ident),+) => {
$(
impl FromScalar for $ty {
type Scalar = Self;
#[inline]
fn from_scalar(scalar: Self) -> Self {
scalar
}
}
impl FromScalarArray<1> for $ty {
#[inline]
fn from_array(scalars: [Self; 1]) -> Self {
let [scalar] = scalars;
scalar
}
}
impl IntoScalarArray<1> for $ty {
#[inline]
fn into_array(self) -> [Self; 1] {
[self]
}
}
impl Zero for $ty {
#[inline]
fn zero() -> Self {
0
}
}
impl One for $ty {
#[inline]
fn one() -> Self {
1
}
}
impl MinMax for $ty {
#[inline]
fn min(self, other: Self) -> Self {
core::cmp::Ord::min(self, other)
}
#[inline]
fn max(self, other: Self) -> Self {
core::cmp::Ord::max(self, other)
}
#[inline]
fn min_max(self, other: Self) -> (Self, Self) {
if self > other {
(other, self)
} else {
(self, other)
}
}
}
impl Powu for $ty {
#[inline]
fn powu(self, exp: u32) -> Self {
pow(self, exp)
}
}
impl IsValidDivisor for $ty {
#[inline]
fn is_valid_divisor(&self) -> bool {
*self != 0
}
}
impl Clamp for $ty {
#[inline]
fn clamp(self, min: Self, max: Self) -> Self {
core::cmp::Ord::clamp(self, min, max)
}
#[inline]
fn clamp_min(self, min: Self) -> Self {
core::cmp::Ord::max(self, min)
}
#[inline]
fn clamp_max(self, max: Self) -> Self {
core::cmp::Ord::min(self, max)
}
}
impl ClampAssign for $ty {
#[inline]
fn clamp_assign(&mut self, min: Self, max: Self) {
*self = core::cmp::Ord::clamp(*self, min, max);
}
#[inline]
fn clamp_min_assign(&mut self, min: Self) {
*self = core::cmp::Ord::max(*self, min);
}
#[inline]
fn clamp_max_assign(&mut self, max: Self) {
*self = core::cmp::Ord::min(*self, max);
}
}
impl MulAdd for $ty {
#[inline]
fn mul_add(self, m: Self, a: Self) -> Self {
(self * m) + a
}
}
impl MulSub for $ty {
#[inline]
fn mul_sub(self, m: Self, s: Self) -> Self {
(self * m) - s
}
}
impl SaturatingAdd for $ty {
type Output = $ty;
#[inline]
fn saturating_add(self, other: Self) -> Self{
<$ty>::saturating_add(self, other)
}
}
impl SaturatingSub for $ty {
type Output = $ty;
#[inline]
fn saturating_sub(self, other: Self) -> Self{
<$ty>::saturating_sub(self, other)
}
}
)+
};
}
macro_rules! impl_float {
($($ty: ident),+) => {
$(
impl Real for $ty {
#[inline]
fn from_f64(n: f64) -> $ty {
n as $ty
}
}
impl FromScalar for $ty {
type Scalar = Self;
#[inline]
fn from_scalar(scalar: Self) -> Self {
scalar
}
}
impl FromScalarArray<1> for $ty {
#[inline]
fn from_array(scalars: [Self; 1]) -> Self {
let [scalar] = scalars;
scalar
}
}
impl IntoScalarArray<1> for $ty {
#[inline]
fn into_array(self) -> [Self; 1] {
[self]
}
}
impl Zero for $ty {
#[inline]
fn zero() -> Self {
0.0
}
}
impl One for $ty {
#[inline]
fn one() -> Self {
1.0
}
}
impl MinMax for $ty {
#[inline]
fn max(self, other: Self) -> Self {
$ty::max(self, other)
}
#[inline]
fn min(self, other: Self) -> Self {
$ty::min(self, other)
}
#[inline]
fn min_max(self, other: Self) -> (Self, Self) {
if self > other {
(other, self)
} else {
(self, other)
}
}
}
impl Powu for $ty {
#[inline]
fn powu(self, exp: u32) -> Self {
pow(self, exp)
}
}
impl IsValidDivisor for $ty {
#[inline]
fn is_valid_divisor(&self) -> bool {
$ty::is_normal(*self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Trigonometry for $ty {
#[inline]
fn sin(self) -> Self {
$ty::sin(self)
}
#[inline]
fn cos(self) -> Self {
$ty::cos(self)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
$ty::sin_cos(self)
}
#[inline]
fn tan(self) -> Self {
$ty::tan(self)
}
#[inline]
fn asin(self) -> Self {
$ty::asin(self)
}
#[inline]
fn acos(self) -> Self {
$ty::acos(self)
}
#[inline]
fn atan(self) -> Self {
$ty::atan(self)
}
#[inline]
fn atan2(self, other: Self) -> Self {
$ty::atan2(self, other)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Abs for $ty {
#[inline]
fn abs(self) -> Self {
$ty::abs(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Sqrt for $ty {
#[inline]
fn sqrt(self) -> Self {
$ty::sqrt(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Cbrt for $ty {
#[inline]
fn cbrt(self) -> Self {
$ty::cbrt(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Powf for $ty {
#[inline]
fn powf(self, exp: Self) -> Self {
$ty::powf(self, exp)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Powi for $ty {
#[inline]
fn powi(self, exp: i32) -> Self {
$ty::powi(self, exp)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Recip for $ty {
#[inline]
fn recip(self) -> Self {
$ty::recip(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Exp for $ty {
#[inline]
fn exp(self) -> Self {
$ty::exp(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Hypot for $ty {
#[inline]
fn hypot(self, other: Self) -> Self {
$ty::hypot(self, other)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Round for $ty {
#[inline]
fn round(self) -> Self {
$ty::round(self)
}
#[inline]
fn floor(self) -> Self {
$ty::floor(self)
}
#[inline]
fn ceil(self) -> Self {
$ty::ceil(self)
}
}
impl Clamp for $ty {
#[inline]
fn clamp(self, min: Self, max: Self) -> Self {
$ty::clamp(self, min, max)
}
#[inline]
fn clamp_min(self, min: Self) -> Self {
$ty::max(self, min)
}
#[inline]
fn clamp_max(self, max: Self) -> Self {
$ty::min(self, max)
}
}
impl ClampAssign for $ty {
#[inline]
fn clamp_assign(&mut self, min: Self, max: Self) {
*self = $ty::clamp(*self, min, max);
}
#[inline]
fn clamp_min_assign(&mut self, min: Self) {
*self = $ty::max(*self, min);
}
#[inline]
fn clamp_max_assign(&mut self, max: Self) {
*self = $ty::min(*self, max);
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl MulAdd for $ty {
#[inline]
fn mul_add(self, m: Self, a: Self) -> Self {
$ty::mul_add(self, m, a)
}
}
impl MulSub for $ty {
#[inline]
fn mul_sub(self, m: Self, s: Self) -> Self {
(self * m) - s
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Signum for $ty {
#[inline]
fn signum(self) -> Self {
$ty::signum(self)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Ln for $ty {
#[inline]
fn ln(self) -> Self {
$ty::ln(self)
}
}
)+
};
}
impl_uint!(u8, u16, u32, u64, u128);
impl_float!(f32, f64);
#[inline]
fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: u32) -> T {
if exp == 0 {
return T::one();
}
while exp & 1 == 0 {
base = base.clone() * base;
exp >>= 1;
}
if exp == 1 {
return base;
}
let mut acc = base.clone();
while exp > 1 {
exp >>= 1;
base = base.clone() * base;
if exp & 1 == 1 {
acc = acc * base.clone();
}
}
acc
}
pub trait PartialCmp: HasBoolMask {
#[must_use]
fn lt(&self, other: &Self) -> Self::Mask;
#[must_use]
fn lt_eq(&self, other: &Self) -> Self::Mask;
#[must_use]
fn eq(&self, other: &Self) -> Self::Mask;
#[must_use]
fn neq(&self, other: &Self) -> Self::Mask;
#[must_use]
fn gt_eq(&self, other: &Self) -> Self::Mask;
#[must_use]
fn gt(&self, other: &Self) -> Self::Mask;
}
macro_rules! impl_partial_cmp {
($($ty:ident),+) => {
$(
impl PartialCmp for $ty {
#[inline]
fn lt(&self, other: &Self) -> Self::Mask {
self < other
}
#[inline]
fn lt_eq(&self, other: &Self) -> Self::Mask {
self <= other
}
#[inline]
fn eq(&self, other: &Self) -> Self::Mask {
self == other
}
#[inline]
fn neq(&self, other: &Self) -> Self::Mask {
self != other
}
#[inline]
fn gt_eq(&self, other: &Self) -> Self::Mask {
self >= other
}
#[inline]
fn gt(&self, other: &Self) -> Self::Mask {
self > other
}
}
)+
};
}
impl_partial_cmp!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);