summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmanuel <emanuel@empa.xyz>2023-12-06 14:32:56 +0100
committerGitHub <noreply@github.com>2023-12-06 14:32:56 +0100
commit9e333e5058f54703fa9be0f34914061be6c8a272 (patch)
tree6f518fc246e4ffb91e0dfb35fd0e107a79bdf9dd
parent9a62b21a25cd9a56090e0bf1afecfa3888d810d8 (diff)
Add calc.root function (#2736)
Fixes #2522
-rw-r--r--crates/typst/src/foundations/calc.rs32
-rw-r--r--tests/typ/compute/calc.typ16
2 files changed, 48 insertions, 0 deletions
diff --git a/crates/typst/src/foundations/calc.rs b/crates/typst/src/foundations/calc.rs
index 597bf156..c65102ce 100644
--- a/crates/typst/src/foundations/calc.rs
+++ b/crates/typst/src/foundations/calc.rs
@@ -17,6 +17,7 @@ pub fn module() -> Module {
scope.define_func::<pow>();
scope.define_func::<exp>();
scope.define_func::<sqrt>();
+ scope.define_func::<root>();
scope.define_func::<sin>();
scope.define_func::<cos>();
scope.define_func::<tan>();
@@ -183,6 +184,37 @@ pub fn sqrt(
Ok(value.v.float().sqrt())
}
+/// Calculates the real nth root of a number.
+///
+/// If the number is negative, then n must be odd.
+///
+/// ```example
+/// #calc.root(16.0, 4) \
+/// #calc.root(27.0, 3)
+/// ```
+#[func]
+pub fn root(
+ /// The expression to take the root of
+ radicand: f64,
+ /// Which root of the radicand to take
+ index: Spanned<i64>,
+) -> SourceResult<f64> {
+ if index.v == 0 {
+ bail!(index.span, "cannot take the 0th root of a number");
+ } else if radicand < 0.0 {
+ if index.v % 2 == 0 {
+ bail!(
+ index.span,
+ "negative numbers do not have a real nth root when n is even"
+ );
+ } else {
+ Ok(-(-radicand).powf(1.0 / index.v as f64))
+ }
+ } else {
+ Ok(radicand.powf(1.0 / index.v as f64))
+ }
+}
+
/// Calculates the sine of an angle.
///
/// When called with an integer or a float, they will be interpreted as
diff --git a/tests/typ/compute/calc.typ b/tests/typ/compute/calc.typ
index 86dcafcd..e61e15d4 100644
--- a/tests/typ/compute/calc.typ
+++ b/tests/typ/compute/calc.typ
@@ -163,6 +163,22 @@
#calc.sqrt(-1)
---
+#test(calc.root(12.0, 1), 12.0)
+#test(calc.root(9.0, 2), 3.0)
+#test(calc.root(27.0, 3), 3.0)
+#test(calc.root(-27.0, 3), -3.0)
+// 100^(-1/2) = (100^(1/2))^-1 = 1/sqrt(100)
+#test(calc.root(100.0, -2), 0.1)
+
+---
+// Error: 17-18 cannot take the 0th root of a number
+#calc.root(1.0, 0)
+
+---
+// Error: 24-25 negative numbers do not have a real nth root when n is even
+#test(calc.root(-27.0, 4), -3.0)
+
+---
// Error: 11-13 value must be strictly positive
#calc.log(-1)