--- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -77,6 +77,11 @@ ("member", builtin_member::INST), ("count", builtin_count::INST), // Math + ("abs", builtin_abs::INST), + ("sign", builtin_sign::INST), + ("max", builtin_max::INST), + ("min", builtin_min::INST), + ("clamp", builtin_clamp::INST), ("modulo", builtin_modulo::INST), ("floor", builtin_floor::INST), ("ceil", builtin_ceil::INST), --- a/crates/jrsonnet-stdlib/src/math.rs +++ b/crates/jrsonnet-stdlib/src/math.rs @@ -1,6 +1,42 @@ use jrsonnet_evaluator::{error::Result, function::builtin, typed::PositiveF64}; #[builtin] +pub fn builtin_abs(x: f64) -> Result { + Ok(x.abs()) +} + +#[builtin] +pub fn builtin_sign(x: f64) -> Result { + Ok(if x == 0. { 0. } else { x.signum() }) +} + +#[builtin] +pub fn builtin_max(x: f64, y: f64) -> Result { + Ok(x.max(y)) +} + +#[builtin] +pub fn builtin_min(x: f64, y: f64) -> Result { + Ok(x.min(y)) +} + +#[builtin] +pub fn builtin_clamp(x: f64, min_val: f64, max_val: f64) -> Result { + debug_assert!(x.is_finite(), "jsonnet number are always finite"); + debug_assert!(min_val.is_finite(), "jsonnet number are always finite"); + debug_assert!(max_val.is_finite(), "jsonnet number are always finite"); + + // `f64::clamp` should noe be used here since it requires extra checks to guarantee NaN-safety + Ok(if x < min_val { + min_val + } else if x > max_val { + max_val + } else { + x + }) +} + +#[builtin] pub fn builtin_modulo(a: f64, b: f64) -> Result { Ok(a % b) } --- a/crates/jrsonnet-stdlib/src/std.jsonnet +++ b/crates/jrsonnet-stdlib/src/std.jsonnet @@ -77,38 +77,6 @@ else error 'Assertion failed. ' + a + ' != ' + b, - abs(n):: - if !std.isNumber(n) then - error 'std.abs expected number, got ' + std.type(n) - else - if n > 0 then n else -n, - - sign(n):: - if !std.isNumber(n) then - error 'std.sign expected number, got ' + std.type(n) - else - if n > 0 then - 1 - else if n < 0 then - -1 - else 0, - - max(a, b):: - if !std.isNumber(a) then - error 'std.max first param expected number, got ' + std.type(a) - else if !std.isNumber(b) then - error 'std.max second param expected number, got ' + std.type(b) - else - if a > b then a else b, - - min(a, b):: - if !std.isNumber(a) then - error 'std.min first param expected number, got ' + std.type(a) - else if !std.isNumber(b) then - error 'std.min second param expected number, got ' + std.type(b) - else - if a < b then a else b, - clamp(x, minVal, maxVal):: if x < minVal then minVal else if x > maxVal then maxVal