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::{bail, At, HintedString, SourceResult, StrResult};
11use crate::foundations::{cast, func, ops, Decimal, IntoValue, Module, Scope, Value};
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 arcsine 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 an 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/// ```example
568/// #calc.gcd(7, 42)
569/// ```
570#[func(title = "Greatest Common Divisor")]
571pub fn gcd(
572    /// The first integer.
573    a: i64,
574    /// The second integer.
575    b: i64,
576) -> i64 {
577    let (mut a, mut b) = (a, b);
578    while b != 0 {
579        let temp = b;
580        b = a % b;
581        a = temp;
582    }
583
584    a.abs()
585}
586
587/// Calculates the least common multiple of two integers.
588///
589/// ```example
590/// #calc.lcm(96, 13)
591/// ```
592#[func(title = "Least Common Multiple")]
593pub fn lcm(
594    /// The first integer.
595    a: i64,
596    /// The second integer.
597    b: i64,
598) -> StrResult<i64> {
599    if a == b {
600        return Ok(a.abs());
601    }
602
603    Ok(a.checked_div(gcd(a, b))
604        .and_then(|gcd| gcd.checked_mul(b))
605        .map(|v| v.abs())
606        .ok_or_else(too_large)?)
607}
608
609/// Rounds a number down to the nearest integer.
610///
611/// If the number is already an integer, it is returned unchanged.
612///
613/// Note that this function will always return an [integer]($int), and will
614/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
615/// 64-bit signed integer or smaller than the minimum for that type.
616///
617/// ```example
618/// #calc.floor(500.1)
619/// #assert(calc.floor(3) == 3)
620/// #assert(calc.floor(3.14) == 3)
621/// #assert(calc.floor(decimal("-3.14")) == -4)
622/// ```
623#[func]
624pub fn floor(
625    /// The number to round down.
626    value: DecNum,
627) -> StrResult<i64> {
628    match value {
629        DecNum::Int(n) => Ok(n),
630        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.floor())
631            .map_err(|_| too_large())?),
632        DecNum::Decimal(n) => Ok(i64::try_from(n.floor()).map_err(|_| too_large())?),
633    }
634}
635
636/// Rounds a number up to the nearest integer.
637///
638/// If the number is already an integer, it is returned unchanged.
639///
640/// Note that this function will always return an [integer]($int), and will
641/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
642/// 64-bit signed integer or smaller than the minimum for that type.
643///
644/// ```example
645/// #calc.ceil(500.1)
646/// #assert(calc.ceil(3) == 3)
647/// #assert(calc.ceil(3.14) == 4)
648/// #assert(calc.ceil(decimal("-3.14")) == -3)
649/// ```
650#[func]
651pub fn ceil(
652    /// The number to round up.
653    value: DecNum,
654) -> StrResult<i64> {
655    match value {
656        DecNum::Int(n) => Ok(n),
657        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.ceil())
658            .map_err(|_| too_large())?),
659        DecNum::Decimal(n) => Ok(i64::try_from(n.ceil()).map_err(|_| too_large())?),
660    }
661}
662
663/// Returns the integer part of a number.
664///
665/// If the number is already an integer, it is returned unchanged.
666///
667/// Note that this function will always return an [integer]($int), and will
668/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
669/// 64-bit signed integer or smaller than the minimum for that type.
670///
671/// ```example
672/// #calc.trunc(15.9)
673/// #assert(calc.trunc(3) == 3)
674/// #assert(calc.trunc(-3.7) == -3)
675/// #assert(calc.trunc(decimal("8493.12949582390")) == 8493)
676/// ```
677#[func(title = "Truncate")]
678pub fn trunc(
679    /// The number to truncate.
680    value: DecNum,
681) -> StrResult<i64> {
682    match value {
683        DecNum::Int(n) => Ok(n),
684        DecNum::Float(n) => Ok(crate::foundations::convert_float_to_int(n.trunc())
685            .map_err(|_| too_large())?),
686        DecNum::Decimal(n) => Ok(i64::try_from(n.trunc()).map_err(|_| too_large())?),
687    }
688}
689
690/// Returns the fractional part of a number.
691///
692/// If the number is an integer, returns `0`.
693///
694/// ```example
695/// #calc.fract(-3.1)
696/// #assert(calc.fract(3) == 0)
697/// #assert(calc.fract(decimal("234.23949211")) == decimal("0.23949211"))
698/// ```
699#[func(title = "Fractional")]
700pub fn fract(
701    /// The number to truncate.
702    value: DecNum,
703) -> DecNum {
704    match value {
705        DecNum::Int(_) => DecNum::Int(0),
706        DecNum::Float(n) => DecNum::Float(n.fract()),
707        DecNum::Decimal(n) => DecNum::Decimal(n.fract()),
708    }
709}
710
711/// Rounds a number to the nearest integer away from zero.
712///
713/// Optionally, a number of decimal places can be specified.
714///
715/// If the number of digits is negative, its absolute value will indicate the
716/// amount of significant integer digits to remove before the decimal point.
717///
718/// Note that this function will return the same type as the operand. That is,
719/// applying `round` to a [`float`] will return a `float`, and to a [`decimal`],
720/// another `decimal`. You may explicitly convert the output of this function to
721/// an integer with [`int`], but note that such a conversion will error if the
722/// `float` or `decimal` is larger than the maximum 64-bit signed integer or
723/// smaller than the minimum integer.
724///
725/// In addition, this function can error if there is an attempt to round beyond
726/// the maximum or minimum integer or `decimal`. If the number is a `float`,
727/// such an attempt will cause `{float.inf}` or `{-float.inf}` to be returned
728/// for maximum and minimum respectively.
729///
730/// ```example
731/// #calc.round(3.1415, digits: 2)
732/// #assert(calc.round(3) == 3)
733/// #assert(calc.round(3.14) == 3)
734/// #assert(calc.round(3.5) == 4.0)
735/// #assert(calc.round(3333.45, digits: -2) == 3300.0)
736/// #assert(calc.round(-48953.45, digits: -3) == -49000.0)
737/// #assert(calc.round(3333, digits: -2) == 3300)
738/// #assert(calc.round(-48953, digits: -3) == -49000)
739/// #assert(calc.round(decimal("-6.5")) == decimal("-7"))
740/// #assert(calc.round(decimal("7.123456789"), digits: 6) == decimal("7.123457"))
741/// #assert(calc.round(decimal("3333.45"), digits: -2) == decimal("3300"))
742/// #assert(calc.round(decimal("-48953.45"), digits: -3) == decimal("-49000"))
743/// ```
744#[func]
745pub fn round(
746    /// The number to round.
747    value: DecNum,
748    /// If positive, the number of decimal places.
749    ///
750    /// If negative, the number of significant integer digits that should be
751    /// removed before the decimal point.
752    #[named]
753    #[default(0)]
754    digits: i64,
755) -> StrResult<DecNum> {
756    match value {
757        DecNum::Int(n) => Ok(DecNum::Int(
758            round_int_with_precision(n, digits.saturating_as::<i16>())
759                .ok_or_else(too_large)?,
760        )),
761        DecNum::Float(n) => {
762            Ok(DecNum::Float(round_with_precision(n, digits.saturating_as::<i16>())))
763        }
764        DecNum::Decimal(n) => Ok(DecNum::Decimal(
765            n.round(digits.saturating_as::<i32>()).ok_or_else(too_large)?,
766        )),
767    }
768}
769
770/// Clamps a number between a minimum and maximum value.
771///
772/// ```example
773/// #calc.clamp(5, 0, 4)
774/// #assert(calc.clamp(5, 0, 10) == 5)
775/// #assert(calc.clamp(5, 6, 10) == 6)
776/// #assert(calc.clamp(decimal("5.45"), 2, decimal("45.9")) == decimal("5.45"))
777/// #assert(calc.clamp(decimal("5.45"), decimal("6.75"), 12) == decimal("6.75"))
778/// ```
779#[func]
780pub fn clamp(
781    span: Span,
782    /// The number to clamp.
783    value: DecNum,
784    /// The inclusive minimum value.
785    min: DecNum,
786    /// The inclusive maximum value.
787    max: Spanned<DecNum>,
788) -> SourceResult<DecNum> {
789    // Ignore if there are incompatible types (decimal and float) since that
790    // will cause `apply3` below to error before calling clamp, avoiding a
791    // panic.
792    if min
793        .apply2(max.v, |min, max| max < min, |min, max| max < min, |min, max| max < min)
794        .unwrap_or(false)
795    {
796        bail!(max.span, "max must be greater than or equal to min")
797    }
798
799    value
800        .apply3(min, max.v, i64::clamp, f64::clamp, Decimal::clamp)
801        .ok_or_else(cant_apply_to_decimal_and_float)
802        .at(span)
803}
804
805/// Determines the minimum of a sequence of values.
806///
807/// ```example
808/// #calc.min(1, -3, -5, 20, 3, 6) \
809/// #calc.min("typst", "is", "cool")
810/// ```
811#[func(title = "Minimum")]
812pub fn min(
813    span: Span,
814    /// The sequence of values from which to extract the minimum.
815    /// Must not be empty.
816    #[variadic]
817    values: Vec<Spanned<Value>>,
818) -> SourceResult<Value> {
819    minmax(span, values, Ordering::Less)
820}
821
822/// Determines the maximum of a sequence of values.
823///
824/// ```example
825/// #calc.max(1, -3, -5, 20, 3, 6) \
826/// #calc.max("typst", "is", "cool")
827/// ```
828#[func(title = "Maximum")]
829pub fn max(
830    span: Span,
831    /// The sequence of values from which to extract the maximum.
832    /// Must not be empty.
833    #[variadic]
834    values: Vec<Spanned<Value>>,
835) -> SourceResult<Value> {
836    minmax(span, values, Ordering::Greater)
837}
838
839/// Find the minimum or maximum of a sequence of values.
840fn minmax(
841    span: Span,
842    values: Vec<Spanned<Value>>,
843    goal: Ordering,
844) -> SourceResult<Value> {
845    let mut iter = values.into_iter();
846    let Some(Spanned { v: mut extremum, .. }) = iter.next() else {
847        bail!(span, "expected at least one value");
848    };
849
850    for Spanned { v, span } in iter {
851        let ordering = ops::compare(&v, &extremum).at(span)?;
852        if ordering == goal {
853            extremum = v;
854        }
855    }
856
857    Ok(extremum)
858}
859
860/// Determines whether an integer is even.
861///
862/// ```example
863/// #calc.even(4) \
864/// #calc.even(5) \
865/// #range(10).filter(calc.even)
866/// ```
867#[func]
868pub fn even(
869    /// The number to check for evenness.
870    value: i64,
871) -> bool {
872    value % 2 == 0
873}
874
875/// Determines whether an integer is odd.
876///
877/// ```example
878/// #calc.odd(4) \
879/// #calc.odd(5) \
880/// #range(10).filter(calc.odd)
881/// ```
882#[func]
883pub fn odd(
884    /// The number to check for oddness.
885    value: i64,
886) -> bool {
887    value % 2 != 0
888}
889
890/// Calculates the remainder of two numbers.
891///
892/// The value `calc.rem(x, y)` always has the same sign as `x`, and is smaller
893/// in magnitude than `y`.
894///
895/// This can error if given a [`decimal`] input and the dividend is too small in
896/// magnitude compared to the divisor.
897///
898/// ```example
899/// #calc.rem(7, 3) \
900/// #calc.rem(7, -3) \
901/// #calc.rem(-7, 3) \
902/// #calc.rem(-7, -3) \
903/// #calc.rem(1.75, 0.5)
904/// ```
905#[func(title = "Remainder")]
906pub fn rem(
907    span: Span,
908    /// The dividend of the remainder.
909    dividend: DecNum,
910    /// The divisor of the remainder.
911    divisor: Spanned<DecNum>,
912) -> SourceResult<DecNum> {
913    if divisor.v.is_zero() {
914        bail!(divisor.span, "divisor must not be zero");
915    }
916
917    dividend
918        .apply2(
919            divisor.v,
920            |a, b| Some(DecNum::Int(a % b)),
921            |a, b| Some(DecNum::Float(a % b)),
922            |a, b| a.checked_rem(b).map(DecNum::Decimal),
923        )
924        .ok_or_else(cant_apply_to_decimal_and_float)
925        .at(span)?
926        .ok_or("dividend too small compared to divisor")
927        .at(span)
928}
929
930/// Performs euclidean division of two numbers.
931///
932/// The result of this computation is that of a division rounded to the integer
933/// `{n}` such that the dividend is greater than or equal to `{n}` times the divisor.
934///
935/// ```example
936/// #calc.div-euclid(7, 3) \
937/// #calc.div-euclid(7, -3) \
938/// #calc.div-euclid(-7, 3) \
939/// #calc.div-euclid(-7, -3) \
940/// #calc.div-euclid(1.75, 0.5) \
941/// #calc.div-euclid(decimal("1.75"), decimal("0.5"))
942/// ```
943#[func(title = "Euclidean Division")]
944pub fn div_euclid(
945    span: Span,
946    /// The dividend of the division.
947    dividend: DecNum,
948    /// The divisor of the division.
949    divisor: Spanned<DecNum>,
950) -> SourceResult<DecNum> {
951    if divisor.v.is_zero() {
952        bail!(divisor.span, "divisor must not be zero");
953    }
954
955    dividend
956        .apply2(
957            divisor.v,
958            |a, b| Some(DecNum::Int(a.div_euclid(b))),
959            |a, b| Some(DecNum::Float(a.div_euclid(b))),
960            |a, b| a.checked_div_euclid(b).map(DecNum::Decimal),
961        )
962        .ok_or_else(cant_apply_to_decimal_and_float)
963        .at(span)?
964        .ok_or_else(too_large)
965        .at(span)
966}
967
968/// This calculates the least nonnegative remainder of a division.
969///
970/// Warning: Due to a floating point round-off error, the remainder may equal
971/// the absolute value of the divisor if the dividend is much smaller in
972/// magnitude than the divisor and the dividend is negative. This only applies
973/// for floating point inputs.
974///
975/// In addition, this can error if given a [`decimal`] input and the dividend is
976/// too small in magnitude compared to the divisor.
977///
978/// ```example
979/// #calc.rem-euclid(7, 3) \
980/// #calc.rem-euclid(7, -3) \
981/// #calc.rem-euclid(-7, 3) \
982/// #calc.rem-euclid(-7, -3) \
983/// #calc.rem-euclid(1.75, 0.5) \
984/// #calc.rem-euclid(decimal("1.75"), decimal("0.5"))
985/// ```
986#[func(title = "Euclidean Remainder", keywords = ["modulo", "modulus"])]
987pub fn rem_euclid(
988    span: Span,
989    /// The dividend of the remainder.
990    dividend: DecNum,
991    /// The divisor of the remainder.
992    divisor: Spanned<DecNum>,
993) -> SourceResult<DecNum> {
994    if divisor.v.is_zero() {
995        bail!(divisor.span, "divisor must not be zero");
996    }
997
998    dividend
999        .apply2(
1000            divisor.v,
1001            |a, b| Some(DecNum::Int(a.rem_euclid(b))),
1002            |a, b| Some(DecNum::Float(a.rem_euclid(b))),
1003            |a, b| a.checked_rem_euclid(b).map(DecNum::Decimal),
1004        )
1005        .ok_or_else(cant_apply_to_decimal_and_float)
1006        .at(span)?
1007        .ok_or("dividend too small compared to divisor")
1008        .at(span)
1009}
1010
1011/// Calculates the quotient (floored division) of two numbers.
1012///
1013/// Note that this function will always return an [integer]($int), and will
1014/// error if the resulting [`float`] or [`decimal`] is larger than the maximum
1015/// 64-bit signed integer or smaller than the minimum for that type.
1016///
1017/// ```example
1018/// $ "quo"(a, b) &= floor(a/b) \
1019///   "quo"(14, 5) &= #calc.quo(14, 5) \
1020///   "quo"(3.46, 0.5) &= #calc.quo(3.46, 0.5) $
1021/// ```
1022#[func(title = "Quotient")]
1023pub fn quo(
1024    span: Span,
1025    /// The dividend of the quotient.
1026    dividend: DecNum,
1027    /// The divisor of the quotient.
1028    divisor: Spanned<DecNum>,
1029) -> SourceResult<i64> {
1030    if divisor.v.is_zero() {
1031        bail!(divisor.span, "divisor must not be zero");
1032    }
1033
1034    let divided = dividend
1035        .apply2(
1036            divisor.v,
1037            |a, b| Some(DecNum::Int(a / b)),
1038            |a, b| Some(DecNum::Float(a / b)),
1039            |a, b| a.checked_div(b).map(DecNum::Decimal),
1040        )
1041        .ok_or_else(cant_apply_to_decimal_and_float)
1042        .at(span)?
1043        .ok_or_else(too_large)
1044        .at(span)?;
1045
1046    floor(divided).at(span)
1047}
1048
1049/// Calculates the p-norm of a sequence of values.
1050///
1051/// ```example
1052/// #calc.norm(1, 2, -3, 0.5) \
1053/// #calc.norm(p: 3, 1, 2)
1054/// ```
1055#[func(title = "𝑝-Norm")]
1056pub fn norm(
1057    /// The p value to calculate the p-norm of.
1058    #[named]
1059    #[default(Spanned::new(2.0, Span::detached()))]
1060    p: Spanned<f64>,
1061    /// The sequence of values from which to calculate the p-norm.
1062    /// Returns `0.0` if empty.
1063    #[variadic]
1064    values: Vec<f64>,
1065) -> SourceResult<f64> {
1066    if p.v <= 0.0 {
1067        bail!(p.span, "p must be greater than zero");
1068    }
1069
1070    // Create an iterator over the absolute values.
1071    let abs = values.into_iter().map(f64::abs);
1072
1073    Ok(if p.v.is_infinite() {
1074        // When p is infinity, the p-norm is the maximum of the absolute values.
1075        abs.max_by(|a, b| a.total_cmp(b)).unwrap_or(0.0)
1076    } else {
1077        abs.map(|v| v.powf(p.v)).sum::<f64>().powf(1.0 / p.v)
1078    })
1079}
1080
1081/// A value which can be passed to functions that work with integers and floats.
1082#[derive(Debug, Copy, Clone)]
1083pub enum Num {
1084    Int(i64),
1085    Float(f64),
1086}
1087
1088impl Num {
1089    fn float(self) -> f64 {
1090        match self {
1091            Self::Int(v) => v as f64,
1092            Self::Float(v) => v,
1093        }
1094    }
1095}
1096
1097cast! {
1098    Num,
1099    self => match self {
1100        Self::Int(v) => v.into_value(),
1101        Self::Float(v) => v.into_value(),
1102    },
1103    v: i64 => Self::Int(v),
1104    v: f64 => Self::Float(v),
1105}
1106
1107/// A value which can be passed to functions that work with integers, floats,
1108/// and decimals.
1109#[derive(Debug, Copy, Clone)]
1110pub enum DecNum {
1111    Int(i64),
1112    Float(f64),
1113    Decimal(Decimal),
1114}
1115
1116impl DecNum {
1117    /// Checks if this number is equivalent to zero.
1118    fn is_zero(self) -> bool {
1119        match self {
1120            Self::Int(i) => i == 0,
1121            Self::Float(f) => f == 0.0,
1122            Self::Decimal(d) => d.is_zero(),
1123        }
1124    }
1125
1126    /// If this `DecNum` holds an integer or float, returns a float.
1127    /// Otherwise, returns `None`.
1128    fn float(self) -> Option<f64> {
1129        match self {
1130            Self::Int(i) => Some(i as f64),
1131            Self::Float(f) => Some(f),
1132            Self::Decimal(_) => None,
1133        }
1134    }
1135
1136    /// If this `DecNum` holds an integer or decimal, returns a decimal.
1137    /// Otherwise, returns `None`.
1138    fn decimal(self) -> Option<Decimal> {
1139        match self {
1140            Self::Int(i) => Some(Decimal::from(i)),
1141            Self::Float(_) => None,
1142            Self::Decimal(d) => Some(d),
1143        }
1144    }
1145
1146    /// Tries to apply a function to two decimal or numeric arguments.
1147    ///
1148    /// Fails with `None` if one is a float and the other is a decimal.
1149    fn apply2<T>(
1150        self,
1151        other: Self,
1152        int: impl FnOnce(i64, i64) -> T,
1153        float: impl FnOnce(f64, f64) -> T,
1154        decimal: impl FnOnce(Decimal, Decimal) -> T,
1155    ) -> Option<T> {
1156        match (self, other) {
1157            (Self::Int(a), Self::Int(b)) => Some(int(a, b)),
1158            (Self::Decimal(a), Self::Decimal(b)) => Some(decimal(a, b)),
1159            (Self::Decimal(a), Self::Int(b)) => Some(decimal(a, Decimal::from(b))),
1160            (Self::Int(a), Self::Decimal(b)) => Some(decimal(Decimal::from(a), b)),
1161            (a, b) => Some(float(a.float()?, b.float()?)),
1162        }
1163    }
1164
1165    /// Tries to apply a function to three decimal or numeric arguments.
1166    ///
1167    /// Fails with `None` if one is a float and the other is a decimal.
1168    fn apply3(
1169        self,
1170        other: Self,
1171        third: Self,
1172        int: impl FnOnce(i64, i64, i64) -> i64,
1173        float: impl FnOnce(f64, f64, f64) -> f64,
1174        decimal: impl FnOnce(Decimal, Decimal, Decimal) -> Decimal,
1175    ) -> Option<Self> {
1176        match (self, other, third) {
1177            (Self::Int(a), Self::Int(b), Self::Int(c)) => Some(Self::Int(int(a, b, c))),
1178            (Self::Decimal(a), b, c) => {
1179                Some(Self::Decimal(decimal(a, b.decimal()?, c.decimal()?)))
1180            }
1181            (a, Self::Decimal(b), c) => {
1182                Some(Self::Decimal(decimal(a.decimal()?, b, c.decimal()?)))
1183            }
1184            (a, b, Self::Decimal(c)) => {
1185                Some(Self::Decimal(decimal(a.decimal()?, b.decimal()?, c)))
1186            }
1187            (a, b, c) => Some(Self::Float(float(a.float()?, b.float()?, c.float()?))),
1188        }
1189    }
1190}
1191
1192cast! {
1193    DecNum,
1194    self => match self {
1195        Self::Int(v) => v.into_value(),
1196        Self::Float(v) => v.into_value(),
1197        Self::Decimal(v) => v.into_value(),
1198    },
1199    v: i64 => Self::Int(v),
1200    v: f64 => Self::Float(v),
1201    v: Decimal => Self::Decimal(v),
1202}
1203
1204/// A value that can be passed to a trigonometric function.
1205pub enum AngleLike {
1206    Int(i64),
1207    Float(f64),
1208    Angle(Angle),
1209}
1210
1211cast! {
1212    AngleLike,
1213    v: i64 => Self::Int(v),
1214    v: f64 => Self::Float(v),
1215    v: Angle => Self::Angle(v),
1216}
1217
1218/// The error message when the result is too large to be represented.
1219#[cold]
1220fn too_large() -> &'static str {
1221    "the result is too large"
1222}
1223
1224/// The hinted error message when trying to apply an operation to decimal and
1225/// float operands.
1226#[cold]
1227fn cant_apply_to_decimal_and_float() -> HintedString {
1228    HintedString::new("cannot apply this operation to a decimal and a float".into())
1229        .with_hint(
1230            "if loss of precision is acceptable, explicitly cast the \
1231             decimal to a float with `float(value)`",
1232        )
1233}