#![allow(non_snake_case)]
pub mod constants;
pub mod conversions;
mod f16;
pub mod macros;
mod random;
mod sum_precise;
pub use constants::*;
pub use conversions::{ToJsInt32, ToJsUint32};
pub struct Math;
impl Math {
pub const E: f64 = constants::E;
pub const LN10: f64 = constants::LN10;
pub const LN_10: f64 = constants::LN_10;
pub const LN2: f64 = constants::LN2;
pub const LN_2: f64 = constants::LN_2;
pub const LOG10E: f64 = constants::LOG10E;
pub const LOG10_E: f64 = constants::LOG10_E;
pub const LOG2E: f64 = constants::LOG2E;
pub const LOG2_E: f64 = constants::LOG2_E;
pub const PI: f64 = constants::PI;
pub const SQRT1_2: f64 = constants::SQRT1_2;
pub const SQRT_1_2: f64 = constants::SQRT_1_2;
pub const SQRT2: f64 = constants::SQRT2;
pub const SQRT_2: f64 = constants::SQRT_2;
#[inline]
pub fn abs(x: f64) -> f64 {
x.abs()
}
#[inline]
pub fn acos(x: f64) -> f64 {
x.acos()
}
#[inline]
pub fn acosh(x: f64) -> f64 {
x.acosh()
}
#[inline]
pub fn asin(x: f64) -> f64 {
x.asin()
}
#[inline]
pub fn asinh(x: f64) -> f64 {
x.asinh()
}
#[inline]
pub fn atan(x: f64) -> f64 {
x.atan()
}
#[inline]
pub fn atanh(x: f64) -> f64 {
x.atanh()
}
#[inline]
pub fn atan2(y: f64, x: f64) -> f64 {
y.atan2(x)
}
#[inline]
pub fn cbrt(x: f64) -> f64 {
x.cbrt()
}
#[inline]
pub fn ceil(x: f64) -> f64 {
x.ceil()
}
#[inline]
pub fn clz32<T: ToJsUint32>(x: T) -> u32 {
x.to_js_uint32().leading_zeros()
}
#[inline]
pub fn cos(x: f64) -> f64 {
x.cos()
}
#[inline]
pub fn cosh(x: f64) -> f64 {
x.cosh()
}
#[inline]
pub fn exp(x: f64) -> f64 {
x.exp()
}
#[inline]
pub fn expm1(x: f64) -> f64 {
x.exp_m1()
}
#[inline]
pub fn floor(x: f64) -> f64 {
x.floor()
}
#[inline]
pub fn fround(x: f64) -> f64 {
(x as f32) as f64
}
#[inline]
pub fn f16round(x: f64) -> f64 {
f16::f16round(x)
}
#[inline]
pub fn hypot(values: &[f64]) -> f64 {
if values.is_empty() {
return 0.0;
}
for &v in values {
if v.is_infinite() {
return f64::INFINITY;
}
}
for &v in values {
if v.is_nan() {
return f64::NAN;
}
}
let mut max = 0.0f64;
for &v in values {
let abs_v = v.abs();
if abs_v > max {
max = abs_v;
}
}
if max == 0.0 {
return 0.0;
}
let mut sum = 0.0f64;
for &v in values {
let scaled = v / max;
sum += scaled * scaled;
}
max * sum.sqrt()
}
#[inline]
pub fn hypot2(x: f64, y: f64) -> f64 {
if x.is_infinite() || y.is_infinite() {
return f64::INFINITY;
}
if x.is_nan() || y.is_nan() {
return f64::NAN;
}
x.hypot(y)
}
#[inline]
pub fn imul<A: ToJsInt32, B: ToJsInt32>(a: A, b: B) -> i32 {
a.to_js_int32().wrapping_mul(b.to_js_int32())
}
#[inline]
pub fn log(x: f64) -> f64 {
x.ln()
}
#[inline]
pub fn log1p(x: f64) -> f64 {
x.ln_1p()
}
#[inline]
pub fn log_1p(x: f64) -> f64 {
x.ln_1p()
}
#[inline]
pub fn log10(x: f64) -> f64 {
x.log10()
}
#[inline]
pub fn log_10(x: f64) -> f64 {
x.log10()
}
#[inline]
pub fn log2(x: f64) -> f64 {
x.log2()
}
#[inline]
pub fn log_2(x: f64) -> f64 {
x.log2()
}
#[inline]
pub fn max(values: &[f64]) -> f64 {
if values.is_empty() {
return f64::NEG_INFINITY;
}
let mut res = f64::NEG_INFINITY;
for &v in values {
if v.is_nan() {
return f64::NAN;
}
if v > res {
res = v;
}
if v == 0.0 && res == 0.0 && v.is_sign_positive() {
res = 0.0;
}
}
res
}
#[inline]
pub fn max2(a: f64, b: f64) -> f64 {
if a.is_nan() || b.is_nan() {
f64::NAN
} else if a == 0.0 && b == 0.0 {
if a.is_sign_positive() || b.is_sign_positive() {
0.0
} else {
-0.0
}
} else if a > b {
a
} else {
b
}
}
#[inline]
pub fn min(values: &[f64]) -> f64 {
if values.is_empty() {
return f64::INFINITY;
}
let mut res = f64::INFINITY;
for &v in values {
if v.is_nan() {
return f64::NAN;
}
if v < res {
res = v;
}
if v == 0.0 && res == 0.0 && v.is_sign_negative() {
res = -0.0;
}
}
res
}
#[inline]
pub fn min2(a: f64, b: f64) -> f64 {
if a.is_nan() || b.is_nan() {
f64::NAN
} else if a == 0.0 && b == 0.0 {
if a.is_sign_negative() || b.is_sign_negative() {
-0.0
} else {
0.0
}
} else if a < b {
a
} else {
b
}
}
#[inline]
pub fn pow(base: f64, exponent: f64) -> f64 {
if exponent == 0.0 {
return 1.0;
}
if exponent.is_nan() {
return f64::NAN;
}
if base.is_nan() {
return f64::NAN;
}
if base.abs() == 1.0 && exponent.is_infinite() {
return f64::NAN;
}
if base == 0.0 && base.is_sign_negative() {
let is_odd = is_odd_integer(exponent);
if exponent > 0.0 {
return if is_odd { -0.0 } else { 0.0 };
} else {
return if is_odd {
f64::NEG_INFINITY
} else {
f64::INFINITY
};
}
}
if base == f64::NEG_INFINITY {
let is_odd = is_odd_integer(exponent);
if exponent > 0.0 {
return if is_odd {
f64::NEG_INFINITY
} else {
f64::INFINITY
};
} else {
return if is_odd { -0.0 } else { 0.0 };
}
}
if base < 0.0 && base.is_finite() && exponent.is_finite() && exponent.floor() != exponent {
return f64::NAN;
}
base.powf(exponent)
}
#[inline]
pub fn random() -> f64 {
random::random()
}
#[inline]
pub fn seed_random(seed: u64) {
random::seed_random(seed);
}
#[inline]
pub fn round(x: f64) -> f64 {
if x.is_nan() || !x.is_finite() || x == 0.0 {
return x;
}
if (-0.5..0.0).contains(&x) {
return -0.0;
}
if (0.0..0.5).contains(&x) {
return 0.0;
}
if x.abs() >= 4503599627370496.0 {
return x;
}
let fl = x.floor();
let frac = x - fl;
if frac >= 0.5 {
let cl = x.ceil();
if cl == 0.0 && x < 0.0 {
-0.0
} else {
cl
}
} else {
if fl == 0.0 && x < 0.0 {
-0.0
} else {
fl
}
}
}
#[inline]
pub fn sign(x: f64) -> f64 {
if x.is_nan() {
f64::NAN
} else if x == 0.0 {
x
} else if x > 0.0 {
1.0
} else {
-1.0
}
}
#[inline]
pub fn sin(x: f64) -> f64 {
x.sin()
}
#[inline]
pub fn sinh(x: f64) -> f64 {
x.sinh()
}
#[inline]
pub fn sqrt(x: f64) -> f64 {
x.sqrt()
}
#[inline]
pub fn sumPrecise<'a, I>(items: I) -> f64
where
I: IntoIterator<Item = &'a f64>,
{
sum_precise::sum_precise(items)
}
#[inline]
pub fn sum_precise<'a, I>(items: I) -> f64
where
I: IntoIterator<Item = &'a f64>,
{
sum_precise::sum_precise(items)
}
#[inline]
pub fn tan(x: f64) -> f64 {
x.tan()
}
#[inline]
pub fn tanh(x: f64) -> f64 {
x.tanh()
}
#[inline]
pub fn trunc(x: f64) -> f64 {
x.trunc()
}
}
#[inline]
fn is_odd_integer(x: f64) -> bool {
x.is_finite() && x.floor() == x && (x % 2.0).abs() == 1.0
}