typst_library/foundations/
calc.rs

1//! Calculations and processing of numeric values.
2
3use std::cmp;
4use std::cmp::Ordering;
5
6use az::SaturatingAs;
7use typst_syntax::{Span, Spanned};
8use typst_utils::{round_int_with_precision, round_with_precision};
9
10use crate::diag::{At, HintedString, SourceResult, StrResult, bail};
11use crate::foundations::{Decimal, IntoValue, Module, Scope, Value, cast, func, ops};
12use crate::layout::{Angle, Fr, Length, Ratio};
13
14/// A module with calculation definitions.
15pub fn module() -> Module {
16    let mut scope = Scope::new();
17    scope.define_func::<abs>();
18    scope.define_func::<pow>();
19    scope.define_func::<exp>();
20    scope.define_func::<sqrt>();
21    scope.define_func::<root>();
22    scope.define_func::<sin>();
23    scope.define_func::<cos>();
24    scope.define_func::<tan>();
25    scope.define_func::<asin>();
26    scope.define_func::<acos>();
27    scope.define_func::<atan>();
28    scope.define_func::<atan2>();
29    scope.define_func::<sinh>();
30    scope.define_func::<cosh>();
31    scope.define_func::<tanh>();
32    scope.define_func::<log>();
33    scope.define_func::<ln>();
34    scope.define_func::<fact>();
35    scope.define_func::<perm>();
36    scope.define_func::<binom>();
37    scope.define_func::<gcd>();
38    scope.define_func::<lcm>();
39    scope.define_func::<floor>();
40    scope.define_func::<ceil>();
41    scope.define_func::<trunc>();
42    scope.define_func::<fract>();
43    scope.define_func::<round>();
44    scope.define_func::<clamp>();
45    scope.define_func::<min>();
46    scope.define_func::<max>();
47    scope.define_func::<even>();
48    scope.define_func::<odd>();
49    scope.define_func::<rem>();
50    scope.define_func::<div_euclid>();
51    scope.define_func::<rem_euclid>();
52    scope.define_func::<quo>();
53    scope.define_func::<norm>();
54    scope.define("inf", f64::INFINITY);
55    scope.define("pi", std::f64::consts::PI);
56    scope.define("tau", std::f64::consts::TAU);
57    scope.define("e", std::f64::consts::E);
58    Module::new("calc", scope)
59}
60
61/// Calculates the absolute value of a numeric value.
62///
63/// ```example
64/// #calc.abs(-5) \
65/// #calc.abs(5pt - 2cm) \
66/// #calc.abs(2fr) \
67/// #calc.abs(decimal("-342.440"))
68/// ```
69#[func(title = "Absolute")]
70pub fn abs(
71    /// The value whose absolute value to calculate.
72    value: ToAbs,
73) -> Value {
74    value.0
75}
76
77/// A value of which the absolute value can be taken.
78pub struct ToAbs(Value);
79
80cast! {
81    ToAbs,
82    v: i64 => Self(v.abs().into_value()),
83    v: f64 => Self(v.abs().into_value()),
84    v: Length => Self(Value::Length(v.try_abs()
85        .ok_or("cannot take absolute value of this length")?)),
86    v: Angle => Self(Value::Angle(v.abs())),
87    v: Ratio => Self(Value::Ratio(v.abs())),
88    v: Fr => Self(Value::Fraction(v.abs())),
89    v: Decimal => Self(Value::Decimal(v.abs()))
90}
91
92/// Raises a value to some exponent.
93///
94/// ```example
95/// #calc.pow(2, 3) \
96/// #calc.pow(decimal("2.5"), 2)
97/// ```
98#[func(title = "Power")]
99pub fn pow(
100    span: Span,
101    /// The base of the power.
102    ///
103    /// If this is a [`decimal`], the exponent can only be an [integer]($int).
104    base: DecNum,
105    /// The exponent of the power.
106    exponent: Spanned<Num>,
107) -> SourceResult<DecNum> {
108    match exponent.v {
109        _ if exponent.v.float() == 0.0 && base.is_zero() => {
110            bail!(span, "zero to the power of zero is undefined")
111        }
112        Num::Int(i) if i32::try_from(i).is_err() => {
113            bail!(exponent.span, "exponent is too large")
114        }
115        Num::Float(f) if !f.is_normal() && f != 0.0 => {
116            bail!(exponent.span, "exponent may not be infinite, subnormal, or NaN")
117        }
118        _ => {}
119    };
120
121    match (base, exponent.v) {
122        (DecNum::Int(a), Num::Int(b)) if b >= 0 => a
123            .checked_pow(b as u32)
124            .map(DecNum::Int)
125            .ok_or_else(too_large)
126            .at(span),
127        (DecNum::Decimal(a), Num::Int(b)) => {
128            a.checked_powi(b).map(DecNum::Decimal).ok_or_else(too_large).at(span)
129        }
130        (a, b) => {
131            let Some(a) = a.float() else {
132                return Err(cant_apply_to_decimal_and_float()).at(span);
133            };
134
135            let result = if a == std::f64::consts::E {
136                b.float().exp()
137            } else if a == 2.0 {
138                b.float().exp2()
139            } else if let Num::Int(b) = b {
140                a.powi(b as i32)
141            } else {
142                a.powf(b.float())
143            };
144
145            if result.is_nan() {
146                bail!(span, "the result is not a real number")
147            }
148
149            Ok(DecNum::Float(result))
150        }
151    }
152}
153
154/// Raises a value to some exponent of e.
155///
156/// ```example
157/// #calc.exp(1)
158/// ```
159#[func(title = "Exponential")]
160pub fn exp(
161    span: Span,
162    /// The exponent of the power.
163    exponent: Spanned<Num>,
164) -> SourceResult<f64> {
165    match exponent.v {
166        Num::Int(i) if i32::try_from(i).is_err() => {
167            bail!(exponent.span, "exponent is too large")
168        }
169        Num::Float(f) if !f.is_normal() && f != 0.0 => {
170            bail!(exponent.span, "exponent may not be infinite, subnormal, or NaN")
171        }
172        _ => {}
173    }
174
175    let result = exponent.v.float().exp();
176    if result.is_nan() {
177        bail!(span, "the result is not a real number")
178    }
179
180    Ok(result)
181}
182
183/// Calculates the square root of a number.
184///
185/// ```example
186/// #calc.sqrt(16) \
187/// #calc.sqrt(2.5)
188/// ```
189#[func(title = "Square Root")]
190pub fn sqrt(
191    /// The number whose square root to calculate. Must be non-negative.
192    value: Spanned<Num>,
193) -> SourceResult<f64> {
194    if value.v.float() < 0.0 {
195        bail!(value.span, "cannot take square root of negative number");
196    }
197    Ok(value.v.float().sqrt())
198}
199
200/// Calculates the real nth root of a number.
201///
202/// If the number is negative, then n must be odd.
203///
204/// ```example
205/// #calc.root(16.0, 4) \
206/// #calc.root(27.0, 3)
207/// ```
208#[func]
209pub fn root(
210    /// The expression to take the root of.
211    radicand: f64,
212    /// Which root of the radicand to take.
213    index: Spanned<i64>,
214) -> SourceResult<f64> {
215    if index.v == 0 {
216        bail!(index.span, "cannot take the 0th root of a number");
217    } else if radicand < 0.0 {
218        if index.v % 2 == 0 {
219            bail!(
220                index.span,
221                "negative numbers do not have a real nth root when n is even"
222            );
223        } else {
224            Ok(-(-radicand).powf(1.0 / index.v as f64))
225        }
226    } else {
227        Ok(radicand.powf(1.0 / index.v as f64))
228    }
229}
230
231/// Calculates the sine of an angle.
232///
233/// When called with an integer or a float, they will be interpreted as
234/// radians.
235///
236/// ```example
237/// #calc.sin(1.5) \
238/// #calc.sin(90deg)
239/// ```
240#[func(title = "Sine")]
241pub fn sin(
242    /// The angle whose sine to calculate.
243    angle: AngleLike,
244) -> f64 {
245    match angle {
246        AngleLike::Angle(a) => a.sin(),
247        AngleLike::Int(n) => (n as f64).sin(),
248        AngleLike::Float(n) => n.sin(),
249    }
250}
251
252/// Calculates the cosine of an angle.
253///
254/// When called with an integer or a float, they will be interpreted as
255/// radians.
256///
257/// ```example
258/// #calc.cos(1.5) \
259/// #calc.cos(90deg)
260/// ```
261#[func(title = "Cosine")]
262pub fn cos(
263    /// The angle whose cosine to calculate.
264    angle: AngleLike,
265) -> f64 {
266    match angle {
267        AngleLike::Angle(a) => a.cos(),
268        AngleLike::Int(n) => (n as f64).cos(),
269        AngleLike::Float(n) => n.cos(),
270    }
271}
272
273/// Calculates the tangent of an angle.
274///
275/// When called with an integer or a float, they will be interpreted as
276/// radians.
277///
278/// ```example
279/// #calc.tan(1.5) \
280/// #calc.tan(90deg)
281/// ```
282#[func(title = "Tangent")]
283pub fn tan(
284    /// The angle whose tangent to calculate.
285    angle: AngleLike,
286) -> f64 {
287    match angle {
288        AngleLike::Angle(a) => a.tan(),
289        AngleLike::Int(n) => (n as f64).tan(),
290        AngleLike::Float(n) => n.tan(),
291    }
292}
293
294/// Calculates the arcsine of a number.
295///
296/// ```example
297/// #calc.asin(0) \
298/// #calc.asin(1)
299/// ```
300#[func(title = "Arcsine")]
301pub fn asin(
302    /// The number whose arcsine to calculate. Must be between -1 and 1.
303    value: Spanned<Num>,
304) -> SourceResult<Angle> {
305    let val = value.v.float();
306    if val < -1.0 || val > 1.0 {
307        bail!(value.span, "value must be between -1 and 1");
308    }
309    Ok(Angle::rad(val.asin()))
310}
311
312/// Calculates the arccosine of a number.
313///
314/// ```example
315/// #calc.acos(0) \
316/// #calc.acos(1)
317/// ```
318#[func(title = "Arccosine")]
319pub fn acos(
320    /// The number whose arccosine to calculate. Must be between -1 and 1.
321    value: Spanned<Num>,
322) -> SourceResult<Angle> {
323    let val = value.v.float();
324    if val < -1.0 || val > 1.0 {
325        bail!(value.span, "value must be between -1 and 1");
326    }
327    Ok(Angle::rad(val.acos()))
328}
329
330/// Calculates the arctangent of a number.
331///
332/// ```example
333/// #calc.atan(0) \
334/// #calc.atan(1)
335/// ```
336#[func(title = "Arctangent")]
337pub fn atan(
338    /// The number whose arctangent to calculate.
339    value: Num,
340) -> Angle {
341    Angle::rad(value.float().atan())
342}
343
344/// Calculates the four-quadrant arctangent of a coordinate.
345///
346/// The arguments are `(x, y)`, not `(y, x)`.
347///
348/// ```example
349/// #calc.atan2(1, 1) \
350/// #calc.atan2(-2, -3)
351/// ```
352#[func(title = "Four-quadrant Arctangent")]
353pub fn atan2(
354    /// The X coordinate.
355    x: Num,
356    /// The Y coordinate.
357    y: Num,
358) -> Angle {
359    Angle::rad(f64::atan2(y.float(), x.float()))
360}
361
362/// Calculates the hyperbolic sine of a hyperbolic angle.
363///
364/// ```example
365/// #calc.sinh(0) \
366/// #calc.sinh(1.5)
367/// ```
368#[func(title = "Hyperbolic Sine")]
369pub fn sinh(
370    /// The hyperbolic angle whose hyperbolic sine to calculate.
371    value: f64,
372) -> f64 {
373    value.sinh()
374}
375
376/// Calculates the hyperbolic cosine of a hyperbolic angle.
377///
378/// ```example
379/// #calc.cosh(0) \
380/// #calc.cosh(1.5)
381/// ```
382#[func(title = "Hyperbolic Cosine")]
383pub fn cosh(
384    /// The hyperbolic angle whose hyperbolic cosine to calculate.
385    value: f64,
386) -> f64 {
387    value.cosh()
388}
389
390/// Calculates the hyperbolic tangent of a hyperbolic angle.
391///
392/// ```example
393/// #calc.tanh(0) \
394/// #calc.tanh(1.5)
395/// ```
396#[func(title = "Hyperbolic Tangent")]
397pub fn tanh(
398    /// The hyperbolic angle whose hyperbolic tangent to calculate.
399    value: f64,
400) -> f64 {
401    value.tanh()
402}
403
404/// Calculates the logarithm of a number.
405///
406/// If the base is not specified, the logarithm is calculated in base 10.
407///
408/// ```example
409/// #calc.log(100)
410/// ```
411#[func(title = "Logarithm")]
412pub fn log(
413    span: Span,
414    /// The number whose logarithm to calculate. Must be strictly positive.
415    value: Spanned<Num>,
416    /// The base of the logarithm. May not be zero.
417    #[named]
418    #[default(Spanned::new(10.0, Span::detached()))]
419    base: Spanned<f64>,
420) -> SourceResult<f64> {
421    let number = value.v.float();
422    if number <= 0.0 {
423        bail!(value.span, "value must be strictly positive")
424    }
425
426    if !base.v.is_normal() {
427        bail!(base.span, "base may not be zero, NaN, infinite, or subnormal")
428    }
429
430    let result = if base.v == std::f64::consts::E {
431        number.ln()
432    } else if base.v == 2.0 {
433        number.log2()
434    } else if base.v == 10.0 {
435        number.log10()
436    } else {
437        number.log(base.v)
438    };
439
440    if result.is_infinite() || result.is_nan() {
441        bail!(span, "the result is not a real number")
442    }
443
444    Ok(result)
445}
446
447/// Calculates the natural logarithm of a number.
448///
449/// ```example
450/// #calc.ln(calc.e)
451/// ```
452#[func(title = "Natural Logarithm")]
453pub fn ln(
454    span: Span,
455    /// The number whose logarithm to calculate. Must be strictly positive.
456    value: Spanned<Num>,
457) -> SourceResult<f64> {
458    let number = value.v.float();
459    if number <= 0.0 {
460        bail!(value.span, "value must be strictly positive")
461    }
462
463    let result = number.ln();
464    if result.is_infinite() {
465        bail!(span, "result close to -inf")
466    }
467
468    Ok(result)
469}
470
471/// Calculates the factorial of a number.
472///
473/// ```example
474/// #calc.fact(5)
475/// ```
476#[func(title = "Factorial")]
477pub fn fact(
478    /// The number whose factorial to calculate. Must be non-negative.
479    number: u64,
480) -> StrResult<i64> {
481    Ok(fact_impl(1, number).ok_or_else(too_large)?)
482}
483
484/// Calculates a permutation.
485///
486/// Returns the `k`-permutation of `n`, or the number of ways to choose `k`
487/// items from a set of `n` with regard to order.
488///
489/// ```example
490/// $ "perm"(n, k) &= n!/((n - k)!) \
491///   "perm"(5, 3) &= #calc.perm(5, 3) $
492/// ```
493#[func(title = "Permutation")]
494pub fn perm(
495    /// The base number. Must be non-negative.
496    base: u64,
497    /// The number of permutations. Must be non-negative.
498    numbers: u64,
499) -> StrResult<i64> {
500    // By convention.
501    if base < numbers {
502        return Ok(0);
503    }
504
505    Ok(fact_impl(base - numbers + 1, base).ok_or_else(too_large)?)
506}
507
508/// Calculates the product of a range of numbers. Used to calculate
509/// permutations. Returns None if the result is larger than `i64::MAX`
510fn fact_impl(start: u64, end: u64) -> Option<i64> {
511    // By convention
512    if end + 1 < start {
513        return Some(0);
514    }
515
516    let real_start: u64 = cmp::max(1, start);
517    let mut count: u64 = 1;
518    for i in real_start..=end {
519        count = count.checked_mul(i)?;
520    }
521
522    count.try_into().ok()
523}
524
525/// Calculates a binomial coefficient.
526///
527/// Returns the `k`-combination of `n`, or the number of ways to choose `k`
528/// items from a set of `n` without regard to order.
529///
530/// ```example
531/// #calc.binom(10, 5)
532/// ```
533#[func(title = "Binomial")]
534pub fn binom(
535    /// The upper coefficient. Must be non-negative.
536    n: u64,
537    /// The lower coefficient. Must be non-negative.
538    k: u64,
539) -> StrResult<i64> {
540    Ok(binom_impl(n, k).ok_or_else(too_large)?)
541}
542
543/// Calculates a binomial coefficient, with `n` the upper coefficient and `k`
544/// the lower coefficient. Returns `None` if the result is larger than
545/// `i64::MAX`
546fn binom_impl(n: u64, k: u64) -> Option<i64> {
547    if k > n {
548        return Some(0);
549    }
550
551    // By symmetry
552    let real_k = cmp::min(n - k, k);
553    if real_k == 0 {
554        return Some(1);
555    }
556
557    let mut result: u64 = 1;
558    for i in 0..real_k {
559        result = result.checked_mul(n - i)?.checked_div(i + 1)?;
560    }
561
562    result.try_into().ok()
563}
564
565/// Calculates the greatest common divisor of two integers.
566///
567/// This will error if the result of integer division would be larger than the
568/// maximum 64-bit signed integer.
569///
570/// ```example
571/// #calc.gcd(7, 42)
572/// ```
573#[func(title = "Greatest Common Divisor")]
574pub fn gcd(
575    /// The first integer.
576    a: i64,
577    /// The second integer.
578    b: i64,
579) -> StrResult<i64> {
580    let (mut a, mut b) = (a, b);
581    while b != 0 {
582        let temp = b;
583        b = a.checked_rem(b).ok_or_else(too_large)?;
584        a = temp;
585    }
586
587    Ok(a.abs())
588}
589
590/// Calculates the least common multiple of two integers.
591///
592/// ```example
593/// #calc.lcm(96, 13)
594/// ```
595#[func(title = "Least Common Multiple")]
596pub fn lcm(
597    /// The first integer.
598    a: i64,
599    /// The second integer.
600    b: i64,
601) -> StrResult<i64> {
602    if a == b {
603        return Ok(a.abs());
604    }
605
606    Ok(a.checked_div(gcd(a, b)?)
607        .and_then(|gcd| gcd.checked_mul(b))
608        .map(|v| v.abs())
609        .ok_or_else(too_large)?)
610}
611
612/// Rounds a number down to the nearest integer.
613///
614/// If the number is already an integer, it is returned unchanged.
615///
616/// Note that this function will always return an [integer]($int), and will
617/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
618/// 64-bit signed integer or smaller than the minimum for that type.
619///
620/// ```example
621/// #calc.floor(500.1)
622/// #assert(calc.floor(3) == 3)
623/// #assert(calc.floor(3.14) == 3)
624/// #assert(calc.floor(decimal("-3.14")) == -4)
625/// ```
626#[func]
627pub fn floor(
628    /// The number to round down.
629    value: DecNum,
630) -> StrResult<i64> {
631    match value {
632        DecNum::Int(n) => Ok(n),
633        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.floor())
634            .map_err(|_| too_large())?),
635        DecNum::Decimal(n) => Ok(i64::try_from(n.floor()).map_err(|_| too_large())?),
636    }
637}
638
639/// Rounds a number up to the nearest integer.
640///
641/// If the number is already an integer, it is returned unchanged.
642///
643/// Note that this function will always return an [integer]($int), and will
644/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
645/// 64-bit signed integer or smaller than the minimum for that type.
646///
647/// ```example
648/// #calc.ceil(500.1)
649/// #assert(calc.ceil(3) == 3)
650/// #assert(calc.ceil(3.14) == 4)
651/// #assert(calc.ceil(decimal("-3.14")) == -3)
652/// ```
653#[func]
654pub fn ceil(
655    /// The number to round up.
656    value: DecNum,
657) -> StrResult<i64> {
658    match value {
659        DecNum::Int(n) => Ok(n),
660        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.ceil())
661            .map_err(|_| too_large())?),
662        DecNum::Decimal(n) => Ok(i64::try_from(n.ceil()).map_err(|_| too_large())?),
663    }
664}
665
666/// Returns the integer part of a number.
667///
668/// If the number is already an integer, it is returned unchanged.
669///
670/// Note that this function will always return an [integer]($int), and will
671/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
672/// 64-bit signed integer or smaller than the minimum for that type.
673///
674/// ```example
675/// #calc.trunc(15.9)
676/// #assert(calc.trunc(3) == 3)
677/// #assert(calc.trunc(-3.7) == -3)
678/// #assert(calc.trunc(decimal("8493.12949582390")) == 8493)
679/// ```
680#[func(title = "Truncate")]
681pub fn trunc(
682    /// The number to truncate.
683    value: DecNum,
684) -> StrResult<i64> {
685    match value {
686        DecNum::Int(n) => Ok(n),
687        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.trunc())
688            .map_err(|_| too_large())?),
689        DecNum::Decimal(n) => Ok(i64::try_from(n.trunc()).map_err(|_| too_large())?),
690    }
691}
692
693/// Returns the fractional part of a number.
694///
695/// If the number is an integer, returns `0`.
696///
697/// ```example
698/// #calc.fract(-3.1)
699/// #assert(calc.fract(3) == 0)
700/// #assert(calc.fract(decimal("234.23949211")) == decimal("0.23949211"))
701/// ```
702#[func(title = "Fractional")]
703pub fn fract(
704    /// The number to truncate.
705    value: DecNum,
706) -> DecNum {
707    match value {
708        DecNum::Int(_) => DecNum::Int(0),
709        DecNum::Float(n) => DecNum::Float(n.fract()),
710        DecNum::Decimal(n) => DecNum::Decimal(n.fract()),
711    }
712}
713
714/// Rounds a number to the nearest integer.
715///
716/// Half-integers are rounded away from zero.
717///
718/// Optionally, a number of decimal places can be specified. If negative, its
719/// absolute value will indicate the amount of significant integer digits to
720/// remove before the decimal point.
721///
722/// Note that this function will return the same type as the operand. That is,
723/// applying `round` to a [`float`] will return a `float`, and to a [`decimal`],
724/// another `decimal`. You may explicitly convert the output of this function to
725/// an integer with [`int`], but note that such a conversion will error if the
726/// `float` or `decimal` is larger than the maximum 64-bit signed integer or
727/// smaller than the minimum integer.
728///
729/// In addition, this function can error if there is an attempt to round beyond
730/// the maximum or minimum integer or `decimal`. If the number is a `float`,
731/// such an attempt will cause `{float.inf}` or `{-float.inf}` to be returned
732/// for maximum and minimum respectively.
733///
734/// ```example
735/// #calc.round(3.1415, digits: 2)
736/// #assert(calc.round(3) == 3)
737/// #assert(calc.round(3.14) == 3)
738/// #assert(calc.round(3.5) == 4.0)
739/// #assert(calc.round(3333.45, digits: -2) == 3300.0)
740/// #assert(calc.round(-48953.45, digits: -3) == -49000.0)
741/// #assert(calc.round(3333, digits: -2) == 3300)
742/// #assert(calc.round(-48953, digits: -3) == -49000)
743/// #assert(calc.round(decimal("-6.5")) == decimal("-7"))
744/// #assert(calc.round(decimal("7.123456789"), digits: 6) == decimal("7.123457"))
745/// #assert(calc.round(decimal("3333.45"), digits: -2) == decimal("3300"))
746/// #assert(calc.round(decimal("-48953.45"), digits: -3) == decimal("-49000"))
747/// ```
748#[func]
749pub fn round(
750    /// The number to round.
751    value: DecNum,
752    /// If positive, the number of decimal places.
753    ///
754    /// If negative, the number of significant integer digits that should be
755    /// removed before the decimal point.
756    #[named]
757    #[default(0)]
758    digits: i64,
759) -> StrResult<DecNum> {
760    match value {
761        DecNum::Int(n) => Ok(DecNum::Int(
762            round_int_with_precision(n, digits.saturating_as::<i16>())
763                .ok_or_else(too_large)?,
764        )),
765        DecNum::Float(n) => {
766            Ok(DecNum::Float(round_with_precision(n, digits.saturating_as::<i16>())))
767        }
768        DecNum::Decimal(n) => Ok(DecNum::Decimal(
769            n.round(digits.saturating_as::<i32>()).ok_or_else(too_large)?,
770        )),
771    }
772}
773
774/// Clamps a number between a minimum and maximum value.
775///
776/// ```example
777/// #calc.clamp(5, 0, 4)
778/// #assert(calc.clamp(5, 0, 10) == 5)
779/// #assert(calc.clamp(5, 6, 10) == 6)
780/// #assert(calc.clamp(decimal("5.45"), 2, decimal("45.9")) == decimal("5.45"))
781/// #assert(calc.clamp(decimal("5.45"), decimal("6.75"), 12) == decimal("6.75"))
782/// ```
783#[func]
784pub fn clamp(
785    span: Span,
786    /// The number to clamp.
787    value: DecNum,
788    /// The inclusive minimum value.
789    min: DecNum,
790    /// The inclusive maximum value.
791    max: Spanned<DecNum>,
792) -> SourceResult<DecNum> {
793    // Ignore if there are incompatible types (decimal and float) since that
794    // will cause `apply3` below to error before calling clamp, avoiding a
795    // panic.
796    if min
797        .apply2(max.v, |min, max| max < min, |min, max| max < min, |min, max| max < min)
798        .unwrap_or(false)
799    {
800        bail!(max.span, "max must be greater than or equal to min")
801    }
802
803    value
804        .apply3(min, max.v, i64::clamp, f64::clamp, Decimal::clamp)
805        .ok_or_else(cant_apply_to_decimal_and_float)
806        .at(span)
807}
808
809/// Determines the minimum of a sequence of values.
810///
811/// ```example
812/// #calc.min(1, -3, -5, 20, 3, 6) \
813/// #calc.min("typst", "is", "cool")
814/// ```
815#[func(title = "Minimum")]
816pub fn min(
817    span: Span,
818    /// The sequence of values from which to extract the minimum.
819    /// Must not be empty.
820    #[variadic]
821    values: Vec<Spanned<Value>>,
822) -> SourceResult<Value> {
823    minmax(span, values, Ordering::Less)
824}
825
826/// Determines the maximum of a sequence of values.
827///
828/// ```example
829/// #calc.max(1, -3, -5, 20, 3, 6) \
830/// #calc.max("typst", "is", "cool")
831/// ```
832#[func(title = "Maximum")]
833pub fn max(
834    span: Span,
835    /// The sequence of values from which to extract the maximum.
836    /// Must not be empty.
837    #[variadic]
838    values: Vec<Spanned<Value>>,
839) -> SourceResult<Value> {
840    minmax(span, values, Ordering::Greater)
841}
842
843/// Find the minimum or maximum of a sequence of values.
844fn minmax(
845    span: Span,
846    values: Vec<Spanned<Value>>,
847    goal: Ordering,
848) -> SourceResult<Value> {
849    let mut iter = values.into_iter();
850    let Some(Spanned { v: mut extremum, .. }) = iter.next() else {
851        bail!(span, "expected at least one value");
852    };
853
854    for Spanned { v, span } in iter {
855        let ordering = ops::compare(&v, &extremum).at(span)?;
856        if ordering == goal {
857            extremum = v;
858        }
859    }
860
861    Ok(extremum)
862}
863
864/// Determines whether an integer is even.
865///
866/// ```example
867/// #calc.even(4) \
868/// #calc.even(5) \
869/// #range(10).filter(calc.even)
870/// ```
871#[func]
872pub fn even(
873    /// The number to check for evenness.
874    value: i64,
875) -> bool {
876    value % 2 == 0
877}
878
879/// Determines whether an integer is odd.
880///
881/// ```example
882/// #calc.odd(4) \
883/// #calc.odd(5) \
884/// #range(10).filter(calc.odd)
885/// ```
886#[func]
887pub fn odd(
888    /// The number to check for oddness.
889    value: i64,
890) -> bool {
891    value % 2 != 0
892}
893
894/// Calculates the remainder of two numbers.
895///
896/// The value `calc.rem(x, y)` always has the same sign as `x`, and is smaller
897/// in magnitude than `y`.
898///
899/// This can error if given a [`decimal`] input and the dividend is too small in
900/// magnitude compared to the divisor.
901///
902/// ```example
903/// #calc.rem(7, 3) \
904/// #calc.rem(7, -3) \
905/// #calc.rem(-7, 3) \
906/// #calc.rem(-7, -3) \
907/// #calc.rem(1.75, 0.5)
908/// ```
909#[func(title = "Remainder")]
910pub fn rem(
911    span: Span,
912    /// The dividend of the remainder.
913    dividend: DecNum,
914    /// The divisor of the remainder.
915    divisor: Spanned<DecNum>,
916) -> SourceResult<DecNum> {
917    if divisor.v.is_zero() {
918        bail!(divisor.span, "divisor must not be zero");
919    }
920
921    dividend
922        .apply2(
923            divisor.v,
924            // `checked_rem` can only overflow on `i64::MIN % -1` which is
925            // mathematically zero.
926            |a, b| Some(DecNum::Int(a.checked_rem(b).unwrap_or(0))),
927            |a, b| Some(DecNum::Float(a % b)),
928            |a, b| a.checked_rem(b).map(DecNum::Decimal),
929        )
930        .ok_or_else(cant_apply_to_decimal_and_float)
931        .at(span)?
932        .ok_or("dividend too small compared to divisor")
933        .at(span)
934}
935
936/// Performs euclidean division of two numbers.
937///
938/// The result of this computation is that of a division rounded to the integer
939/// `{n}` such that the dividend is greater than or equal to `{n}` times
940/// the divisor.
941///
942/// This can error if the resulting number is larger than the maximum value or
943/// smaller than the minimum value for its type.
944///
945/// ```example
946/// #calc.div-euclid(7, 3) \
947/// #calc.div-euclid(7, -3) \
948/// #calc.div-euclid(-7, 3) \
949/// #calc.div-euclid(-7, -3) \
950/// #calc.div-euclid(1.75, 0.5) \
951/// #calc.div-euclid(decimal("1.75"), decimal("0.5"))
952/// ```
953#[func(title = "Euclidean Division")]
954pub fn div_euclid(
955    span: Span,
956    /// The dividend of the division.
957    dividend: DecNum,
958    /// The divisor of the division.
959    divisor: Spanned<DecNum>,
960) -> SourceResult<DecNum> {
961    if divisor.v.is_zero() {
962        bail!(divisor.span, "divisor must not be zero");
963    }
964
965    dividend
966        .apply2(
967            divisor.v,
968            |a, b| a.checked_div_euclid(b).map(DecNum::Int),
969            |a, b| Some(DecNum::Float(a.div_euclid(b))),
970            |a, b| a.checked_div_euclid(b).map(DecNum::Decimal),
971        )
972        .ok_or_else(cant_apply_to_decimal_and_float)
973        .at(span)?
974        .ok_or_else(too_large)
975        .at(span)
976}
977
978/// This calculates the least nonnegative remainder of a division.
979///
980/// Warning: Due to a floating point round-off error, the remainder may equal
981/// the absolute value of the divisor if the dividend is much smaller in
982/// magnitude than the divisor and the dividend is negative. This only applies
983/// for floating point inputs.
984///
985/// In addition, this can error if given a [`decimal`] input and the dividend is
986/// too small in magnitude compared to the divisor.
987///
988/// ```example
989/// #calc.rem-euclid(7, 3) \
990/// #calc.rem-euclid(7, -3) \
991/// #calc.rem-euclid(-7, 3) \
992/// #calc.rem-euclid(-7, -3) \
993/// #calc.rem-euclid(1.75, 0.5) \
994/// #calc.rem-euclid(decimal("1.75"), decimal("0.5"))
995/// ```
996#[func(title = "Euclidean Remainder", keywords = ["modulo", "modulus"])]
997pub fn rem_euclid(
998    span: Span,
999    /// The dividend of the remainder.
1000    dividend: DecNum,
1001    /// The divisor of the remainder.
1002    divisor: Spanned<DecNum>,
1003) -> SourceResult<DecNum> {
1004    if divisor.v.is_zero() {
1005        bail!(divisor.span, "divisor must not be zero");
1006    }
1007
1008    dividend
1009        .apply2(
1010            divisor.v,
1011            // `checked_rem_euclid` can only overflow on `i64::MIN % -1` which
1012            // is mathematically zero.
1013            |a, b| Some(DecNum::Int(a.checked_rem_euclid(b).unwrap_or(0))),
1014            |a, b| Some(DecNum::Float(a.rem_euclid(b))),
1015            |a, b| a.checked_rem_euclid(b).map(DecNum::Decimal),
1016        )
1017        .ok_or_else(cant_apply_to_decimal_and_float)
1018        .at(span)?
1019        .ok_or("dividend too small compared to divisor")
1020        .at(span)
1021}
1022
1023/// Calculates the quotient (floored division) of two numbers.
1024///
1025/// Note that this function will always return an [integer]($int), and will
1026/// error if the resulting number is larger than the maximum 64-bit signed
1027/// integer or smaller than the minimum for that type.
1028///
1029/// ```example
1030/// $ "quo"(a, b) &= floor(a/b) \
1031///   "quo"(14, 5) &= #calc.quo(14, 5) \
1032///   "quo"(3.46, 0.5) &= #calc.quo(3.46, 0.5) $
1033/// ```
1034#[func(title = "Quotient")]
1035pub fn quo(
1036    span: Span,
1037    /// The dividend of the quotient.
1038    dividend: DecNum,
1039    /// The divisor of the quotient.
1040    divisor: Spanned<DecNum>,
1041) -> SourceResult<i64> {
1042    if divisor.v.is_zero() {
1043        bail!(divisor.span, "divisor must not be zero");
1044    }
1045
1046    let divided = dividend
1047        .apply2(
1048            divisor.v,
1049            |a, b| a.checked_div(b).map(DecNum::Int),
1050            |a, b| Some(DecNum::Float(a / b)),
1051            |a, b| a.checked_div(b).map(DecNum::Decimal),
1052        )
1053        .ok_or_else(cant_apply_to_decimal_and_float)
1054        .at(span)?
1055        .ok_or_else(too_large)
1056        .at(span)?;
1057
1058    floor(divided).at(span)
1059}
1060
1061/// Calculates the p-norm of a sequence of values.
1062///
1063/// ```example
1064/// #calc.norm(1, 2, -3, 0.5) \
1065/// #calc.norm(p: 3, 1, 2)
1066/// ```
1067#[func(title = "𝑝-Norm")]
1068pub fn norm(
1069    /// The p value to calculate the p-norm of.
1070    #[named]
1071    #[default(Spanned::new(2.0, Span::detached()))]
1072    p: Spanned<f64>,
1073    /// The sequence of values from which to calculate the p-norm.
1074    /// Returns `0.0` if empty.
1075    #[variadic]
1076    values: Vec<f64>,
1077) -> SourceResult<f64> {
1078    if p.v <= 0.0 {
1079        bail!(p.span, "p must be greater than zero");
1080    }
1081
1082    // Create an iterator over the absolute values.
1083    let abs = values.into_iter().map(f64::abs);
1084
1085    Ok(if p.v.is_infinite() {
1086        // When p is infinity, the p-norm is the maximum of the absolute values.
1087        abs.max_by(|a, b| a.total_cmp(b)).unwrap_or(0.0)
1088    } else {
1089        abs.map(|v| v.powf(p.v)).sum::<f64>().powf(1.0 / p.v)
1090    })
1091}
1092
1093/// A value which can be passed to functions that work with integers and floats.
1094#[derive(Debug, Copy, Clone)]
1095pub enum Num {
1096    Int(i64),
1097    Float(f64),
1098}
1099
1100impl Num {
1101    fn float(self) -> f64 {
1102        match self {
1103            Self::Int(v) => v as f64,
1104            Self::Float(v) => v,
1105        }
1106    }
1107}
1108
1109cast! {
1110    Num,
1111    self => match self {
1112        Self::Int(v) => v.into_value(),
1113        Self::Float(v) => v.into_value(),
1114    },
1115    v: i64 => Self::Int(v),
1116    v: f64 => Self::Float(v),
1117}
1118
1119/// A value which can be passed to functions that work with integers, floats,
1120/// and decimals.
1121#[derive(Debug, Copy, Clone)]
1122pub enum DecNum {
1123    Int(i64),
1124    Float(f64),
1125    Decimal(Decimal),
1126}
1127
1128impl DecNum {
1129    /// Checks if this number is equivalent to zero.
1130    fn is_zero(self) -> bool {
1131        match self {
1132            Self::Int(i) => i == 0,
1133            Self::Float(f) => f == 0.0,
1134            Self::Decimal(d) => d.is_zero(),
1135        }
1136    }
1137
1138    /// If this `DecNum` holds an integer or float, returns a float.
1139    /// Otherwise, returns `None`.
1140    fn float(self) -> Option<f64> {
1141        match self {
1142            Self::Int(i) => Some(i as f64),
1143            Self::Float(f) => Some(f),
1144            Self::Decimal(_) => None,
1145        }
1146    }
1147
1148    /// If this `DecNum` holds an integer or decimal, returns a decimal.
1149    /// Otherwise, returns `None`.
1150    fn decimal(self) -> Option<Decimal> {
1151        match self {
1152            Self::Int(i) => Some(Decimal::from(i)),
1153            Self::Float(_) => None,
1154            Self::Decimal(d) => Some(d),
1155        }
1156    }
1157
1158    /// Tries to apply a function to two decimal or numeric arguments.
1159    ///
1160    /// Fails with `None` if one is a float and the other is a decimal.
1161    fn apply2<T>(
1162        self,
1163        other: Self,
1164        int: impl FnOnce(i64, i64) -> T,
1165        float: impl FnOnce(f64, f64) -> T,
1166        decimal: impl FnOnce(Decimal, Decimal) -> T,
1167    ) -> Option<T> {
1168        match (self, other) {
1169            (Self::Int(a), Self::Int(b)) => Some(int(a, b)),
1170            (Self::Decimal(a), Self::Decimal(b)) => Some(decimal(a, b)),
1171            (Self::Decimal(a), Self::Int(b)) => Some(decimal(a, Decimal::from(b))),
1172            (Self::Int(a), Self::Decimal(b)) => Some(decimal(Decimal::from(a), b)),
1173            (a, b) => Some(float(a.float()?, b.float()?)),
1174        }
1175    }
1176
1177    /// Tries to apply a function to three decimal or numeric arguments.
1178    ///
1179    /// Fails with `None` if one is a float and the other is a decimal.
1180    fn apply3(
1181        self,
1182        other: Self,
1183        third: Self,
1184        int: impl FnOnce(i64, i64, i64) -> i64,
1185        float: impl FnOnce(f64, f64, f64) -> f64,
1186        decimal: impl FnOnce(Decimal, Decimal, Decimal) -> Decimal,
1187    ) -> Option<Self> {
1188        match (self, other, third) {
1189            (Self::Int(a), Self::Int(b), Self::Int(c)) => Some(Self::Int(int(a, b, c))),
1190            (Self::Decimal(a), b, c) => {
1191                Some(Self::Decimal(decimal(a, b.decimal()?, c.decimal()?)))
1192            }
1193            (a, Self::Decimal(b), c) => {
1194                Some(Self::Decimal(decimal(a.decimal()?, b, c.decimal()?)))
1195            }
1196            (a, b, Self::Decimal(c)) => {
1197                Some(Self::Decimal(decimal(a.decimal()?, b.decimal()?, c)))
1198            }
1199            (a, b, c) => Some(Self::Float(float(a.float()?, b.float()?, c.float()?))),
1200        }
1201    }
1202}
1203
1204cast! {
1205    DecNum,
1206    self => match self {
1207        Self::Int(v) => v.into_value(),
1208        Self::Float(v) => v.into_value(),
1209        Self::Decimal(v) => v.into_value(),
1210    },
1211    v: i64 => Self::Int(v),
1212    v: f64 => Self::Float(v),
1213    v: Decimal => Self::Decimal(v),
1214}
1215
1216/// A value that can be passed to a trigonometric function.
1217pub enum AngleLike {
1218    Int(i64),
1219    Float(f64),
1220    Angle(Angle),
1221}
1222
1223cast! {
1224    AngleLike,
1225    v: i64 => Self::Int(v),
1226    v: f64 => Self::Float(v),
1227    v: Angle => Self::Angle(v),
1228}
1229
1230/// The error message when the result is too large to be represented.
1231#[cold]
1232fn too_large() -> &'static str {
1233    "the result is too large"
1234}
1235
1236/// The hinted error message when trying to apply an operation to decimal and
1237/// float operands.
1238#[cold]
1239fn cant_apply_to_decimal_and_float() -> HintedString {
1240    HintedString::new("cannot apply this operation to a decimal and a float".into())
1241        .with_hint(
1242            "if loss of precision is acceptable, explicitly cast the \
1243             decimal to a float with `float(value)`",
1244        )
1245}