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 lang;
|
||||
mod markup;
|
||||
mod math;
|
||||
mod pad;
|
||||
mod page;
|
||||
mod par;
|
||||
@ -21,6 +22,7 @@ pub use basic::*;
|
||||
pub use font::*;
|
||||
pub use lang::*;
|
||||
pub use markup::*;
|
||||
pub use math::*;
|
||||
pub use pad::*;
|
||||
pub use page::*;
|
||||
pub use par::*;
|
||||
@ -69,6 +71,8 @@ pub fn _new() -> Scope {
|
||||
func!("h", h);
|
||||
func!("image", image);
|
||||
func!("lang", lang);
|
||||
func!("max", max);
|
||||
func!("min", min);
|
||||
func!("pad", pad);
|
||||
func!("page", page);
|
||||
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