summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-08-30 16:59:09 +0200
committerLaurenz <laurmaedje@gmail.com>2021-08-30 16:59:09 +0200
commitee84bf74083f5b9cc88a2a0a968dc905b1eef22c (patch)
treed2756f462ee242c328c526d2a65de4105830cb27
parentff25573224400673d08b31e576d5a0d87751dbe1 (diff)
Add abs() function
-rw-r--r--src/geom/angle.rs5
-rw-r--r--src/geom/fr.rs5
-rw-r--r--src/geom/length.rs5
-rw-r--r--src/geom/relative.rs5
-rw-r--r--src/library/mod.rs1
-rw-r--r--src/library/utility.rs15
-rw-r--r--tests/typ/utility/math.typ18
7 files changed, 54 insertions, 0 deletions
diff --git a/src/geom/angle.rs b/src/geom/angle.rs
index 023b1d98..b6fa3f41 100644
--- a/src/geom/angle.rs
+++ b/src/geom/angle.rs
@@ -50,6 +50,11 @@ impl Angle {
pub fn to_unit(self, unit: AngularUnit) -> f64 {
self.to_raw() / unit.raw_scale()
}
+
+ /// The absolute value of the this angle.
+ pub fn abs(self) -> Self {
+ Self::raw(self.to_raw().abs())
+ }
}
impl Debug for Angle {
diff --git a/src/geom/fr.rs b/src/geom/fr.rs
index ed0c8329..5f3e5534 100644
--- a/src/geom/fr.rs
+++ b/src/geom/fr.rs
@@ -29,6 +29,11 @@ impl Fractional {
pub fn is_zero(self) -> bool {
self.0 == 0.0
}
+
+ /// The absolute value of the this fractional.
+ pub fn abs(self) -> Self {
+ Self::new(self.get().abs())
+ }
}
impl Debug for Fractional {
diff --git a/src/geom/length.rs b/src/geom/length.rs
index f8484f75..b9eb7b75 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -92,6 +92,11 @@ impl Length {
self.0.into_inner().is_infinite()
}
+ /// The absolute value of the this length.
+ pub fn abs(self) -> Self {
+ Self::raw(self.to_raw().abs())
+ }
+
/// The minimum of this and another length.
pub fn min(self, other: Self) -> Self {
Self(self.0.min(other.0))
diff --git a/src/geom/relative.rs b/src/geom/relative.rs
index 056af206..9122af84 100644
--- a/src/geom/relative.rs
+++ b/src/geom/relative.rs
@@ -42,6 +42,11 @@ impl Relative {
pub fn is_zero(self) -> bool {
self.0 == 0.0
}
+
+ /// The absolute value of the this relative.
+ pub fn abs(self) -> Self {
+ Self::new(self.get().abs())
+ }
}
impl Debug for Relative {
diff --git a/src/library/mod.rs b/src/library/mod.rs
index d02c9608..ca99d43b 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -61,6 +61,7 @@ pub fn new() -> Scope {
std.def_func("repr", repr);
std.def_func("len", len);
std.def_func("rgb", rgb);
+ std.def_func("abs", abs);
std.def_func("min", min);
std.def_func("max", max);
std.def_func("lower", lower);
diff --git a/src/library/utility.rs b/src/library/utility.rs
index b26ed154..0ece88ac 100644
--- a/src/library/utility.rs
+++ b/src/library/utility.rs
@@ -45,6 +45,21 @@ pub fn rgb(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
)))
}
+/// `abs`: The absolute value of a numeric value.
+pub fn abs(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
+ let Spanned { v, span } = args.expect("numeric value")?;
+ Ok(match v {
+ Value::Int(v) => Value::Int(v.abs()),
+ Value::Float(v) => Value::Float(v.abs()),
+ Value::Length(v) => Value::Length(v.abs()),
+ Value::Angle(v) => Value::Angle(v.abs()),
+ Value::Relative(v) => Value::Relative(v.abs()),
+ Value::Fractional(v) => Value::Fractional(v.abs()),
+ Value::Linear(_) => bail!(span, "cannot take absolute value of a linear"),
+ _ => bail!(span, "expected numeric value"),
+ })
+}
+
/// `min`: The minimum of a sequence of values.
pub fn min(_: &mut EvalContext, args: &mut Arguments) -> TypResult<Value> {
minmax(args, Ordering::Less)
diff --git a/tests/typ/utility/math.typ b/tests/typ/utility/math.typ
index 05c3639f..aeb0d6ad 100644
--- a/tests/typ/utility/math.typ
+++ b/tests/typ/utility/math.typ
@@ -2,6 +2,24 @@
// Ref: false
---
+// Test `abs` function.
+#test(abs(-3), 3)
+#test(abs(3), 3)
+#test(abs(-0.0), 0.0)
+#test(abs(0.0), -0.0)
+#test(abs(-3.14), 3.14)
+#test(abs(-12pt), 12pt)
+#test(abs(50%), 50%)
+
+---
+// Error: 6-16 cannot take absolute value of a linear
+#abs(10pt + 50%)
+
+---
+// Error: 6-17 expected numeric value
+#abs("no number")
+
+---
// Test `min` and `max` functions.
#test(min(2, -4), -4)
#test(min(3.5, 1e2, -0.1, 3), -0.1)