///|
fn double_is_nan(x : Double) -> Bool {
x != x
}
///|
fn double_pow_nat(base : Double, exponent : UInt) -> Double {
let mut exp = exponent
let mut acc : Double = 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 Double with fn sqrt(x) -> Double {
@km.sqrt(x)
}
///|
pub impl Cbrt for Double with fn cbrt(x) -> Double {
@km.cbrt(x)
}
///|
pub impl Exponential for Double with fn exp(x) -> Double {
@km.exp(x)
}
///|
pub impl Exponential for Double with fn exp2(x) -> Double {
@km.exp2(x)
}
///|
pub impl Logarithmic for Double with fn ln(x) -> Double {
@km.log(x)
}
///|
pub impl Logarithmic for Double with fn log2(x) -> Double {
@km.log2(x)
}
///|
pub impl Logarithmic for Double with fn log10(x) -> Double {
@km.log10(x)
}
///|
pub impl Power for Double with fn pow(base, exponent) -> Double {
@km.pow(base, exponent)
}
///|
pub impl Trigonometric for Double with fn sin(x) -> Double {
@km.sin(x)
}
///|
pub impl Trigonometric for Double with fn cos(x) -> Double {
@km.cos(x)
}
///|
pub impl Trigonometric for Double with fn tan(x) -> Double {
@km.tan(x)
}
///|
pub impl InverseTrigonometric for Double with fn asin(x) -> Double {
@km.asin(x)
}
///|
pub impl InverseTrigonometric for Double with fn acos(x) -> Double {
@km.acos(x)
}
///|
pub impl InverseTrigonometric for Double with fn atan(x) -> Double {
@km.atan(x)
}
///|
pub impl InverseTrigonometric for Double with fn atan2(y, x) -> Double {
@km.atan2(y, x)
}
///|
pub impl Hyperbolic for Double with fn sinh(x) -> Double {
@km.sinh(x)
}
///|
pub impl Hyperbolic for Double with fn cosh(x) -> Double {
@km.cosh(x)
}
///|
pub impl Hyperbolic for Double with fn tanh(x) -> Double {
@km.tanh(x)
}
///|
pub impl InverseHyperbolic for Double with fn asinh(x) -> Double {
@km.asinh(x)
}
///|
pub impl InverseHyperbolic for Double with fn acosh(x) -> Double {
@km.acosh(x)
}
///|
pub impl InverseHyperbolic for Double with fn atanh(x) -> Double {
@km.atanh(x)
}
///|
pub impl Constants for Double with fn pi() -> Double {
@math.PI
}
///|
pub impl Constants for Double with fn tau() -> Double {
@math.PI * 2.0
}
///|
pub impl Constants for Double with fn e() -> Double {
@km.exp(1.0)
}
///|
pub impl Radical for Double
///|
pub impl SqrtChecked for Double with fn sqrt_checked(x, _ctx) -> Result[
Double,
ArithmeticError,
] {
Ok(Sqrt::sqrt(x))
}
///|
pub impl DivChecked for Double with fn div_checked(lhs, rhs, _ctx) -> Result[
Double,
ArithmeticError,
] {
guard rhs != 0.0 else {
return Err(ArithmeticError::division_by_zero("division by zero"))
}
Ok(lhs / rhs)
}
///|
pub impl CompareChecked for Double with fn compare_checked(lhs, rhs) -> Result[
Int,
ArithmeticError,
] {
guard !double_is_nan(lhs) && !double_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 Double with fn pow_nat_checked(base, exponent, _ctx) -> Result[
Double,
ArithmeticError,
] {
Ok(double_pow_nat(base, exponent))
}
///|
pub impl PowIntChecked for Double with fn pow_int_checked(base, exponent, ctx) -> Result[
Double,
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 = double_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)
}