summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library/math.rs60
-rw-r--r--src/library/mod.rs4
2 files changed, 64 insertions, 0 deletions
diff --git a/src/library/math.rs b/src/library/math.rs
new file mode 100644
index 00000000..3392f664
--- /dev/null
+++ b/src/library/math.rs
@@ -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
+ })
+}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 5018f0b4..2cfe02ba 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -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);