mirror of
https://github.com/typst/typst
synced 2025-05-20 12:05:27 +08:00
Min and max functions
This commit is contained in:
parent
6b08862b83
commit
72434f0695
60
src/library/math.rs
Normal file
60
src/library/math.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// `min`: The minimum of two values.
|
||||||
|
///
|
||||||
|
/// # Positional parameters
|
||||||
|
/// - Values: variadic, must be comparable.
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
/// The minimum of the sequence of values. For equal elements, the first one is
|
||||||
|
/// returned.
|
||||||
|
pub fn min(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
||||||
|
minmax(ctx, args, Ordering::Less)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `max`: The maximum of two values.
|
||||||
|
///
|
||||||
|
/// # Positional parameters
|
||||||
|
/// - Values: variadic, must be comparable.
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
/// The maximum of the sequence of values. For equal elements, the first one is
|
||||||
|
/// returned.
|
||||||
|
pub fn max(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
|
||||||
|
minmax(ctx, args, Ordering::Greater)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the minimum or maximum of a sequence of values.
|
||||||
|
fn minmax(ctx: &mut EvalContext, args: &mut FuncArgs, which: Ordering) -> Value {
|
||||||
|
let mut values = args.filter::<Value>(ctx);
|
||||||
|
let mut extremum = None;
|
||||||
|
|
||||||
|
for value in &mut values {
|
||||||
|
if let Some(prev) = &extremum {
|
||||||
|
match value.cmp(&prev) {
|
||||||
|
Some(ord) if ord == which => extremum = Some(value),
|
||||||
|
Some(_) => {}
|
||||||
|
None => {
|
||||||
|
drop(values);
|
||||||
|
ctx.diag(error!(
|
||||||
|
args.span,
|
||||||
|
"cannot compare {} with {}",
|
||||||
|
prev.type_name(),
|
||||||
|
value.type_name(),
|
||||||
|
));
|
||||||
|
return Value::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
extremum = Some(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(values);
|
||||||
|
extremum.unwrap_or_else(|| {
|
||||||
|
args.require::<Value>(ctx, "value");
|
||||||
|
Value::Error
|
||||||
|
})
|
||||||
|
}
|
@ -9,6 +9,7 @@ mod font;
|
|||||||
mod image;
|
mod image;
|
||||||
mod lang;
|
mod lang;
|
||||||
mod markup;
|
mod markup;
|
||||||
|
mod math;
|
||||||
mod pad;
|
mod pad;
|
||||||
mod page;
|
mod page;
|
||||||
mod par;
|
mod par;
|
||||||
@ -21,6 +22,7 @@ pub use basic::*;
|
|||||||
pub use font::*;
|
pub use font::*;
|
||||||
pub use lang::*;
|
pub use lang::*;
|
||||||
pub use markup::*;
|
pub use markup::*;
|
||||||
|
pub use math::*;
|
||||||
pub use pad::*;
|
pub use pad::*;
|
||||||
pub use page::*;
|
pub use page::*;
|
||||||
pub use par::*;
|
pub use par::*;
|
||||||
@ -69,6 +71,8 @@ pub fn _new() -> Scope {
|
|||||||
func!("h", h);
|
func!("h", h);
|
||||||
func!("image", image);
|
func!("image", image);
|
||||||
func!("lang", lang);
|
func!("lang", lang);
|
||||||
|
func!("max", max);
|
||||||
|
func!("min", min);
|
||||||
func!("pad", pad);
|
func!("pad", pad);
|
||||||
func!("page", page);
|
func!("page", page);
|
||||||
func!("pagebreak", pagebreak);
|
func!("pagebreak", pagebreak);
|
||||||
|
15
tests/typ/library/math.typ
Normal file
15
tests/typ/library/math.typ
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Test math functions.
|
||||||
|
// Ref: false
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test `min` and `max` functions.
|
||||||
|
#test(min(2, -4), -4)
|
||||||
|
#test(min(3.5, 1e2, -0.1, 3), -0.1)
|
||||||
|
#test(max(-3, 11), 11)
|
||||||
|
#test(min("hi"), "hi")
|
||||||
|
|
||||||
|
// Error: 6 missing argument: value
|
||||||
|
#min()
|
||||||
|
|
||||||
|
// Error: 11-18 cannot compare integer with string
|
||||||
|
#test(min(1, "hi"), error)
|
Loading…
x
Reference in New Issue
Block a user