use crate::scalar::Scalar;
pub use strict_num::{FiniteF32, NonZeroPositiveF32, NormalizedF32};
#[cfg(all(not(feature = "std"), feature = "no-std-float"))]
use crate::NoStdFloat;
pub(crate) const FLOAT_PI: f32 = 3.14159265;
const MAX_I32_FITS_IN_F32: f32 = 2147483520.0;
const MIN_I32_FITS_IN_F32: f32 = -MAX_I32_FITS_IN_F32;
pub trait SaturateCast<T>: Sized {
fn saturate_from(n: T) -> Self;
}
impl SaturateCast<f32> for i32 {
fn saturate_from(mut x: f32) -> Self {
x = if x < MAX_I32_FITS_IN_F32 {
x
} else {
MAX_I32_FITS_IN_F32
};
x = if x > MIN_I32_FITS_IN_F32 {
x
} else {
MIN_I32_FITS_IN_F32
};
x as i32
}
}
impl SaturateCast<f64> for i32 {
fn saturate_from(mut x: f64) -> Self {
x = if x < i32::MAX as f64 {
x
} else {
i32::MAX as f64
};
x = if x > i32::MIN as f64 {
x
} else {
i32::MIN as f64
};
x as i32
}
}
#[allow(missing_docs)]
pub trait SaturateRound<T>: SaturateCast<T> {
fn saturate_floor(n: T) -> Self;
fn saturate_ceil(n: T) -> Self;
fn saturate_round(n: T) -> Self;
}
impl SaturateRound<f32> for i32 {
fn saturate_floor(x: f32) -> Self {
Self::saturate_from(x.floor())
}
fn saturate_ceil(x: f32) -> Self {
Self::saturate_from(x.ceil())
}
fn saturate_round(x: f32) -> Self {
Self::saturate_from(x.floor() + 0.5)
}
}
pub(crate) fn f32_as_2s_compliment(x: f32) -> i32 {
sign_bit_to_2s_compliment(bytemuck::cast(x))
}
fn sign_bit_to_2s_compliment(mut x: i32) -> i32 {
if x < 0 {
x &= 0x7FFFFFFF;
x = -x;
}
x
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Debug)]
#[repr(transparent)]
pub struct NormalizedF32Exclusive(FiniteF32);
impl NormalizedF32Exclusive {
pub const ANY: Self = Self::HALF;
pub const HALF: Self = NormalizedF32Exclusive(unsafe { FiniteF32::new_unchecked(0.5) });
pub fn new(n: f32) -> Option<Self> {
if n > 0.0 && n < 1.0 {
FiniteF32::new(n).map(NormalizedF32Exclusive)
} else {
None
}
}
pub fn new_bounded(n: f32) -> Self {
let n = n.bound(core::f32::EPSILON, 1.0 - core::f32::EPSILON);
debug_assert!(n.is_finite());
NormalizedF32Exclusive(unsafe { FiniteF32::new_unchecked(n) })
}
pub fn get(self) -> f32 {
self.0.get()
}
pub fn to_normalized(self) -> NormalizedF32 {
unsafe { NormalizedF32::new_unchecked(self.0.get()) }
}
}