mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Simplify calc
functions
This commit is contained in:
parent
0287b98ef3
commit
53844b5a87
@ -1,4 +1,5 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::ops::Rem;
|
||||||
|
|
||||||
use typst::model::{Module, Scope};
|
use typst::model::{Module, Scope};
|
||||||
|
|
||||||
@ -95,8 +96,7 @@ pub fn pow(args: &mut Args) -> SourceResult<Value> {
|
|||||||
_ => bail!(n.span, "exponent must be non-negative"),
|
_ => bail!(n.span, "exponent must be non-negative"),
|
||||||
})?
|
})?
|
||||||
.v;
|
.v;
|
||||||
|
Ok(base.apply2(exponent, |a, b| a.pow(b as u32), f64::powf))
|
||||||
Ok(base.apply2(exponent, |a, b| a.pow(b as u32), |a, b| a.powf(b)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Square Root
|
/// # Square Root
|
||||||
@ -117,7 +117,7 @@ pub fn pow(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn sqrt(args: &mut Args) -> SourceResult<Value> {
|
pub fn sqrt(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Spanned<Num>>("value")?;
|
let value = args.expect::<Spanned<Num>>("value")?;
|
||||||
if value.v.is_negative() {
|
if value.v.float() < 0.0 {
|
||||||
bail!(value.span, "cannot take square root of negative number");
|
bail!(value.span, "cannot take square root of negative number");
|
||||||
}
|
}
|
||||||
Ok(Value::Float(value.v.float().sqrt()))
|
Ok(Value::Float(value.v.float().sqrt()))
|
||||||
@ -143,7 +143,6 @@ pub fn sqrt(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn sin(args: &mut Args) -> SourceResult<Value> {
|
pub fn sin(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.sin(),
|
AngleLike::Angle(a) => a.sin(),
|
||||||
AngleLike::Int(n) => (n as f64).sin(),
|
AngleLike::Int(n) => (n as f64).sin(),
|
||||||
@ -171,7 +170,6 @@ pub fn sin(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn cos(args: &mut Args) -> SourceResult<Value> {
|
pub fn cos(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.cos(),
|
AngleLike::Angle(a) => a.cos(),
|
||||||
AngleLike::Int(n) => (n as f64).cos(),
|
AngleLike::Int(n) => (n as f64).cos(),
|
||||||
@ -198,7 +196,6 @@ pub fn cos(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn tan(args: &mut Args) -> SourceResult<Value> {
|
pub fn tan(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.tan(),
|
AngleLike::Angle(a) => a.tan(),
|
||||||
AngleLike::Int(n) => (n as f64).tan(),
|
AngleLike::Int(n) => (n as f64).tan(),
|
||||||
@ -228,7 +225,6 @@ pub fn asin(args: &mut Args) -> SourceResult<Value> {
|
|||||||
if val < -1.0 || val > 1.0 {
|
if val < -1.0 || val > 1.0 {
|
||||||
bail!(span, "arcsin must be between -1 and 1");
|
bail!(span, "arcsin must be between -1 and 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Angle(Angle::rad(val.asin())))
|
Ok(Value::Angle(Angle::rad(val.asin())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +250,6 @@ pub fn acos(args: &mut Args) -> SourceResult<Value> {
|
|||||||
if val < -1.0 || val > 1.0 {
|
if val < -1.0 || val > 1.0 {
|
||||||
bail!(span, "arccos must be between -1 and 1");
|
bail!(span, "arccos must be between -1 and 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::Angle(Angle::rad(val.acos())))
|
Ok(Value::Angle(Angle::rad(val.acos())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +271,6 @@ pub fn acos(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn atan(args: &mut Args) -> SourceResult<Value> {
|
pub fn atan(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<Num>("value")?;
|
||||||
|
|
||||||
Ok(Value::Angle(Angle::rad(value.float().atan())))
|
Ok(Value::Angle(Angle::rad(value.float().atan())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,9 +293,8 @@ pub fn atan(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn sinh(args: &mut Args) -> SourceResult<Value> {
|
pub fn sinh(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.to_rad(),
|
AngleLike::Angle(a) => a.to_rad().sinh(),
|
||||||
AngleLike::Int(n) => (n as f64).sinh(),
|
AngleLike::Int(n) => (n as f64).sinh(),
|
||||||
AngleLike::Float(n) => n.sinh(),
|
AngleLike::Float(n) => n.sinh(),
|
||||||
}))
|
}))
|
||||||
@ -326,9 +319,8 @@ pub fn sinh(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn cosh(args: &mut Args) -> SourceResult<Value> {
|
pub fn cosh(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.to_rad(),
|
AngleLike::Angle(a) => a.to_rad().cosh(),
|
||||||
AngleLike::Int(n) => (n as f64).cosh(),
|
AngleLike::Int(n) => (n as f64).cosh(),
|
||||||
AngleLike::Float(n) => n.cosh(),
|
AngleLike::Float(n) => n.cosh(),
|
||||||
}))
|
}))
|
||||||
@ -353,9 +345,8 @@ pub fn cosh(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn tanh(args: &mut Args) -> SourceResult<Value> {
|
pub fn tanh(args: &mut Args) -> SourceResult<Value> {
|
||||||
let arg = args.expect::<AngleLike>("angle")?;
|
let arg = args.expect::<AngleLike>("angle")?;
|
||||||
|
|
||||||
Ok(Value::Float(match arg {
|
Ok(Value::Float(match arg {
|
||||||
AngleLike::Angle(a) => a.to_rad(),
|
AngleLike::Angle(a) => a.to_rad().tanh(),
|
||||||
AngleLike::Int(n) => (n as f64).tanh(),
|
AngleLike::Int(n) => (n as f64).tanh(),
|
||||||
AngleLike::Float(n) => n.tanh(),
|
AngleLike::Float(n) => n.tanh(),
|
||||||
}))
|
}))
|
||||||
@ -380,10 +371,9 @@ pub fn tanh(args: &mut Args) -> SourceResult<Value> {
|
|||||||
/// calculate
|
/// calculate
|
||||||
#[func]
|
#[func]
|
||||||
pub fn log(args: &mut Args) -> SourceResult<Value> {
|
pub fn log(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<f64>("value")?;
|
||||||
let base = args.named::<Num>("base")?.unwrap_or_else(|| Num::Int(10));
|
let base = args.named::<f64>("base")?.unwrap_or_else(|| 10.0);
|
||||||
|
Ok(Value::Float(value.log(base)))
|
||||||
Ok(value.apply2(base, |a, b| a.ilog(b) as i64, |a, b| a.log(b)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Round down
|
/// # Round down
|
||||||
@ -406,7 +396,6 @@ pub fn log(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn floor(args: &mut Args) -> SourceResult<Value> {
|
pub fn floor(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<Num>("value")?;
|
||||||
|
|
||||||
Ok(match value {
|
Ok(match value {
|
||||||
Num::Int(n) => Value::Int(n),
|
Num::Int(n) => Value::Int(n),
|
||||||
Num::Float(n) => Value::Int(n.floor() as i64),
|
Num::Float(n) => Value::Int(n.floor() as i64),
|
||||||
@ -433,7 +422,6 @@ pub fn floor(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn ceil(args: &mut Args) -> SourceResult<Value> {
|
pub fn ceil(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<Num>("value")?;
|
||||||
|
|
||||||
Ok(match value {
|
Ok(match value {
|
||||||
Num::Int(n) => Value::Int(n),
|
Num::Int(n) => Value::Int(n),
|
||||||
Num::Float(n) => Value::Int(n.ceil() as i64),
|
Num::Float(n) => Value::Int(n.ceil() as i64),
|
||||||
@ -461,22 +449,12 @@ pub fn ceil(args: &mut Args) -> SourceResult<Value> {
|
|||||||
#[func]
|
#[func]
|
||||||
pub fn round(args: &mut Args) -> SourceResult<Value> {
|
pub fn round(args: &mut Args) -> SourceResult<Value> {
|
||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<Num>("value")?;
|
||||||
let digits = args.named::<Spanned<i64>>("digits").and_then(|n| match n {
|
let digits = args.named::<u32>("digits")?.unwrap_or(0);
|
||||||
Some(Spanned { v, span }) if v < 0 => {
|
|
||||||
bail!(span, "digits must be non-negative")
|
|
||||||
}
|
|
||||||
Some(Spanned { v, span }) if v > i32::MAX as i64 => {
|
|
||||||
bail!(span, "digits must be less than {}", i32::MAX)
|
|
||||||
}
|
|
||||||
Some(Spanned { v, .. }) => Ok(v as i32),
|
|
||||||
None => Ok(0),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(match value {
|
Ok(match value {
|
||||||
Num::Int(n) if digits == 0 => Value::Int(n),
|
Num::Int(n) if digits == 0 => Value::Int(n),
|
||||||
_ => {
|
_ => {
|
||||||
let n = value.float();
|
let n = value.float();
|
||||||
let factor = 10.0_f64.powi(digits) as f64;
|
let factor = 10.0_f64.powi(digits as i32) as f64;
|
||||||
Value::Float((n * factor).round() / factor)
|
Value::Float((n * factor).round() / factor)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -507,33 +485,10 @@ pub fn clamp(args: &mut Args) -> SourceResult<Value> {
|
|||||||
let value = args.expect::<Num>("value")?;
|
let value = args.expect::<Num>("value")?;
|
||||||
let min = args.expect::<Num>("min")?;
|
let min = args.expect::<Num>("min")?;
|
||||||
let max = args.expect::<Spanned<Num>>("max")?;
|
let max = args.expect::<Spanned<Num>>("max")?;
|
||||||
|
|
||||||
if max.v.float() < min.float() {
|
if max.v.float() < min.float() {
|
||||||
bail!(max.span, "max must be greater than or equal to min")
|
bail!(max.span, "max must be greater than or equal to min")
|
||||||
}
|
}
|
||||||
|
Ok(value.apply3(min, max.v, i64::clamp, f64::clamp))
|
||||||
Ok(value.apply3(
|
|
||||||
min,
|
|
||||||
max.v,
|
|
||||||
|v, min, max| {
|
|
||||||
if v < min {
|
|
||||||
min
|
|
||||||
} else if v > max {
|
|
||||||
max
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|v, min, max| {
|
|
||||||
if v < min {
|
|
||||||
min
|
|
||||||
} else if v > max {
|
|
||||||
max
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Minimum
|
/// # Minimum
|
||||||
@ -672,33 +627,15 @@ pub fn odd(args: &mut Args) -> SourceResult<Value> {
|
|||||||
/// calculate
|
/// calculate
|
||||||
#[func]
|
#[func]
|
||||||
pub fn mod_(args: &mut Args) -> SourceResult<Value> {
|
pub fn mod_(args: &mut Args) -> SourceResult<Value> {
|
||||||
let Spanned { v: v1, span: span1 } = args.expect("dividend")?;
|
let dividend = args.expect::<Num>("dividend")?;
|
||||||
let Spanned { v: v2, span: span2 } = args.expect("divisor")?;
|
let Spanned { v: divisor, span } = args.expect::<Spanned<Num>>("divisor")?;
|
||||||
|
if divisor.float() == 0.0 {
|
||||||
let (a, b) = match (v1, v2) {
|
bail!(span, "divisor must not be zero");
|
||||||
(Value::Int(a), Value::Int(b)) => match a.checked_rem(b) {
|
|
||||||
Some(res) => return Ok(Value::Int(res)),
|
|
||||||
None => bail!(span2, "divisor must not be zero"),
|
|
||||||
},
|
|
||||||
(Value::Int(a), Value::Float(b)) => (a as f64, b),
|
|
||||||
(Value::Float(a), Value::Int(b)) => (a, b as f64),
|
|
||||||
(Value::Float(a), Value::Float(b)) => (a, b),
|
|
||||||
(Value::Int(_), b) | (Value::Float(_), b) => {
|
|
||||||
bail!(span2, format!("expected integer or float, found {}", b.type_name()))
|
|
||||||
}
|
}
|
||||||
(a, _) => {
|
Ok(dividend.apply2(divisor, Rem::rem, Rem::rem))
|
||||||
bail!(span1, format!("expected integer or float, found {}", a.type_name()))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if b == 0.0 {
|
|
||||||
bail!(span2, "divisor must not be zero");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::Float(a % b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value which can be passed to the `mod` function.
|
/// A value which can be passed to functions that work with integers and floats.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
enum Num {
|
enum Num {
|
||||||
Int(i64),
|
Int(i64),
|
||||||
@ -737,13 +674,6 @@ impl Num {
|
|||||||
Self::Float(v) => v,
|
Self::Float(v) => v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_negative(self) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::Int(v) => v < 0,
|
|
||||||
Self::Float(v) => v < 0.0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
castable! {
|
castable! {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user