Functional Weave
Code in Rust

math.exp@1.0.1

impl/rust.rs

1,744 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

// Derived from fdlibm e_exp.c.
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
// Developed at SunSoft, a Sun Microsystems, Inc. business.
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one

// fdlibm's split of ln 2: k * LN2_HI is exact for every k this range needs.
const LN2: f64 = 0.6931471805599453;
const LN2_HI: f64 = 6.93147180369123816490e-01;
const LN2_LO: f64 = 1.90821492927058770002e-10;

/// e^x using only +, -, * and /, in the same order as the TypeScript and
/// Python versions, so all three return the same double.
///
/// # Panics
/// Panics unless `x` is between -708 and 709.
pub fn exp(x: f64) -> f64 {
    if !x.is_finite() || x < -708.0 || x > 709.0 {
        panic!("exp needs x between -708 and 709, received {}", x);
    }
    let kf = (x / LN2 + 0.5).floor();
    let r = x - kf * LN2_HI - kf * LN2_LO;
    let mut p = 1.0 / 20922789888000.0;
    p = 1.0 / 1307674368000.0 + r * p;
    p = 1.0 / 87178291200.0 + r * p;
    p = 1.0 / 6227020800.0 + r * p;
    p = 1.0 / 479001600.0 + r * p;
    p = 1.0 / 39916800.0 + r * p;
    p = 1.0 / 3628800.0 + r * p;
    p = 1.0 / 362880.0 + r * p;
    p = 1.0 / 40320.0 + r * p;
    p = 1.0 / 5040.0 + r * p;
    p = 1.0 / 720.0 + r * p;
    p = 1.0 / 120.0 + r * p;
    p = 1.0 / 24.0 + r * p;
    p = 1.0 / 6.0 + r * p;
    p = 1.0 / 2.0 + r * p;
    p = 1.0 + r * p;
    let mut result = 1.0 + r * p;
    let k = kf as i64;
    for _ in 0..k.max(0) {
        result *= 2.0;
    }
    for _ in 0..(-k).max(0) {
        result /= 2.0;
    }
    result
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::Float(exp(args[0].as_f64()))
}