summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarmoGlace <23212967+HarmoGlace@users.noreply.github.com>2023-04-04 14:33:26 +0200
committerGitHub <noreply@github.com>2023-04-04 14:33:26 +0200
commit4aa5e0a4a3d005c25cbd12c843e464a791340c1a (patch)
treefd7daa485692eadd65a67e771cd2d71fcf6dc332
parent2d1598e51d10bfe4e331c1ad6ca7899c5cdbb468 (diff)
Make behavior of calculation functions consistent (#515)
-rw-r--r--library/src/compute/calc.rs45
-rw-r--r--tests/typ/compute/calc.typ20
2 files changed, 56 insertions, 9 deletions
diff --git a/library/src/compute/calc.rs b/library/src/compute/calc.rs
index ccc6e7b1..c48c6816 100644
--- a/library/src/compute/calc.rs
+++ b/library/src/compute/calc.rs
@@ -104,11 +104,23 @@ pub fn pow(
_ => {}
};
- match (base, exp) {
+ let return_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(a.float().powf(b.float())),
+ };
+
+ let is_nan = match return_value {
+ Value::Float(f) => f.is_nan(),
+ Value::Int(i) => (i as f64).is_nan(),
+ _ => false,
+ };
+
+ if is_nan {
+ bail!(span, "the return value is not a real number")
}
+
+ return_value
}
/// Calculate the square root of a number.
@@ -367,20 +379,35 @@ pub fn tanh(
/// Returns: float
#[func]
pub fn log(
- /// The number whose logarithm to calculate.
- value: f64,
- /// The base of the logarithm.
+ /// The number whose logarithm to calculate. It must be strictly positive.
+ value: Spanned<Num>,
+ /// The base of the logarithm. It can't be null.
#[named]
#[default(10.0)]
base: f64,
) -> Value {
- Value::Float(if base == 2.0 {
- value.log2()
+ let number = value.v.float();
+
+ if number <= 0 as f64 {
+ bail!(value.span, "a logarithm parameter must be strictly positive")
+ }
+ if !base.is_normal() {
+ bail!(value.span, "a logarithm base should be normal (not NaN, not infinite, non-null, not subnormal)")
+ }
+
+ let return_value = if base == 2.0 {
+ number.log2()
} else if base == 10.0 {
- value.log10()
+ number.log10()
} else {
- value.log(base)
- })
+ number.log(base)
+ };
+
+ if return_value.is_infinite() || return_value.is_nan() {
+ bail!(value.span, "this logarithm doesn't return a real value")
+ }
+
+ Value::Float(return_value)
}
/// Round a number down to the nearest integer.
diff --git a/tests/typ/compute/calc.typ b/tests/typ/compute/calc.typ
index 51569f7a..b7c6df02 100644
--- a/tests/typ/compute/calc.typ
+++ b/tests/typ/compute/calc.typ
@@ -94,6 +94,26 @@
#calc.pow(2, calc.pow(2.0, 10000.0))
---
+// Error: 15-18 the return value is not a real number
+#calc.pow(-1, 0.5)
+
+---
+// Error: 12-14 cannot take square root of negative number
+#calc.sqrt(-1)
+
+---
+// Error: 11-13 a logarithm parameter must be strictly positive
+#calc.log(-1)
+
+---
+// Error: 11-12 a logarithm base should be normal (not NaN, not infinite, non-null, not subnormal)
+#calc.log(1, base: 0)
+
+---
+// Error: 11-13 this logarithm doesn't return a real value
+#calc.log(10, base: -1)
+
+---
// Error: 10-12 expected at least one value
#calc.min()