Skip to content

Commit

Permalink
added math function clamp
Browse files Browse the repository at this point in the history
  • Loading branch information
juerg committed Mar 12, 2024
1 parent 8702ff0 commit 819d9cf
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file.

### Added

- ...
- math function `clamp`



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public DocSection section() {
arithmetic.addItem(diBuilder.getDocItem("dec"));
arithmetic.addItem(diBuilder.getDocItem("min"));
arithmetic.addItem(diBuilder.getDocItem("max"));
arithmetic.addItem(diBuilder.getDocItem("clamp"));
arithmetic.addItem(diBuilder.getDocItem("mod"));
arithmetic.addItem(diBuilder.getDocItem("mod-floor"));
arithmetic.addItem(diBuilder.getDocItem("abs"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ public VncVal apply(final VncList args) {
"(max 1.0)", "(max 1.0 2.0)", "(max 4.0 3.0 2.0 1.0)",
"(max 1.0M)", "(max 1.0M 2.0M)", "(max 4.0M 3.0M 2.0M 1.0M)",
"(max 1.0M 2)")
.seeAlso("min")
.seeAlso("min", "clamp")
.build()
) {
@Override
Expand Down Expand Up @@ -568,7 +568,7 @@ else if (op != Nil){
"(min 1.0)", "(min 1.0 2.0)", "(min 4.0 3.0 2.0 1.0)",
"(min 1.0M)", "(min 1.0M 2.0M)", "(min 4.0M 3.0M 2.0M 1.0M)",
"(min 1.0M 2)")
.seeAlso("max")
.seeAlso("max", "clamp")
.build()
) {
@Override
Expand Down Expand Up @@ -597,6 +597,58 @@ else if (op != Nil) {
private static final long serialVersionUID = -1848883965231344442L;
};

public static VncFunction clamp =
new VncFunction(
"clamp",
VncFunction
.meta()
.arglists("(clamp x min max)")
.doc(
"Restricts a given value between a lower and upper bound. " +
"In this way, it acts like a combination of the `min` and `max` functions.")
.examples(
"(clamp 1 10 20)",
"(clamp 1I 10I 20I)",
"(clamp 1.0 10.0 20.0)")
.seeAlso("min", "max")
.build()
) {
@Override
public VncVal apply(final VncList args) {
ArityExceptions.assertArity(this, args, 3);

final VncVal v = args.first();
final VncVal min = args.second();
final VncVal max = args.third();

if (!Types.isVncNumber(v)) {
throw new VncException(String.format(
"Function 'clamp' does not allow %s as value",
Types.getType(v)));
}
if (!Types.isVncNumber(min)) {
throw new VncException(String.format(
"Function 'clamp' does not allow %s as min value",
Types.getType(min)));
}
if (!Types.isVncNumber(max)) {
throw new VncException(String.format(
"Function 'clamp' does not allow %s as max value",
Types.getType(max)));
}

if (v.compareTo(min) < 0) {
return min;
}
else if (v.compareTo(max) > 0) {
return max;
}
return v;
}

private static final long serialVersionUID = -1848883965231344442L;
};

public static VncFunction abs =
new VncFunction(
"abs",
Expand Down Expand Up @@ -2166,6 +2218,7 @@ private static VncVal median(final VncList sortedData) {
.add(sgn)
.add(min)
.add(max)
.add(clamp)
.add(negate)
.add(floor)
.add(ceil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,51 @@ public void test_min() {
assertEquals(new BigDecimal("3.0"), venice.eval("(min 4N 3.0M)"));
}

@Test
public void test_clamp() {
final Venice venice = new Venice();

// Integer
assertEquals(Integer.valueOf(5), venice.eval("(clamp 4I 5I 8I)"));
assertEquals(Integer.valueOf(5), venice.eval("(clamp 5I 5I 8I)"));
assertEquals(Integer.valueOf(6), venice.eval("(clamp 6I 5I 8I)"));
assertEquals(Integer.valueOf(7), venice.eval("(clamp 7I 5I 8I)"));
assertEquals(Integer.valueOf(8), venice.eval("(clamp 8I 5I 8I)"));
assertEquals(Integer.valueOf(8), venice.eval("(clamp 9I 5I 8I)"));

// Long
assertEquals(Long.valueOf(5), venice.eval("(clamp 4 5 8)"));
assertEquals(Long.valueOf(5), venice.eval("(clamp 5 5 8)"));
assertEquals(Long.valueOf(6), venice.eval("(clamp 6 5 8)"));
assertEquals(Long.valueOf(7), venice.eval("(clamp 7 5 8)"));
assertEquals(Long.valueOf(8), venice.eval("(clamp 8 5 8)"));
assertEquals(Long.valueOf(8), venice.eval("(clamp 9 5 8)"));

// Double
assertEquals(Double.valueOf(5.0D), venice.eval("(clamp 4.0 5.0 8.0)"));
assertEquals(Double.valueOf(5.0D), venice.eval("(clamp 5.0 5.0 8.0)"));
assertEquals(Double.valueOf(6.0D), venice.eval("(clamp 6.0 5.0 8.0)"));
assertEquals(Double.valueOf(7.0D), venice.eval("(clamp 7.0 5.0 8.0)"));
assertEquals(Double.valueOf(8.0D), venice.eval("(clamp 8.0 5.0 8.0)"));
assertEquals(Double.valueOf(8.0D), venice.eval("(clamp 9.0 5.0 8.0)"));

// Decimal
assertEquals(new BigDecimal("5.0"), venice.eval("(clamp 4.0M 5.0M 8.0M)"));
assertEquals(new BigDecimal("5.0"), venice.eval("(clamp 5.0M 5.0M 8.0M)"));
assertEquals(new BigDecimal("6.0"), venice.eval("(clamp 6.0M 5.0M 8.0M)"));
assertEquals(new BigDecimal("7.0"), venice.eval("(clamp 7.0M 5.0M 8.0M)"));
assertEquals(new BigDecimal("8.0"), venice.eval("(clamp 8.0M 5.0M 8.0M)"));
assertEquals(new BigDecimal("8.0"), venice.eval("(clamp 9.0M 5.0M 8.0M)"));

// BigInteger
assertEquals(new BigInteger("5"), venice.eval("(clamp 4N 5N 8N)"));
assertEquals(new BigInteger("5"), venice.eval("(clamp 5N 5N 8N)"));
assertEquals(new BigInteger("6"), venice.eval("(clamp 6N 5N 8N)"));
assertEquals(new BigInteger("7"), venice.eval("(clamp 7N 5N 8N)"));
assertEquals(new BigInteger("8"), venice.eval("(clamp 8N 5N 8N)"));
assertEquals(new BigInteger("8"), venice.eval("(clamp 9N 5N 8N)"));
}

@Test
public void test_mean() {
final Venice venice = new Venice();
Expand Down

0 comments on commit 819d9cf

Please sign in to comment.