///|
fn float_is_nan(x : Float) -> Bool {
x != x
}
///|
fn float_pow_nat(base : Float, exponent : UInt) -> Float {
let mut exp = exponent
let mut acc : Float = 1.0
let mut factor = base
while exp > 0U {
if (exp & 1U) == 1U {
acc = acc * factor
}
exp = exp >> 1
if exp > 0U {
factor = factor * factor
}
}
acc
}
///|
pub impl Sqrt for Float with fn sqrt(x) -> Float {
@km.sqrtf(x)
}
///|
pub impl Cbrt for Float with fn cbrt(x) -> Float {
@km.cbrtf(x)
}
///|
pub impl Exponential for Float with fn exp(x) -> Float {
@km.expf(x)
}
///|
pub impl Exponential for Float with fn exp2(x) -> Float {
@km.powf(2.0, x)
}
///|
pub impl Logarithmic for Float with fn ln(x) -> Float {
@km.logf(x)
}
///|
pub impl Logarithmic for Float with fn log2(x) -> Float {
@km.log2f(x)
}
///|
pub impl Logarithmic for Float with fn log10(x) -> Float {
@km.log10f(x)
}
///|
pub impl Power for Float with fn pow(base, exponent) -> Float {
@km.powf(base, exponent)
}
///|
pub impl Trigonometric for Float with fn sin(x) -> Float {
@km.sinf(x)
}
///|
pub impl Trigonometric for Float with fn cos(x) -> Float {
@km.cosf(x)
}
///|
pub impl Trigonometric for Float with fn tan(x) -> Float {
@km.tanf(x)
}
///|
pub impl InverseTrigonometric for Float with fn asin(x) -> Float {
@km.asinf(x)
}
///|
pub impl InverseTrigonometric for Float with fn acos(x) -> Float {
@km.acosf(x)
}
///|
pub impl InverseTrigonometric for Float with fn atan(x) -> Float {
@km.atanf(x)
}
///|
pub impl InverseTrigonometric for Float with fn atan2(y, x) -> Float {
@km.atan2f(y, x)
}
///|
pub impl Hyperbolic for Float with fn sinh(x) -> Float {
@km.sinhf(x)
}
///|
pub impl Hyperbolic for Float with fn cosh(x) -> Float {
@km.coshf(x)
}
///|
pub impl Hyperbolic for Float with fn tanh(x) -> Float {
@km.tanhf(x)
}
///|
pub impl InverseHyperbolic for Float with fn asinh(x) -> Float {
@km.asinhf(x)
}
///|
pub impl InverseHyperbolic for Float with fn acosh(x) -> Float {
@km.acoshf(x)
}
///|
pub impl InverseHyperbolic for Float with fn atanh(x) -> Float {
@km.atanhf(x)
}
///|
pub impl Constants for Float with fn pi() -> Float {
Float::from_double(@math.PI)
}
///|
pub impl Constants for Float with fn tau() -> Float {
Float::from_double(@math.PI * 2.0)
}
///|
pub impl Constants for Float with fn e() -> Float {
@km.expf(1.0)
}
///|
pub impl Radical for Float
///|
pub impl SqrtChecked for Float with fn sqrt_checked(x, _ctx) -> Result[
Float,
ArithmeticError,
] {
Ok(Sqrt::sqrt(x))
}
///|
pub impl DivChecked for Float with fn div_checked(lhs, rhs, _ctx) -> Result[
Float,
ArithmeticError,
] {
guard rhs != 0.0 else {
return Err(ArithmeticError::division_by_zero("division by zero"))
}
Ok(lhs / rhs)
}
///|
pub impl CompareChecked for Float with fn compare_checked(lhs, rhs) -> Result[
Int,
ArithmeticError,
] {
guard !float_is_nan(lhs) && !float_is_nan(rhs) else {
return Err(ArithmeticError::unordered_comparison("NaN is unordered"))
}
Ok(if lhs < rhs { -1 } else if lhs > rhs { 1 } else { 0 })
}
///|
pub impl PowNatChecked for Float with fn pow_nat_checked(base, exponent, _ctx) -> Result[
Float,
ArithmeticError,
] {
Ok(float_pow_nat(base, exponent))
}
///|
pub impl PowIntChecked for Float with fn pow_int_checked(base, exponent, ctx) -> Result[
Float,
ArithmeticError,
] {
if exponent == 0 {
return Ok(1.0)
}
if exponent < 0 {
guard base != 0.0 else {
return Err(
ArithmeticError::division_by_zero(
"negative exponent requires a non-zero base",
),
)
}
let positive = float_pow_nat(base, (-exponent).reinterpret_as_uint())
return DivChecked::div_checked(1.0, positive, ctx)
}
PowNatChecked::pow_nat_checked(base, exponent.reinterpret_as_uint(), ctx)
}