use super::funejson::Value; use super::math_round_div::round_div; // (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 { 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, } }