Skip to content

Commit

Permalink
[interval] Implements various helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazurl authored and 5pilow committed Aug 31, 2023
1 parent 2a0fbfa commit 9f621da
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 6 deletions.
12 changes: 12 additions & 0 deletions src/main/java/leekscript/runner/AI.java
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,9 @@ public ArrayLeekValue range(Object value, Object start, Object end, Object strid
var stride = longint(strideObject);
return ((ArrayLeekValue) value).arraySlice(this, start, end, stride);
}
if (value instanceof IntervalLeekValue) {
return ((IntervalLeekValue) value).range(this, start, end, real(strideObject));
}
addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new Object[] { value });
return null;
}
Expand All @@ -2752,6 +2755,9 @@ public ArrayLeekValue range_start(Object value, Object start, Object strideObjec
var stride = longint(strideObject);
return array.arraySlice(this, start, null, stride);
}
if (value instanceof IntervalLeekValue) {
return ((IntervalLeekValue) value).range(this, start, null, real(strideObject));
}
addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new Object[] { value });
return null;
}
Expand All @@ -2766,6 +2772,9 @@ public ArrayLeekValue range_end(Object value, Object end, Object strideObject) t
var stride = longint(strideObject);
return array.arraySlice(this, null, end, stride);
}
if (value instanceof IntervalLeekValue) {
return ((IntervalLeekValue) value).range(this, null, end, real(strideObject));
}
addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new Object[] { value });
return null;
}
Expand All @@ -2779,6 +2788,9 @@ public ArrayLeekValue range_all(Object value, Object strideObject) throws LeekRu
var stride = longint(strideObject);
return ((ArrayLeekValue) value).arraySlice(this, null, null, stride);
}
if (value instanceof IntervalLeekValue) {
return ((IntervalLeekValue) value).range(this, null, null, real(strideObject));
}
addSystemLog(AILog.ERROR, Error.VALUE_IS_NOT_AN_ARRAY, new Object[] { value });
return null;
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/leekscript/runner/LeekFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ public class LeekFunctions {
method("intervalUpperBound", "Interval", 1, Type.REAL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsEmpty", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsRightBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIsLeftBounded", "Interval", 1, Type.BOOL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalMidpoint", "Interval", 3, Type.REAL, new Type[] { Type.INTERVAL }).setMinVersion(4);
method("intervalIntersection", "Interval", 3, Type.INTERVAL, new Type[] { Type.INTERVAL, Type.INTERVAL }).setMinVersion(4);
method("intervalCombine", "Interval", 3, Type.INTERVAL, new Type[] { Type.INTERVAL, Type.INTERVAL }).setMinVersion(4);
method("intervalToArray", "Interval", new CallableVersion[] {
new CallableVersion(Type.ARRAY_REAL, new Type[] { Type.INTERVAL, Type.REAL }),
new CallableVersion(Type.ARRAY_REAL, new Type[] { Type.INTERVAL}),
Expand Down
93 changes: 87 additions & 6 deletions src/main/java/leekscript/runner/values/IntervalLeekValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public String toString(AI ai, Set<Object> visited) throws LeekRunException {

StringBuilder sb = new StringBuilder("[");

if (isLeftBounded()) {
if (intervalIsLeftBounded(ai)) {
sb.append(ai.export(from, visited));
}
sb.append("..");
if (isRightBounded()) {
if (intervalIsRightBounded(ai)) {
sb.append(ai.export(to, visited));
}

Expand All @@ -66,14 +66,14 @@ public boolean intervalIsEmpty(AI ai) {
}

public boolean intervalIsBounded(AI ai) {
return isLeftBounded() && isRightBounded();
return intervalIsLeftBounded(ai) && intervalIsRightBounded(ai);
}

public boolean isLeftBounded() {
public boolean intervalIsLeftBounded(AI ai) {
return from != Double.NEGATIVE_INFINITY;
}

public boolean isRightBounded() {
public boolean intervalIsRightBounded(AI ai) {
return to != Double.POSITIVE_INFINITY;
}

Expand All @@ -83,6 +83,51 @@ public boolean operatorIn(Object value) throws LeekRunException {
return from <= valueAsReal && valueAsReal <= to;
}

public double intervalMidpoint(AI ai) throws LeekRunException {
if (intervalIsEmpty(ai)) {
return Double.NaN;
}

// [a..b]
if (intervalIsBounded(ai)) {
return (from + to) / 2;
}
// [a..]
if (intervalIsLeftBounded(ai)) {
return Double.POSITIVE_INFINITY;
}
// [..b]
if (intervalIsRightBounded(ai)) {
return Double.NEGATIVE_INFINITY;
}
// [..]
return Double.NaN;
}

public IntervalLeekValue intervalIntersection(AI ai, IntervalLeekValue interval) throws LeekRunException {
if (intervalIsEmpty(ai)) {
return new IntervalLeekValue(ai, from, to);
}

if (interval.intervalIsEmpty(ai)) {
return new IntervalLeekValue(ai, interval.from, interval.to);
}

return new IntervalLeekValue(ai, Math.max(from, interval.from), Math.min(to, interval.to));
}

public IntervalLeekValue intervalCombine(AI ai, IntervalLeekValue interval) throws LeekRunException {
if (intervalIsEmpty(ai)) {
return new IntervalLeekValue(ai, interval.from, interval.to);
}

if (interval.intervalIsEmpty(ai)) {
return new IntervalLeekValue(ai, from, to);
}

return new IntervalLeekValue(ai, Math.min(from, interval.from), Math.max(to, interval.to));
}

public ArrayLeekValue intervalToArray(AI ai) throws LeekRunException {
return intervalToArray(ai, 1);
}
Expand All @@ -93,7 +138,6 @@ public ArrayLeekValue intervalToArray(AI ai, double step) throws LeekRunExceptio
return null;
}

// Operations are added by the array
var array = new ArrayLeekValue(ai);

if (step >= 0.0) {
Expand All @@ -110,4 +154,41 @@ public ArrayLeekValue intervalToArray(AI ai, double step) throws LeekRunExceptio

return array;
}

public ArrayLeekValue range(AI ai, Object start, Object end, double step) throws LeekRunException {
if (!intervalIsBounded(ai)) {
ai.addSystemLog(AILog.ERROR, Error.CANNOT_ITERATE_UNBOUNDED_INTERVAL, new Object[] { this });
return null;
}

if (intervalIsEmpty(ai)) {
return new ArrayLeekValue(ai);
}

if (step == 0.0) {
step = 1.0;
}

int maxSize = (int) ((to - from) / Math.abs(step)) + 1;

var startAsInteger = start == null ? 0 : ai.integer(start);
var endAsInteger = end == null ? maxSize : ai.integer(end);

int minIdx = Math.max(0, startAsInteger < 0 ? maxSize + startAsInteger : startAsInteger);
int maxIdx = Math.min(maxSize, endAsInteger < 0 ? maxSize + endAsInteger : endAsInteger);

var array = new ArrayLeekValue(ai);

for (var i = minIdx; i < maxIdx; ++i) {
if (step >= 0) {
array.push(ai, from + i * step);
} else {
array.push(ai, to + i * step);
}
}

ai.ops(array.size() * 2);

return array;
}
}
54 changes: 54 additions & 0 deletions src/test/java/test/TestInterval.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ public void run() throws Exception {
code_v4_("return intervalIsBounded([..]);").equals("false");
code_v4_("intervalIsBounded([1..2])").ops(3);

section("Interval.intervalIsLeftBounded");
code_v4_("return intervalIsLeftBounded([1..]);").equals("true");
code_v4_("return intervalIsLeftBounded([..2]);").equals("false");
code_v4_("intervalIsLeftBounded([1..2])").ops(3);

section("Interval.intervalIsRightBounded");
code_v4_("return intervalIsRightBounded([1..]);").equals("false");
code_v4_("return intervalIsRightBounded([..2]);").equals("true");
code_v4_("intervalIsRightBounded([1..2])").ops(3);

section("Interval.in");
code_v4_("return 1 in [1..2];").equals("true");
code_v4_("return 1 in [-1..];").equals("true");
Expand All @@ -77,6 +87,38 @@ public void run() throws Exception {
section("Interval typing");
code_strict_v4_("Interval i = [0..]; return i instanceof Interval").equals("true");

section("Interval.intervalMidpoint");
code_v4_("return intervalMidpoint([1..2]);").equals("1.5");
code_v4_("return intervalMidpoint([-10..10]);").equals("0.0");
code_v4_("return intervalMidpoint([1..1]);").equals("1.0");
code_v4_("return intervalMidpoint([1..0]);").equals("NaN");
code_v4_("return intervalMidpoint([..1]);").equals("-Infinity");
code_v4_("return intervalMidpoint([1..]);").equals("Infinity");
code_v4_("return intervalMidpoint([..]);").equals("NaN");
code_v4_("intervalMidpoint([1..2])").ops(5);

section("Interval.intervalIntersection");
code_v4_("return intervalIntersection([1..2], [1..2]);").equals("[1.0..2.0]");
code_v4_("return intervalIntersection([1..2], [1..3]);").equals("[1.0..2.0]");
code_v4_("return intervalIntersection([1..2], [0..1]);").equals("[1.0..1.0]");
code_v4_("return intervalIntersection([1..2], [-1..0]);").equals("[1.0..0.0]");
code_v4_("return intervalIntersection([-1..2], [1..]);").equals("[1.0..2.0]");
code_v4_("return intervalIntersection([1..2], [..1]);").equals("[1.0..1.0]");
code_v4_("return intervalIntersection([1..2], [..]);").equals("[1.0..2.0]");
code_v4_("return intervalIntersection([..2], [1..]);").equals("[1.0..2.0]");
code_v4_("intervalIntersection([1..2], [1..2])").ops(7);

section("Interval.intervalCombine");
code_v4_("return intervalCombine([1..2], [1..2]);").equals("[1.0..2.0]");
code_v4_("return intervalCombine([1..2], [1..3]);").equals("[1.0..3.0]");
code_v4_("return intervalCombine([1..2], [0..1]);").equals("[0.0..2.0]");
code_v4_("return intervalCombine([1..2], [-1..0]);").equals("[-1.0..2.0]");
code_v4_("return intervalCombine([-1..2], [1..]);").equals("[-1.0..]");
code_v4_("return intervalCombine([1..2], [..1]);").equals("[..2.0]");
code_v4_("return intervalCombine([1..2], [..]);").equals("[..]");
code_v4_("return intervalCombine([..2], [1..]);").equals("[..]");
code_v4_("intervalCombine([1..2], [1..2])").ops(7);

section("Interval.intervalToArray()");
code_v4_("return intervalToArray([1..2]);").equals("[1.0, 2.0]");
code_v4_("return intervalToArray([-2..2]);").equals("[-2.0, -1.0, 0.0, 1.0, 2.0]");
Expand All @@ -99,5 +141,17 @@ public void run() throws Exception {
code_v4_("return intervalToArray([-10..10], -5);").equals("[10.0, 5.0, 0.0, -5.0, -10.0]");
code_v4_("return intervalToArray([1..1], -7);").equals("[1.0]");
code_v4_("return intervalToArray([1..0], -2);").equals("[]");

section("Interval.[start:end:step]");
code_v4_("return [1..10][2:4:2];").equals("[5.0, 7.0]");
code_v4_("return [1..3][2:4:2];").equals("[]");
code_v4_("return [1..3][::2];").equals("[1.0, 3.0]");
code_v4_("return [1..3][::-1.5];").equals("[3.0, 1.5]");
code_v4_("return [1..10][2:4:-2];").equals("[6.0, 4.0]");
code_v4_("return [1..4][::];").equals("[1.0, 2.0, 3.0, 4.0]");
code_v4_("return [1..4][-1::];").equals("[4.0]");
code_v4_("return [1..4][:-1:];").equals("[1.0, 2.0, 3.0]");
code_v4_("return [1..4][2::];").equals("[3.0, 4.0]");
code_v4_("return [1..4][:2:];").equals("[1.0, 2.0]");
}
}

0 comments on commit 9f621da

Please sign in to comment.