mirror of
https://github.com/typst/typst
synced 2025-05-16 01:55:28 +08:00
add calc.exp, calc.ln (#1299)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
0dc1776202
commit
c87f802cf6
@ -13,6 +13,7 @@ pub fn module() -> Module {
|
|||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
scope.define("abs", abs_func());
|
scope.define("abs", abs_func());
|
||||||
scope.define("pow", pow_func());
|
scope.define("pow", pow_func());
|
||||||
|
scope.define("exp", exp_func());
|
||||||
scope.define("sqrt", sqrt_func());
|
scope.define("sqrt", sqrt_func());
|
||||||
scope.define("sin", sin_func());
|
scope.define("sin", sin_func());
|
||||||
scope.define("cos", cos_func());
|
scope.define("cos", cos_func());
|
||||||
@ -25,6 +26,7 @@ pub fn module() -> Module {
|
|||||||
scope.define("cosh", cosh_func());
|
scope.define("cosh", cosh_func());
|
||||||
scope.define("tanh", tanh_func());
|
scope.define("tanh", tanh_func());
|
||||||
scope.define("log", log_func());
|
scope.define("log", log_func());
|
||||||
|
scope.define("ln", ln_func());
|
||||||
scope.define("fact", fact_func());
|
scope.define("fact", fact_func());
|
||||||
scope.define("perm", perm_func());
|
scope.define("perm", perm_func());
|
||||||
scope.define("binom", binom_func());
|
scope.define("binom", binom_func());
|
||||||
@ -96,7 +98,7 @@ cast! {
|
|||||||
pub fn pow(
|
pub fn pow(
|
||||||
/// The base of the power.
|
/// The base of the power.
|
||||||
base: Num,
|
base: Num,
|
||||||
/// The exponent of the power. Must be non-negative.
|
/// The exponent of the power.
|
||||||
exponent: Spanned<Num>,
|
exponent: Spanned<Num>,
|
||||||
/// The callsite span.
|
/// The callsite span.
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -120,8 +122,15 @@ pub fn pow(
|
|||||||
.map(Num::Int)
|
.map(Num::Int)
|
||||||
.ok_or("the result is too large")
|
.ok_or("the result is too large")
|
||||||
.at(span)?,
|
.at(span)?,
|
||||||
(a, Num::Int(b)) => Num::Float(a.float().powi(b as i32)),
|
(a, b) => Num::Float(if a.float() == std::f64::consts::E {
|
||||||
(a, b) => Num::Float(a.float().powf(b.float())),
|
b.float().exp()
|
||||||
|
} else if a.float() == 2.0 {
|
||||||
|
b.float().exp2()
|
||||||
|
} else if let Num::Int(b) = b {
|
||||||
|
a.float().powi(b as i32)
|
||||||
|
} else {
|
||||||
|
a.float().powf(b.float())
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
if result.float().is_nan() {
|
if result.float().is_nan() {
|
||||||
@ -131,6 +140,40 @@ pub fn pow(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raise a value to some exponent of e.
|
||||||
|
///
|
||||||
|
/// ## Example { #example }
|
||||||
|
/// ```example
|
||||||
|
/// #calc.exp(3)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Display: Exponential
|
||||||
|
/// Category: calculate
|
||||||
|
#[func]
|
||||||
|
pub fn exp(
|
||||||
|
/// The exponent of the power.
|
||||||
|
exponent: Spanned<Num>,
|
||||||
|
/// The callsite span.
|
||||||
|
span: Span,
|
||||||
|
) -> SourceResult<f64> {
|
||||||
|
match exponent.v {
|
||||||
|
Num::Int(i) if i32::try_from(i).is_err() => {
|
||||||
|
bail!(exponent.span, "exponent is too large")
|
||||||
|
}
|
||||||
|
Num::Float(f) if !f.is_normal() && f != 0.0 => {
|
||||||
|
bail!(exponent.span, "exponent may not be infinite, subnormal, or NaN")
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = exponent.v.float().exp();
|
||||||
|
if result.is_nan() {
|
||||||
|
bail!(span, "the result is not a real number")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the square root of a number.
|
/// Calculate the square root of a number.
|
||||||
///
|
///
|
||||||
/// ## Example { #example }
|
/// ## Example { #example }
|
||||||
@ -416,7 +459,9 @@ pub fn log(
|
|||||||
bail!(base.span, "base may not be zero, NaN, infinite, or subnormal")
|
bail!(base.span, "base may not be zero, NaN, infinite, or subnormal")
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = if base.v == 2.0 {
|
let result = if base.v == std::f64::consts::E {
|
||||||
|
number.ln()
|
||||||
|
} else if base.v == 2.0 {
|
||||||
number.log2()
|
number.log2()
|
||||||
} else if base.v == 10.0 {
|
} else if base.v == 10.0 {
|
||||||
number.log10()
|
number.log10()
|
||||||
@ -431,6 +476,35 @@ pub fn log(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate the natural logarithm of a number.
|
||||||
|
///
|
||||||
|
/// ## Example { #example }
|
||||||
|
/// ```example
|
||||||
|
/// #calc.ln(100)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Display: Natural Logarithm
|
||||||
|
/// Category: calculate
|
||||||
|
#[func]
|
||||||
|
pub fn ln(
|
||||||
|
/// The number whose logarithm to calculate. Must be strictly positive.
|
||||||
|
value: Spanned<Num>,
|
||||||
|
/// The callsite span.
|
||||||
|
span: Span,
|
||||||
|
) -> SourceResult<f64> {
|
||||||
|
let number = value.v.float();
|
||||||
|
if number <= 0.0 {
|
||||||
|
bail!(value.span, "value must be strictly positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = number.ln();
|
||||||
|
if result.is_infinite() {
|
||||||
|
bail!(span, "result close to -inf")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate the factorial of a number.
|
/// Calculate the factorial of a number.
|
||||||
///
|
///
|
||||||
/// ## Example { #example }
|
/// ## Example { #example }
|
||||||
|
@ -94,9 +94,11 @@
|
|||||||
#test(calc.min("hi"), "hi")
|
#test(calc.min("hi"), "hi")
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test the `calc` function.
|
// Test the `pow`, `log`, `exp`, and `ln` functions.
|
||||||
#test(calc.pow(10, 0), 1)
|
#test(calc.pow(10, 0), 1)
|
||||||
#test(calc.pow(2, 4), 16)
|
#test(calc.pow(2, 4), 16)
|
||||||
|
#test(calc.exp(2), calc.pow(calc.e, 2))
|
||||||
|
#test(calc.ln(10), calc.log(10, base: calc.e))
|
||||||
|
|
||||||
---
|
---
|
||||||
// Error: 10-16 zero to the power of zero is undefined
|
// Error: 10-16 zero to the power of zero is undefined
|
||||||
|
Loading…
x
Reference in New Issue
Block a user