Add calc.root function (#2736)

Fixes #2522
This commit is contained in:
Emanuel 2023-12-06 14:32:56 +01:00 committed by GitHub
parent 9a62b21a25
commit 9e333e5058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 0 deletions

View File

@ -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

View File

@ -162,6 +162,22 @@
// Error: 12-14 cannot take square root of negative number
#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)