Functional Weave
Code in TypeScript

math.percent-change@1.0.0

impl/rust.rs

1,270 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.

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_round_div::round_div;  ← from math.round-div ^1.0.0 · built alongside by fune

// (difference * 10000) must stay an exact integer in a JavaScript number, and
// the three languages must agree on what is too large.
const MAX_DIFFERENCE: i128 = 900_719_925_474;

/// Percentage change from `from_value` to `to_value`, in basis points.
///
/// Divides by |from_value| so the sign always says which way the value moved,
/// even when the starting value is negative. `None` when `from_value` is zero.
///
/// # Panics
/// Panics if the difference is too large to express exactly, or the mode is unknown.
pub fn percent_change(from_value: i64, to_value: i64, mode: &str) -> Option<i64> {
    if from_value == 0 {
        return None;
    }
    let difference = to_value as i128 - from_value as i128;
    if difference.abs() > MAX_DIFFERENCE {
        panic!(
            "the change from {} to {} is too large to express exactly",
            from_value, to_value
        );
    }
    Some(round_div(
        (difference * 10000) as i64,
        from_value.abs(),
        mode,
    ))
}

pub fn fune_vector(args: &[Value]) -> Value {
    match percent_change(args[0].as_i64(), args[1].as_i64(), args[2].as_str()) {
        Some(bp) => Value::Int(bp),
        None => Value::Null,
    }
}