diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java b/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java index 84e55cf55..09cae4354 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java @@ -474,6 +474,9 @@ public class TArrays extends TObject { } public static void sort(int[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } int[] subarray = new int[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -536,6 +539,9 @@ public class TArrays extends TObject { } public static void sort(long[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } long[] subarray = new long[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -598,6 +604,9 @@ public class TArrays extends TObject { } public static void sort(short[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } short[] subarray = new short[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -660,6 +669,9 @@ public class TArrays extends TObject { } public static void sort(char[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } char[] subarray = new char[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -722,6 +734,9 @@ public class TArrays extends TObject { } public static void sort(byte[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } byte[] subarray = new byte[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -784,6 +799,9 @@ public class TArrays extends TObject { } public static void sort(float[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } float[] subarray = new float[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -835,7 +853,7 @@ public class TArrays extends TObject { } float p = a[from]; float q = a[from2]; - if (p <= q) { + if (Float.compare(p, q) <= 0) { b[index++] = p; ++from; } else { @@ -846,6 +864,9 @@ public class TArrays extends TObject { } public static void sort(double[] a, int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } double[] subarray = new double[toIndex - fromIndex]; for (int i = fromIndex; i < toIndex; ++i) { subarray[i - fromIndex] = a[i]; @@ -897,7 +918,7 @@ public class TArrays extends TObject { } double p = a[from]; double q = a[from2]; - if (p <= q) { + if (Double.compare(p, q) <= 0) { b[index++] = p; ++from; } else { @@ -916,6 +937,9 @@ public class TArrays extends TObject { } public static void sort(T[] a, int fromIndex, int toIndex, TComparator c) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException(); + } if (c == null) { c = TComparator.NaturalOrder.instance(); } @@ -993,28 +1017,20 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; int e = a[i]; if (e == key) { return i; } else if (key < e) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } public static int binarySearch(long[] a, long key) { @@ -1025,28 +1041,20 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; long e = a[i]; if (e == key) { return i; } else if (e > key) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } public static int binarySearch(short[] a, short key) { @@ -1057,28 +1065,20 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; short e = a[i]; if (e == key) { return i; } else if (e > key) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } public static int binarySearch(char[] a, char key) { @@ -1089,28 +1089,20 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; char e = a[i]; if (e == key) { return i; } else if (e > key) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } public static int binarySearch(byte[] a, byte key) { @@ -1121,28 +1113,20 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; byte e = a[i]; if (e == key) { return i; } else if (e > key) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } public static int binarySearch(double[] a, double key) { @@ -1153,28 +1137,21 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; double e = a[i]; - if (e == key) { - return i; - } else if (e > key) { - u = i - 1; - if (u < l) { - return -i - 1; - } - } else { + int cmp = Double.compare(e, key); + if (cmp < 0) { l = i + 1; - if (l > u) { - return -i - 2; - } + } else if (cmp > 0) { + u = i - 1; + } else { + return i; } } + return -l - 1; } public static int binarySearch(float[] a, float key) { @@ -1185,28 +1162,21 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; float e = a[i]; - if (e == key) { - return i; - } else if (e > key) { - u = i - 1; - if (u < l) { - return -i - 1; - } - } else { + int cmp = Float.compare(e, key); + if (cmp < 0) { l = i + 1; - if (l > u) { - return -i - 2; - } + } else if (cmp > 0) { + u = i - 1; + } else { + return i; } } + return -l - 1; } public static int binarySearch(Object[] a, Object key) { @@ -1228,12 +1198,9 @@ public class TArrays extends TObject { if (fromIndex > toIndex) { throw new TIllegalArgumentException(); } - if (fromIndex == toIndex) { - return -1; - } int l = fromIndex; int u = toIndex - 1; - while (true) { + while (l <= u) { int i = (l + u) / 2; T e = a[i]; int cmp = c.compare(key, e); @@ -1241,16 +1208,11 @@ public class TArrays extends TObject { return i; } else if (cmp < 0) { u = i - 1; - if (u < l) { - return -i - 1; - } } else { l = i + 1; - if (l > u) { - return -i - 2; - } } } + return -l - 1; } private static int mismatchImpl(long[] a, int aStart, long[] a2, int a2Start, int length) { @@ -1500,7 +1462,7 @@ public class TArrays extends TObject { private static int mismatchImpl(float[] a, int aStart, float[] a2, int a2Start, int length) { for (int i = 0; i < length; ++i) { - if (a[i + aStart] != a2[i + a2Start]) { + if (Float.compare(a[i + aStart], a2[i + a2Start]) != 0) { return i; } } @@ -1549,7 +1511,7 @@ public class TArrays extends TObject { private static int mismatchImpl(double[] a, int aStart, double[] a2, int a2Start, int length) { for (int i = 0; i < length; ++i) { - if (a[i + aStart] != a2[i + a2Start]) { + if (Double.compare(a[i + aStart], a2[i + a2Start]) != 0) { return i; } } diff --git a/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java b/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java index e6e357903..6a4a8c57d 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java @@ -25,6 +25,7 @@ import java.util.Optional; import java.util.stream.Collectors; import org.junit.Test; import org.junit.runner.RunWith; +import org.teavm.classlib.java.lang.DoubleTest; import org.teavm.junit.TeaVMTestRunner; @RunWith(TeaVMTestRunner.class) @@ -40,6 +41,36 @@ public class ArraysTest { assertEquals(Integer.valueOf(6), array[4]); assertEquals(Integer.valueOf(7), array[5]); Arrays.sort(array, null); // NPE check + double[] dSpecials1 = new double[] { Double.NaN, Double.MAX_VALUE, + Double.MIN_VALUE, 0d, -0d, Double.POSITIVE_INFINITY, + Double.NEGATIVE_INFINITY }; + double[] dSpecials2 = new double[] { 0d, Double.POSITIVE_INFINITY, -0d, + Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Double.NaN, + Double.MAX_VALUE }; + double[] dSorted = new double[] { Double.NEGATIVE_INFINITY, -0d, 0d, + Double.MIN_VALUE, Double.MAX_VALUE, Double.POSITIVE_INFINITY, + Double.NaN }; + Arrays.sort(dSpecials1); + assertTrue("specials sort incorrectly 1: " + Arrays.toString(dSpecials1), + Arrays.equals(dSpecials1, dSorted)); + Arrays.sort(dSpecials2); + assertTrue("specials sort incorrectly 2: " + Arrays.toString(dSpecials2), + Arrays.equals(dSpecials2, dSorted)); + float[] fSpecials1 = new float[] { Float.NaN, Float.MAX_VALUE, + Float.MIN_VALUE, 0f, -0f, Float.POSITIVE_INFINITY, + Float.NEGATIVE_INFINITY }; + float[] fSpecials2 = new float[] { 0f, Float.POSITIVE_INFINITY, -0f, + Float.NEGATIVE_INFINITY, Float.MIN_VALUE, Float.NaN, + Float.MAX_VALUE }; + float[] fSorted = new float[] { Float.NEGATIVE_INFINITY, -0f, 0f, + Float.MIN_VALUE, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN }; + Arrays.sort(fSpecials1); + assertTrue("specials sort incorrectly 1: " + Arrays.toString(fSpecials1), + Arrays.equals(fSpecials1, fSorted)); + Arrays.sort(fSpecials2); + assertTrue("specials sort incorrectly 2: " + Arrays.toString(fSpecials2), + Arrays.equals(fSpecials2, fSorted)); } @Test @@ -54,6 +85,23 @@ public class ArraysTest { assertEquals(-8, Arrays.binarySearch(array, 15)); assertEquals(-9, Arrays.binarySearch(array, 17)); assertEquals(3, Arrays.binarySearch(array, 8, null)); // NPE check + assertEquals(-6, Arrays.binarySearch(array, 5, 5, 10)); + float[] floatSpecials = new float[] { Float.NEGATIVE_INFINITY, + -Float.MAX_VALUE, -2f, -Float.MIN_VALUE, -0f, 0f, + Float.MIN_VALUE, 2f, Float.MAX_VALUE, Float.POSITIVE_INFINITY, + Float.NaN }; + for (int i = 0; i < floatSpecials.length; i++) { + int result = Arrays.binarySearch(floatSpecials, floatSpecials[i]); + assertEquals(floatSpecials[i] + " invalid: " + result, result, i); + } + double[] doubleSpecials = new double[] { Double.NEGATIVE_INFINITY, + -Double.MAX_VALUE, -2d, -Double.MIN_VALUE, -0d, 0d, + Double.MIN_VALUE, 2d, Double.MAX_VALUE, + Double.POSITIVE_INFINITY, Double.NaN }; + for (int i = 0; i < doubleSpecials.length; i++) { + int result = Arrays.binarySearch(doubleSpecials, doubleSpecials[i]); + assertEquals(doubleSpecials[i] + " invalid: " + result, result, i); + } } @Test @@ -162,10 +210,14 @@ public class ArraysTest { int[] equal = { 1, 2, 3 }; int[] shorter = { 1, 2 }; int[] different = { 3, 1, 2 }; + double[] withNaN = { 1.0, Double.NaN }; + double[] withOtherNaN = { 1.0, DoubleTest.OTHER_NAN }; // Simple equals assertTrue(Arrays.equals(array, array)); assertTrue(Arrays.equals(array, equal)); + assertTrue(Arrays.equals(withNaN, withNaN)); + assertTrue(Arrays.equals(withNaN, withOtherNaN)); // Equal to null assertTrue(Arrays.equals((int[]) null, null));