diff --git a/library/src/compute/calc.rs b/library/src/compute/calc.rs index ba01c18ef..ccc6e7b1d 100644 --- a/library/src/compute/calc.rs +++ b/library/src/compute/calc.rs @@ -90,28 +90,24 @@ pub fn pow( /// The exponent of the power. Must be non-negative. exponent: Spanned, ) -> Value { - let exponent_value = match exponent.v { - Num::Int(i) if i > u32::MAX as i64 => { - bail!(exponent.span, "exponent too large"); + let Spanned { v: exp, span } = exponent; + match exp { + _ if exp.float() == 0.0 && base.float() == 0.0 => { + bail!(args.span, "zero to the power of zero is undefined") } - Num::Int(i) => exponent.v, - Num::Float(f) if f.is_normal() || f == 0 as f64 => exponent.v, - _ => { - bail!( - exponent.span, - "exponent must be normal (non-NaN, non-infinite, non-subnormal)" - ); + Num::Int(i) if i32::try_from(i).is_err() => { + bail!(span, "exponent is too large") } + Num::Float(f) if !f.is_normal() && f != 0.0 => { + bail!(span, "exponent may not be NaN, infinite, or subnormal") + } + _ => {} }; - if exponent_value.float() == 0 as f64 && base.float() == 0 as f64 { - return bail!(exponent.span, "zero to the power of zero is undefined"); - } - - match (base, exponent_value) { + match (base, exp) { (Num::Int(a), Num::Int(b)) if b >= 0 => Value::Int(a.pow(b as u32)), (a, Num::Int(b)) => Value::Float(a.float().powi(b as i32)), - (a, b) => Value::Float(f64::powf(a.float(), b.float())), + (a, b) => Value::Float(a.float().powf(b.float())), } } diff --git a/tests/typ/compute/calc.typ b/tests/typ/compute/calc.typ index ee0637070..51569f7ae 100644 --- a/tests/typ/compute/calc.typ +++ b/tests/typ/compute/calc.typ @@ -76,6 +76,23 @@ #test(calc.max(-3, 11), 11) #test(calc.min("hi"), "hi") +--- +// Test the `calc` function. +#test(calc.pow(10, 0), 1) +#test(calc.pow(2, 4), 16) + +--- +// Error: 10-16 zero to the power of zero is undefined +#calc.pow(0, 0) + +--- +// Error: 14-31 exponent is too large +#calc.pow(2, 10000000000000000) + +--- +// Error: 14-36 exponent may not be NaN, infinite, or subnormal +#calc.pow(2, calc.pow(2.0, 10000.0)) + --- // Error: 10-12 expected at least one value #calc.min()