Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::math_exp::exp; ← from math.exp ^1.0.0 · built alongside by fune
use super::math_ln::ln; ← from math.ln ^1.0.0 · built alongside by fune
// Below this exponent of e the result is smaller than any normal double.
const SMALLEST: f64 = -708.0;
const LARGEST: f64 = 709.0;
/// base^exponent with the same bits in TypeScript, Python and Rust.
///
/// A whole-number exponent is done by repeated squaring, so 10^3 is exactly
/// 1000; any other is exp(exponent * ln(base)) from math.exp and math.ln.
/// `f64::powf` calls the platform's maths library, whose last bit may differ.
///
/// # Panics
/// Panics on a non-finite argument, zero to a negative power, a negative base
/// with a fractional exponent, or a result too large for a double.
pub fn pow(base: f64, exponent: f64) -> f64 {
if !base.is_finite() {
panic!("pow needs a finite base, received {}", base);
}
if !exponent.is_finite() {
panic!("pow needs a finite exponent, received {}", exponent);
}
if base == 0.0 {
if exponent < 0.0 {
panic!("zero cannot be raised to a negative power");
}
return if exponent == 0.0 { 1.0 } else { 0.0 };
}
if exponent.floor() == exponent {
let mut n = exponent.abs();
let mut b = base;
let mut result = 1.0;
while n > 0.0 {
if n % 2.0 == 1.0 {
result *= b;
}
n = (n / 2.0).floor();
if n > 0.0 {
b *= b;
}
}
if exponent < 0.0 {
result = 1.0 / result;
}
if !result.is_finite() {
panic!("pow result is too large to represent");
}
return result + 0.0;
}
if base < 0.0 {
panic!("a negative base needs a whole-number exponent");
}
let power = exponent * ln(base);
if power > LARGEST {
panic!("pow result is too large to represent");
}
if power < SMALLEST {
return 0.0;
}
exp(power)
}
pub fn fune_vector(args: &[Value]) -> Value {
Value::Float(pow(args[0].as_f64(), args[1].as_f64()))
}