pub(super) fn f64_trunc(x: f64) -> f64 {
if x.is_nan() || x.is_infinite() {
return x;
}
if x >= 9_007_199_254_740_992.0 || x <= -9_007_199_254_740_992.0 {
return x;
}
(x as i64) as f64
}
static PRNG_STATE: core::sync::atomic::AtomicU64 =
core::sync::atomic::AtomicU64::new(0x2545_F491_4F6C_DD1D);
pub(super) fn prng_next_u64() -> u64 {
use core::sync::atomic::Ordering;
let mut x = PRNG_STATE.load(Ordering::Relaxed);
loop {
if x == 0 {
x = 0x2545_F491_4F6C_DD1D;
}
let mut next = x;
next ^= next << 13;
next ^= next >> 7;
next ^= next << 17;
match PRNG_STATE.compare_exchange_weak(x, next, Ordering::Relaxed, Ordering::Relaxed) {
Ok(_) => return next,
Err(seen) => x = seen,
}
}
}
static UUIDV7_MONO: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0);
pub(super) fn uuidv7_monotonic(base_ms: u64) -> (u64, u16) {
use core::sync::atomic::Ordering;
let mut packed = UUIDV7_MONO.load(Ordering::Relaxed);
loop {
let last_ms = packed >> 12;
let last_ctr = (packed & 0xFFF) as u16;
let (ms, ctr) = if base_ms > last_ms {
(base_ms, 0)
} else if last_ctr < 0xFFF {
(last_ms, last_ctr + 1)
} else {
(last_ms + 1, 0)
};
let next = (ms << 12) | u64::from(ctr);
match UUIDV7_MONO.compare_exchange_weak(packed, next, Ordering::Relaxed, Ordering::Relaxed)
{
Ok(_) => return (ms, ctr),
Err(seen) => packed = seen,
}
}
}
pub(super) fn prng_seed(seed: f64) {
use core::sync::atomic::Ordering;
let bits = seed.to_bits();
let state = if bits == 0 {
0x2545_F491_4F6C_DD1D
} else {
bits
};
PRNG_STATE.store(state, Ordering::Relaxed);
}
pub(super) fn prng_next_f64() -> f64 {
let mantissa = prng_next_u64() >> 11;
let denom = (1u64 << 53) as f64;
mantissa as f64 / denom
}
pub(crate) fn f64_sqrt(x: f64) -> f64 {
libm::sqrt(x)
}
#[cfg(feature = "std")]
mod plat {
pub fn exp(x: f64) -> f64 {
x.exp()
}
pub fn ln(x: f64) -> f64 {
x.ln()
}
pub fn pow(x: f64, y: f64) -> f64 {
x.powf(y)
}
pub fn sinh(x: f64) -> f64 {
x.sinh()
}
pub fn cosh(x: f64) -> f64 {
x.cosh()
}
pub fn tanh(x: f64) -> f64 {
x.tanh()
}
pub fn asinh(x: f64) -> f64 {
x.asinh()
}
pub fn acosh(x: f64) -> f64 {
x.acosh()
}
pub fn atanh(x: f64) -> f64 {
x.atanh()
}
}
#[cfg(not(feature = "std"))]
mod plat {
pub fn exp(x: f64) -> f64 {
libm::exp(x)
}
pub fn ln(x: f64) -> f64 {
libm::log(x)
}
pub fn pow(x: f64, y: f64) -> f64 {
libm::pow(x, y)
}
pub fn sinh(x: f64) -> f64 {
libm::sinh(x)
}
pub fn cosh(x: f64) -> f64 {
libm::cosh(x)
}
pub fn tanh(x: f64) -> f64 {
libm::tanh(x)
}
pub fn asinh(x: f64) -> f64 {
libm::asinh(x)
}
pub fn acosh(x: f64) -> f64 {
libm::acosh(x)
}
pub fn atanh(x: f64) -> f64 {
libm::atanh(x)
}
}
pub(crate) fn f64_exp(x: f64) -> f64 {
plat::exp(x)
}
pub(crate) fn f64_ln(x: f64) -> f64 {
if x < 0.0 {
return f64::NAN;
}
plat::ln(x)
}
pub(crate) fn f64_pow(x: f64, y: f64) -> f64 {
plat::pow(x, y)
}
pub(crate) fn f64_sinh(x: f64) -> f64 {
plat::sinh(x)
}
pub(crate) fn f64_cosh(x: f64) -> f64 {
plat::cosh(x)
}
pub(crate) fn f64_tanh(x: f64) -> f64 {
plat::tanh(x)
}
pub(crate) fn f64_asinh(x: f64) -> f64 {
plat::asinh(x)
}
pub(crate) fn f64_acosh(x: f64) -> f64 {
plat::acosh(x)
}
pub(crate) fn f64_atanh(x: f64) -> f64 {
plat::atanh(x)
}
pub(super) fn f64_powi(base: f64, exp: i32) -> f64 {
if exp == 0 {
return 1.0;
}
let mut result = 1.0;
let mut b = if exp > 0 { base } else { 1.0 / base };
let mut e = exp.unsigned_abs();
while e > 0 {
if e & 1 == 1 {
result *= b;
}
e >>= 1;
if e > 0 {
b *= b;
}
}
result
}
pub(super) fn f64_round_half_away(x: f64) -> f64 {
if x.is_nan() || x.is_infinite() {
return x;
}
if x >= 0.0 {
f64_floor(x + 0.5)
} else {
f64_ceil(x - 0.5)
}
}
pub(crate) fn f64_round_half_even(x: f64) -> f64 {
if x.is_nan() || x.is_infinite() {
return x;
}
let fl = f64_floor(x);
let diff = x - fl;
if diff < 0.5 {
fl
} else if diff > 0.5 {
fl + 1.0
} else {
let half = fl / 2.0;
if half == f64_floor(half) {
fl
} else {
fl + 1.0
}
}
}
pub(crate) fn f64_ceil(x: f64) -> f64 {
if x.is_nan() || x.is_infinite() {
return x;
}
if x >= 9_007_199_254_740_992.0 || x <= -9_007_199_254_740_992.0 {
return x;
}
let trunc = (x as i64) as f64;
if x > 0.0 && x != trunc {
trunc + 1.0
} else {
trunc
}
}
pub(crate) fn f64_floor(x: f64) -> f64 {
if x.is_nan() || x.is_infinite() {
return x;
}
if x >= 9_007_199_254_740_992.0 || x <= -9_007_199_254_740_992.0 {
return x;
}
let trunc = (x as i64) as f64;
if x < 0.0 && x != trunc {
trunc - 1.0
} else {
trunc
}
}