1 /*
2  * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @compile/module=java.base java/util/SortingHelper.java
27  * @bug 6880672 6896573 6899694 6976036 7013585 7018258 8003981 8226297
28  * @build Sorting
29  * @run main Sorting -shortrun
30  * @summary Exercise Arrays.sort, Arrays.parallelSort
31  *
32  * @author Vladimir Yaroslavskiy
33  * @author Jon Bentley
34  * @author Josh Bloch
35  */
36 
37 package test.java.util.Arrays;
38 
39 import android.platform.test.annotations.LargeTest;
40 
41 import java.io.PrintStream;
42 import java.util.Comparator;
43 import java.util.Random;
44 
45 @LargeTest
46 @SuppressWarnings("IdentityBinaryExpression")
47 public class Sorting {
48 
49     private static final PrintStream out = System.out;
50     private static final PrintStream err = System.err;
51 
52     // Array lengths used in a long run (default)
53     private static final int[] LONG_RUN_LENGTHS = {
54         1, 3, 8, 21, 55, 100, 1_000, 10_000, 100_000 };
55 
56     // Array lengths used in a short run
57     private static final int[] SHORT_RUN_LENGTHS = {
58         1, 8, 55, 100, 10_000 };
59 
60     // Random initial values used in a long run (default)
61     private static final TestRandom[] LONG_RUN_RANDOMS = {
62         TestRandom.BABA, TestRandom.DEDA, TestRandom.C0FFEE };
63 
64     // Random initial values used in a short run
65     private static final TestRandom[] SHORT_RUN_RANDOMS = {
66         TestRandom.C0FFEE };
67 
68     // Constants used in subarray sorting
69     private static final int A380 = 0xA380;
70     private static final int B747 = 0xB747;
71 
72     @LargeTest
main(String[] args)73     public static void main(String[] args) {
74         long start = System.currentTimeMillis();
75         // Android-changed: coverage run with this flag set to true takes too
76         // much time. Locally it was killed after 45 minutes.
77         // boolean shortRun = args.length > 0 && args[0].equals("-shortrun");
78         boolean shortRun = true;
79 
80         int[] lengths = shortRun ? SHORT_RUN_LENGTHS : LONG_RUN_LENGTHS;
81         TestRandom[] randoms = shortRun ? SHORT_RUN_RANDOMS : LONG_RUN_RANDOMS;
82 
83         new InnerState(SortingHelper.DUAL_PIVOT_QUICKSORT, randoms, lengths).testCore();
84         new InnerState(SortingHelper.PARALLEL_SORT, randoms, lengths).testCore();
85         new InnerState(SortingHelper.HEAP_SORT, randoms, lengths).testBasic();
86         new InnerState(SortingHelper.ARRAYS_SORT, randoms, lengths).testAll();
87         new InnerState(SortingHelper.ARRAYS_PARALLEL_SORT, randoms, lengths).testAll();
88 
89         long end = System.currentTimeMillis();
90         out.format("PASSED in %d sec.\n", (end - start) / 1000);
91     }
92 
93     // Android-changed: runner can't run test with non-default contructor.
94     private static class InnerState {
95         private final SortingHelper sortingHelper;
96         private final TestRandom[] randoms;
97         private final int[] lengths;
98         private Object[] gold;
99         private Object[] test;
100 
InnerState(SortingHelper sortingHelper, TestRandom[] randoms, int[] lengths)101         public InnerState(SortingHelper sortingHelper, TestRandom[] randoms, int[] lengths) {
102             this.sortingHelper = sortingHelper;
103             this.randoms = randoms;
104             this.lengths = lengths;
105         }
106 
testBasic()107         private void testBasic() {
108             testEmptyArray();
109 
110             for (int length : lengths) {
111                 createData(length);
112                 testBasic(length);
113             }
114         }
115 
testBasic(int length)116         private void testBasic(int length) {
117             for (TestRandom random : randoms) {
118                 testWithInsertionSort(length, random);
119                 testWithCheckSum(length, random);
120                 testWithScrambling(length, random);
121             }
122         }
123 
testCore()124         private void testCore() {
125             for (int length : lengths) {
126                 createData(length);
127                 testCore(length);
128             }
129         }
130 
testCore(int length)131         private void testCore(int length) {
132             testBasic(length);
133 
134             for (TestRandom random : randoms) {
135                 testMergingSort(length, random);
136                 testSubArray(length, random);
137                 testNegativeZero(length, random);
138                 testFloatingPointSorting(length, random);
139             }
140         }
141 
testAll()142         private void testAll() {
143             for (int length : lengths) {
144                 createData(length);
145                 testAll(length);
146             }
147         }
148 
testAll(int length)149         private void testAll(int length) {
150             testCore(length);
151 
152             for (TestRandom random : randoms) {
153                 testRange(length, random);
154                 testStability(length, random);
155             }
156         }
157 
testEmptyArray()158         private void testEmptyArray() {
159             testEmptyAndNullIntArray();
160             testEmptyAndNullLongArray();
161             testEmptyAndNullByteArray();
162             testEmptyAndNullCharArray();
163             testEmptyAndNullShortArray();
164             testEmptyAndNullFloatArray();
165             testEmptyAndNullDoubleArray();
166         }
167 
testStability(int length, TestRandom random)168         private void testStability(int length, TestRandom random) {
169             printTestName("Test stability", random, length);
170 
171             Pair[] a = build(length, random);
172             sortingHelper.sort(a);
173             checkSorted(a);
174             checkStable(a);
175 
176             a = build(length, random);
177             sortingHelper.sort(a, pairComparator);
178             checkSorted(a);
179             checkStable(a);
180 
181             out.println();
182         }
183 
testEmptyAndNullIntArray()184         private void testEmptyAndNullIntArray() {
185             sortingHelper.sort(new int[]{});
186             sortingHelper.sort(new int[]{}, 0, 0);
187 
188             try {
189                 sortingHelper.sort(null);
190             } catch (NullPointerException expected) {
191                 try {
192                     sortingHelper.sort(null, 0, 0);
193                 } catch (NullPointerException expected2) {
194                     return;
195                 }
196                 fail(sortingHelper + "(int[],fromIndex,toIndex) shouldn't " +
197                         "catch null array");
198             }
199             fail(sortingHelper + "(int[]) shouldn't catch null array");
200         }
201 
testEmptyAndNullLongArray()202         private void testEmptyAndNullLongArray() {
203             sortingHelper.sort(new long[]{});
204             sortingHelper.sort(new long[]{}, 0, 0);
205 
206             try {
207                 sortingHelper.sort(null);
208             } catch (NullPointerException expected) {
209                 try {
210                     sortingHelper.sort(null, 0, 0);
211                 } catch (NullPointerException expected2) {
212                     return;
213                 }
214                 fail(sortingHelper + "(long[],fromIndex,toIndex) shouldn't " +
215                         "catch null array");
216             }
217             fail(sortingHelper + "(long[]) shouldn't catch null array");
218         }
219 
testEmptyAndNullByteArray()220         private void testEmptyAndNullByteArray() {
221             sortingHelper.sort(new byte[]{});
222             sortingHelper.sort(new byte[]{}, 0, 0);
223 
224             try {
225                 sortingHelper.sort(null);
226             } catch (NullPointerException expected) {
227                 try {
228                     sortingHelper.sort(null, 0, 0);
229                 } catch (NullPointerException expected2) {
230                     return;
231                 }
232                 fail(sortingHelper + "(byte[],fromIndex,toIndex) shouldn't " +
233                         "catch null array");
234             }
235             fail(sortingHelper + "(byte[]) shouldn't catch null array");
236         }
237 
testEmptyAndNullCharArray()238         private void testEmptyAndNullCharArray() {
239             sortingHelper.sort(new char[]{});
240             sortingHelper.sort(new char[]{}, 0, 0);
241 
242             try {
243                 sortingHelper.sort(null);
244             } catch (NullPointerException expected) {
245                 try {
246                     sortingHelper.sort(null, 0, 0);
247                 } catch (NullPointerException expected2) {
248                     return;
249                 }
250                 fail(sortingHelper + "(char[],fromIndex,toIndex) shouldn't " +
251                         "catch null array");
252             }
253             fail(sortingHelper + "(char[]) shouldn't catch null array");
254         }
255 
testEmptyAndNullShortArray()256         private void testEmptyAndNullShortArray() {
257             sortingHelper.sort(new short[]{});
258             sortingHelper.sort(new short[]{}, 0, 0);
259 
260             try {
261                 sortingHelper.sort(null);
262             } catch (NullPointerException expected) {
263                 try {
264                     sortingHelper.sort(null, 0, 0);
265                 } catch (NullPointerException expected2) {
266                     return;
267                 }
268                 fail(sortingHelper + "(short[],fromIndex,toIndex) shouldn't " +
269                         "catch null array");
270             }
271             fail(sortingHelper + "(short[]) shouldn't catch null array");
272         }
273 
testEmptyAndNullFloatArray()274         private void testEmptyAndNullFloatArray() {
275             sortingHelper.sort(new float[]{});
276             sortingHelper.sort(new float[]{}, 0, 0);
277 
278             try {
279                 sortingHelper.sort(null);
280             } catch (NullPointerException expected) {
281                 try {
282                     sortingHelper.sort(null, 0, 0);
283                 } catch (NullPointerException expected2) {
284                     return;
285                 }
286                 fail(sortingHelper + "(float[],fromIndex,toIndex) shouldn't " +
287                         "catch null array");
288             }
289             fail(sortingHelper + "(float[]) shouldn't catch null array");
290         }
291 
testEmptyAndNullDoubleArray()292         private void testEmptyAndNullDoubleArray() {
293             sortingHelper.sort(new double[]{});
294             sortingHelper.sort(new double[]{}, 0, 0);
295 
296             try {
297                 sortingHelper.sort(null);
298             } catch (NullPointerException expected) {
299                 try {
300                     sortingHelper.sort(null, 0, 0);
301                 } catch (NullPointerException expected2) {
302                     return;
303                 }
304                 fail(sortingHelper + "(double[],fromIndex,toIndex) shouldn't " +
305                         "catch null array");
306             }
307             fail(sortingHelper + "(double[]) shouldn't catch null array");
308         }
309 
testSubArray(int length, TestRandom random)310         private void testSubArray(int length, TestRandom random) {
311             if (length < 4) {
312                 return;
313             }
314             for (int m = 1; m < length / 2; m <<= 1) {
315                 int fromIndex = m;
316                 int toIndex = length - m;
317 
318                 prepareSubArray((int[]) gold[0], fromIndex, toIndex);
319                 convertData(length);
320 
321                 for (int i = 0; i < test.length; i++) {
322                     printTestName("Test subarray", random, length,
323                             ", m = " + m + ", " + getType(i));
324                     sortingHelper.sort(test[i], fromIndex, toIndex);
325                     checkSubArray(test[i], fromIndex, toIndex);
326                 }
327             }
328             out.println();
329         }
330 
testRange(int length, TestRandom random)331         private void testRange(int length, TestRandom random) {
332             if (length < 2) {
333                 return;
334             }
335             for (int m = 1; m < length; m <<= 1) {
336                 for (int i = 1; i <= length; i++) {
337                     ((int[]) gold[0])[i - 1] = i % m + m % i;
338                 }
339                 convertData(length);
340 
341                 for (int i = 0; i < test.length; i++) {
342                     printTestName("Test range check", random, length,
343                             ", m = " + m + ", " + getType(i));
344                     checkRange(test[i], m);
345                 }
346             }
347             out.println();
348         }
349 
checkSorted(Pair[] a)350         private void checkSorted(Pair[] a) {
351             for (int i = 0; i < a.length - 1; i++) {
352                 if (a[i].getKey() > a[i + 1].getKey()) {
353                     fail("Array is not sorted at " + i + "-th position: " +
354                             a[i].getKey() + " and " + a[i + 1].getKey());
355                 }
356             }
357         }
358 
checkStable(Pair[] a)359         private void checkStable(Pair[] a) {
360             for (int i = 0; i < a.length / 4; ) {
361                 int key1 = a[i].getKey();
362                 int value1 = a[i++].getValue();
363                 int key2 = a[i].getKey();
364                 int value2 = a[i++].getValue();
365                 int key3 = a[i].getKey();
366                 int value3 = a[i++].getValue();
367                 int key4 = a[i].getKey();
368                 int value4 = a[i++].getValue();
369 
370                 if (!(key1 == key2 && key2 == key3 && key3 == key4)) {
371                     fail("Keys are different " + key1 + ", " + key2 + ", " +
372                             key3 + ", " + key4 + " at position " + i);
373                 }
374                 if (!(value1 < value2 && value2 < value3 && value3 < value4)) {
375                     fail("Sorting is not stable at position " + i +
376                             ". Second values have been changed: " + value1 + ", " +
377                             value2 + ", " + value3 + ", " + value4);
378                 }
379             }
380         }
381 
build(int length, Random random)382         private Pair[] build(int length, Random random) {
383             Pair[] a = new Pair[length * 4];
384 
385             for (int i = 0; i < a.length; ) {
386                 int key = random.nextInt();
387                 a[i++] = new Pair(key, 1);
388                 a[i++] = new Pair(key, 2);
389                 a[i++] = new Pair(key, 3);
390                 a[i++] = new Pair(key, 4);
391             }
392             return a;
393         }
394 
testWithInsertionSort(int length, TestRandom random)395         private void testWithInsertionSort(int length, TestRandom random) {
396             if (length > 1000) {
397                 return;
398             }
399             for (int m = 1; m <= length; m <<= 1) {
400                 for (UnsortedBuilder builder : UnsortedBuilder.values()) {
401                     builder.build((int[]) gold[0], m, random);
402                     convertData(length);
403 
404                     for (int i = 0; i < test.length; i++) {
405                         printTestName("Test with insertion sort", random, length,
406                                 ", m = " + m + ", " + getType(i) + " " + builder);
407                         sortingHelper.sort(test[i]);
408                         sortByInsertionSort(gold[i]);
409                         compare(test[i], gold[i]);
410                     }
411                 }
412             }
413             out.println();
414         }
415 
testMergingSort(int length, TestRandom random)416         private void testMergingSort(int length, TestRandom random) {
417             if (length < (4 << 10)) { // DualPivotQuicksort.MIN_TRY_MERGE_SIZE
418                 return;
419             }
420             final int PERIOD = 50;
421 
422             for (int m = PERIOD - 2; m <= PERIOD + 2; m++) {
423                 for (MergingBuilder builder : MergingBuilder.values()) {
424                     builder.build((int[]) gold[0], m);
425                     convertData(length);
426 
427                     for (int i = 0; i < test.length; i++) {
428                         printTestName("Test merging sort", random, length,
429                                 ", m = " + m + ", " + getType(i) + " " + builder);
430                         sortingHelper.sort(test[i]);
431                         checkSorted(test[i]);
432                     }
433                 }
434             }
435             out.println();
436         }
437 
testWithCheckSum(int length, TestRandom random)438         private void testWithCheckSum(int length, TestRandom random) {
439             for (int m = 1; m <= length; m <<= 1) {
440                 for (UnsortedBuilder builder : UnsortedBuilder.values()) {
441                     builder.build((int[]) gold[0], m, random);
442                     convertData(length);
443 
444                     for (int i = 0; i < test.length; i++) {
445                         printTestName("Test with check sum", random, length,
446                                 ", m = " + m + ", " + getType(i) + " " + builder);
447                         sortingHelper.sort(test[i]);
448                         checkWithCheckSum(test[i], gold[i]);
449                     }
450                 }
451             }
452             out.println();
453         }
454 
testWithScrambling(int length, TestRandom random)455         private void testWithScrambling(int length, TestRandom random) {
456             for (int m = 1; m <= length; m <<= 1) {
457                 for (SortedBuilder builder : SortedBuilder.values()) {
458                     builder.build((int[]) gold[0], m);
459                     convertData(length);
460 
461                     for (int i = 0; i < test.length; i++) {
462                         printTestName("Test with scrambling", random, length,
463                                 ", m = " + m + ", " + getType(i) + " " + builder);
464                         scramble(test[i], random);
465                         sortingHelper.sort(test[i]);
466                         compare(test[i], gold[i]);
467                     }
468                 }
469             }
470             out.println();
471         }
472 
testNegativeZero(int length, TestRandom random)473         private void testNegativeZero(int length, TestRandom random) {
474             for (int i = 5; i < test.length; i++) {
475                 printTestName("Test negative zero -0.0", random, length, " " + getType(i));
476 
477                 NegativeZeroBuilder builder = NegativeZeroBuilder.values()[i - 5];
478                 builder.build(test[i], random);
479 
480                 sortingHelper.sort(test[i]);
481                 checkNegativeZero(test[i]);
482             }
483             out.println();
484         }
485 
testFloatingPointSorting(int length, TestRandom random)486         private void testFloatingPointSorting(int length, TestRandom random) {
487             if (length < 2) {
488                 return;
489             }
490             final int MAX = 13;
491 
492             for (int a = 0; a < MAX; a++) {
493                 for (int g = 0; g < MAX; g++) {
494                     for (int z = 0; z < MAX; z++) {
495                         for (int n = 0; n < MAX; n++) {
496                             for (int p = 0; p < MAX; p++) {
497                                 if (a + g + z + n + p != length) {
498                                     continue;
499                                 }
500                                 for (int i = 5; i < test.length; i++) {
501                                     printTestName("Test float-pointing sorting", random, length,
502                                             ", a = " + a + ", g = " + g + ", z = " + z +
503                                                     ", n = " + n + ", p = " + p + ", " + getType(
504                                                     i));
505                                     FloatingPointBuilder builder =
506                                             FloatingPointBuilder.values()[i - 5];
507                                     builder.build(gold[i], a, g, z, n, p, random);
508                                     copy(test[i], gold[i]);
509                                     scramble(test[i], random);
510                                     sortingHelper.sort(test[i]);
511                                     compare(test[i], gold[i], a, n, g);
512                                 }
513                             }
514                         }
515                     }
516                 }
517             }
518 
519             for (int m = 13; m > 4; m--) {
520                 int t = length / m;
521                 int g = t, z = t, n = t, p = t;
522                 int a = length - g - z - n - p;
523 
524                 for (int i = 5; i < test.length; i++) {
525                     printTestName("Test float-pointing sorting", random, length,
526                             ", a = " + a + ", g = " + g + ", z = " + z +
527                                     ", n = " + n + ", p = " + p + ", " + getType(i));
528                     FloatingPointBuilder builder = FloatingPointBuilder.values()[i - 5];
529                     builder.build(gold[i], a, g, z, n, p, random);
530                     copy(test[i], gold[i]);
531                     scramble(test[i], random);
532                     sortingHelper.sort(test[i]);
533                     compare(test[i], gold[i], a, n, g);
534                 }
535             }
536             out.println();
537         }
538 
prepareSubArray(int[] a, int fromIndex, int toIndex)539         private void prepareSubArray(int[] a, int fromIndex, int toIndex) {
540             for (int i = 0; i < fromIndex; i++) {
541                 a[i] = A380;
542             }
543             int middle = (fromIndex + toIndex) >>> 1;
544             int k = 0;
545 
546             for (int i = fromIndex; i < middle; i++) {
547                 a[i] = k++;
548             }
549 
550             for (int i = middle; i < toIndex; i++) {
551                 a[i] = k--;
552             }
553 
554             for (int i = toIndex; i < a.length; i++) {
555                 a[i] = B747;
556             }
557         }
558 
scramble(Object a, Random random)559         private void scramble(Object a, Random random) {
560             if (a instanceof int[]) {
561                 scramble((int[]) a, random);
562             } else if (a instanceof long[]) {
563                 scramble((long[]) a, random);
564             } else if (a instanceof byte[]) {
565                 scramble((byte[]) a, random);
566             } else if (a instanceof char[]) {
567                 scramble((char[]) a, random);
568             } else if (a instanceof short[]) {
569                 scramble((short[]) a, random);
570             } else if (a instanceof float[]) {
571                 scramble((float[]) a, random);
572             } else if (a instanceof double[]) {
573                 scramble((double[]) a, random);
574             } else {
575                 fail("Unknown type of array: " + a.getClass().getName());
576             }
577         }
578 
scramble(int[] a, Random random)579         private void scramble(int[] a, Random random) {
580             for (int i = 0; i < a.length * 7; i++) {
581                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
582             }
583         }
584 
scramble(long[] a, Random random)585         private void scramble(long[] a, Random random) {
586             for (int i = 0; i < a.length * 7; i++) {
587                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
588             }
589         }
590 
scramble(byte[] a, Random random)591         private void scramble(byte[] a, Random random) {
592             for (int i = 0; i < a.length * 7; i++) {
593                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
594             }
595         }
596 
scramble(char[] a, Random random)597         private void scramble(char[] a, Random random) {
598             for (int i = 0; i < a.length * 7; i++) {
599                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
600             }
601         }
602 
scramble(short[] a, Random random)603         private void scramble(short[] a, Random random) {
604             for (int i = 0; i < a.length * 7; i++) {
605                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
606             }
607         }
608 
scramble(float[] a, Random random)609         private void scramble(float[] a, Random random) {
610             for (int i = 0; i < a.length * 7; i++) {
611                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
612             }
613         }
614 
scramble(double[] a, Random random)615         private void scramble(double[] a, Random random) {
616             for (int i = 0; i < a.length * 7; i++) {
617                 swap(a, random.nextInt(a.length), random.nextInt(a.length));
618             }
619         }
620 
swap(int[] a, int i, int j)621         private void swap(int[] a, int i, int j) {
622             int t = a[i];
623             a[i] = a[j];
624             a[j] = t;
625         }
626 
swap(long[] a, int i, int j)627         private void swap(long[] a, int i, int j) {
628             long t = a[i];
629             a[i] = a[j];
630             a[j] = t;
631         }
632 
swap(byte[] a, int i, int j)633         private void swap(byte[] a, int i, int j) {
634             byte t = a[i];
635             a[i] = a[j];
636             a[j] = t;
637         }
638 
swap(char[] a, int i, int j)639         private void swap(char[] a, int i, int j) {
640             char t = a[i];
641             a[i] = a[j];
642             a[j] = t;
643         }
644 
swap(short[] a, int i, int j)645         private void swap(short[] a, int i, int j) {
646             short t = a[i];
647             a[i] = a[j];
648             a[j] = t;
649         }
650 
swap(float[] a, int i, int j)651         private void swap(float[] a, int i, int j) {
652             float t = a[i];
653             a[i] = a[j];
654             a[j] = t;
655         }
656 
swap(double[] a, int i, int j)657         private void swap(double[] a, int i, int j) {
658             double t = a[i];
659             a[i] = a[j];
660             a[j] = t;
661         }
662 
checkWithCheckSum(Object test, Object gold)663         private void checkWithCheckSum(Object test, Object gold) {
664             checkSorted(test);
665             checkCheckSum(test, gold);
666         }
667 
fail(String message)668         private void fail(String message) {
669             err.format("\n*** TEST FAILED ***\n\n%s\n\n", message);
670             throw new RuntimeException("Test failed");
671         }
672 
checkNegativeZero(Object a)673         private void checkNegativeZero(Object a) {
674             if (a instanceof float[]) {
675                 checkNegativeZero((float[]) a);
676             } else if (a instanceof double[]) {
677                 checkNegativeZero((double[]) a);
678             } else {
679                 fail("Unknown type of array: " + a.getClass().getName());
680             }
681         }
682 
checkNegativeZero(float[] a)683         private void checkNegativeZero(float[] a) {
684             for (int i = 0; i < a.length - 1; i++) {
685                 if (Float.floatToRawIntBits(a[i]) == 0 && Float.floatToRawIntBits(a[i + 1]) < 0) {
686                     fail(a[i] + " before " + a[i + 1] + " at position " + i);
687                 }
688             }
689         }
690 
checkNegativeZero(double[] a)691         private void checkNegativeZero(double[] a) {
692             for (int i = 0; i < a.length - 1; i++) {
693                 if (Double.doubleToRawLongBits(a[i]) == 0 && Double.doubleToRawLongBits(a[i + 1])
694                         < 0) {
695                     fail(a[i] + " before " + a[i + 1] + " at position " + i);
696                 }
697             }
698         }
699 
compare(Object a, Object b, int numNaN, int numNeg, int numNegZero)700         private void compare(Object a, Object b, int numNaN, int numNeg, int numNegZero) {
701             if (a instanceof float[]) {
702                 compare((float[]) a, (float[]) b, numNaN, numNeg, numNegZero);
703             } else if (a instanceof double[]) {
704                 compare((double[]) a, (double[]) b, numNaN, numNeg, numNegZero);
705             } else {
706                 fail("Unknown type of array: " + a.getClass().getName());
707             }
708         }
709 
compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero)710         private void compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero) {
711             for (int i = a.length - numNaN; i < a.length; i++) {
712                 if (a[i] == a[i]) {
713                     fail("There must be NaN instead of " + a[i] + " at position " + i);
714                 }
715             }
716             final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
717 
718             for (int i = numNeg; i < numNeg + numNegZero; i++) {
719                 if (NEGATIVE_ZERO != Float.floatToIntBits(a[i])) {
720                     fail("There must be -0.0 instead of " + a[i] + " at position " + i);
721                 }
722             }
723 
724             for (int i = 0; i < a.length - numNaN; i++) {
725                 if (a[i] != b[i]) {
726                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
727                 }
728             }
729         }
730 
compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero)731         private void compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero) {
732             for (int i = a.length - numNaN; i < a.length; i++) {
733                 if (a[i] == a[i]) {
734                     fail("There must be NaN instead of " + a[i] + " at position " + i);
735                 }
736             }
737             final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
738 
739             for (int i = numNeg; i < numNeg + numNegZero; i++) {
740                 if (NEGATIVE_ZERO != Double.doubleToLongBits(a[i])) {
741                     fail("There must be -0.0 instead of " + a[i] + " at position " + i);
742                 }
743             }
744 
745             for (int i = 0; i < a.length - numNaN; i++) {
746                 if (a[i] != b[i]) {
747                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
748                 }
749             }
750         }
751 
compare(Object a, Object b)752         private void compare(Object a, Object b) {
753             if (a instanceof int[]) {
754                 compare((int[]) a, (int[]) b);
755             } else if (a instanceof long[]) {
756                 compare((long[]) a, (long[]) b);
757             } else if (a instanceof byte[]) {
758                 compare((byte[]) a, (byte[]) b);
759             } else if (a instanceof char[]) {
760                 compare((char[]) a, (char[]) b);
761             } else if (a instanceof short[]) {
762                 compare((short[]) a, (short[]) b);
763             } else if (a instanceof float[]) {
764                 compare((float[]) a, (float[]) b);
765             } else if (a instanceof double[]) {
766                 compare((double[]) a, (double[]) b);
767             } else {
768                 fail("Unknown type of array: " + a.getClass().getName());
769             }
770         }
771 
compare(int[] a, int[] b)772         private void compare(int[] a, int[] b) {
773             for (int i = 0; i < a.length; i++) {
774                 if (a[i] != b[i]) {
775                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
776                 }
777             }
778         }
779 
compare(long[] a, long[] b)780         private void compare(long[] a, long[] b) {
781             for (int i = 0; i < a.length; i++) {
782                 if (a[i] != b[i]) {
783                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
784                 }
785             }
786         }
787 
compare(byte[] a, byte[] b)788         private void compare(byte[] a, byte[] b) {
789             for (int i = 0; i < a.length; i++) {
790                 if (a[i] != b[i]) {
791                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
792                 }
793             }
794         }
795 
compare(char[] a, char[] b)796         private void compare(char[] a, char[] b) {
797             for (int i = 0; i < a.length; i++) {
798                 if (a[i] != b[i]) {
799                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
800                 }
801             }
802         }
803 
compare(short[] a, short[] b)804         private void compare(short[] a, short[] b) {
805             for (int i = 0; i < a.length; i++) {
806                 if (a[i] != b[i]) {
807                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
808                 }
809             }
810         }
811 
compare(float[] a, float[] b)812         private void compare(float[] a, float[] b) {
813             for (int i = 0; i < a.length; i++) {
814                 if (a[i] != b[i]) {
815                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
816                 }
817             }
818         }
819 
compare(double[] a, double[] b)820         private void compare(double[] a, double[] b) {
821             for (int i = 0; i < a.length; i++) {
822                 if (a[i] != b[i]) {
823                     fail("There must be " + b[i] + " instead of " + a[i] + " at position " + i);
824                 }
825             }
826         }
827 
getType(int i)828         private String getType(int i) {
829             Object a = test[i];
830 
831             if (a instanceof int[]) {
832                 return "INT   ";
833             }
834             if (a instanceof long[]) {
835                 return "LONG  ";
836             }
837             if (a instanceof byte[]) {
838                 return "BYTE  ";
839             }
840             if (a instanceof char[]) {
841                 return "CHAR  ";
842             }
843             if (a instanceof short[]) {
844                 return "SHORT ";
845             }
846             if (a instanceof float[]) {
847                 return "FLOAT ";
848             }
849             if (a instanceof double[]) {
850                 return "DOUBLE";
851             }
852             fail("Unknown type of array: " + a.getClass().getName());
853             return null;
854         }
855 
checkSorted(Object a)856         private void checkSorted(Object a) {
857             if (a instanceof int[]) {
858                 checkSorted((int[]) a);
859             } else if (a instanceof long[]) {
860                 checkSorted((long[]) a);
861             } else if (a instanceof byte[]) {
862                 checkSorted((byte[]) a);
863             } else if (a instanceof char[]) {
864                 checkSorted((char[]) a);
865             } else if (a instanceof short[]) {
866                 checkSorted((short[]) a);
867             } else if (a instanceof float[]) {
868                 checkSorted((float[]) a);
869             } else if (a instanceof double[]) {
870                 checkSorted((double[]) a);
871             } else {
872                 fail("Unknown type of array: " + a.getClass().getName());
873             }
874         }
875 
checkSorted(int[] a)876         private void checkSorted(int[] a) {
877             for (int i = 0; i < a.length - 1; i++) {
878                 if (a[i] > a[i + 1]) {
879                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
880                             + 1]);
881                 }
882             }
883         }
884 
checkSorted(long[] a)885         private void checkSorted(long[] a) {
886             for (int i = 0; i < a.length - 1; i++) {
887                 if (a[i] > a[i + 1]) {
888                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
889                             + 1]);
890                 }
891             }
892         }
893 
checkSorted(byte[] a)894         private void checkSorted(byte[] a) {
895             for (int i = 0; i < a.length - 1; i++) {
896                 if (a[i] > a[i + 1]) {
897                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
898                             + 1]);
899                 }
900             }
901         }
902 
checkSorted(char[] a)903         private void checkSorted(char[] a) {
904             for (int i = 0; i < a.length - 1; i++) {
905                 if (a[i] > a[i + 1]) {
906                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
907                             + 1]);
908                 }
909             }
910         }
911 
checkSorted(short[] a)912         private void checkSorted(short[] a) {
913             for (int i = 0; i < a.length - 1; i++) {
914                 if (a[i] > a[i + 1]) {
915                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
916                             + 1]);
917                 }
918             }
919         }
920 
checkSorted(float[] a)921         private void checkSorted(float[] a) {
922             for (int i = 0; i < a.length - 1; i++) {
923                 if (a[i] > a[i + 1]) {
924                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
925                             + 1]);
926                 }
927             }
928         }
929 
checkSorted(double[] a)930         private void checkSorted(double[] a) {
931             for (int i = 0; i < a.length - 1; i++) {
932                 if (a[i] > a[i + 1]) {
933                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
934                             + 1]);
935                 }
936             }
937         }
938 
checkCheckSum(Object test, Object gold)939         private void checkCheckSum(Object test, Object gold) {
940             if (checkSumXor(test) != checkSumXor(gold)) {
941                 fail("Original and sorted arrays are not identical [^]");
942             }
943             if (checkSumPlus(test) != checkSumPlus(gold)) {
944                 fail("Original and sorted arrays are not identical [+]");
945             }
946         }
947 
checkSumXor(Object a)948         private int checkSumXor(Object a) {
949             if (a instanceof int[]) {
950                 return checkSumXor((int[]) a);
951             }
952             if (a instanceof long[]) {
953                 return checkSumXor((long[]) a);
954             }
955             if (a instanceof byte[]) {
956                 return checkSumXor((byte[]) a);
957             }
958             if (a instanceof char[]) {
959                 return checkSumXor((char[]) a);
960             }
961             if (a instanceof short[]) {
962                 return checkSumXor((short[]) a);
963             }
964             if (a instanceof float[]) {
965                 return checkSumXor((float[]) a);
966             }
967             if (a instanceof double[]) {
968                 return checkSumXor((double[]) a);
969             }
970             fail("Unknown type of array: " + a.getClass().getName());
971             return -1;
972         }
973 
checkSumXor(int[] a)974         private int checkSumXor(int[] a) {
975             int checkSum = 0;
976 
977             for (int e : a) {
978                 checkSum ^= e;
979             }
980             return checkSum;
981         }
982 
checkSumXor(long[] a)983         private int checkSumXor(long[] a) {
984             long checkSum = 0;
985 
986             for (long e : a) {
987                 checkSum ^= e;
988             }
989             return (int) checkSum;
990         }
991 
checkSumXor(byte[] a)992         private int checkSumXor(byte[] a) {
993             byte checkSum = 0;
994 
995             for (byte e : a) {
996                 checkSum ^= e;
997             }
998             return (int) checkSum;
999         }
1000 
checkSumXor(char[] a)1001         private int checkSumXor(char[] a) {
1002             char checkSum = 0;
1003 
1004             for (char e : a) {
1005                 checkSum ^= e;
1006             }
1007             return (int) checkSum;
1008         }
1009 
checkSumXor(short[] a)1010         private int checkSumXor(short[] a) {
1011             short checkSum = 0;
1012 
1013             for (short e : a) {
1014                 checkSum ^= e;
1015             }
1016             return (int) checkSum;
1017         }
1018 
checkSumXor(float[] a)1019         private int checkSumXor(float[] a) {
1020             int checkSum = 0;
1021 
1022             for (float e : a) {
1023                 checkSum ^= (int) e;
1024             }
1025             return checkSum;
1026         }
1027 
checkSumXor(double[] a)1028         private int checkSumXor(double[] a) {
1029             int checkSum = 0;
1030 
1031             for (double e : a) {
1032                 checkSum ^= (int) e;
1033             }
1034             return checkSum;
1035         }
1036 
checkSumPlus(Object a)1037         private int checkSumPlus(Object a) {
1038             if (a instanceof int[]) {
1039                 return checkSumPlus((int[]) a);
1040             }
1041             if (a instanceof long[]) {
1042                 return checkSumPlus((long[]) a);
1043             }
1044             if (a instanceof byte[]) {
1045                 return checkSumPlus((byte[]) a);
1046             }
1047             if (a instanceof char[]) {
1048                 return checkSumPlus((char[]) a);
1049             }
1050             if (a instanceof short[]) {
1051                 return checkSumPlus((short[]) a);
1052             }
1053             if (a instanceof float[]) {
1054                 return checkSumPlus((float[]) a);
1055             }
1056             if (a instanceof double[]) {
1057                 return checkSumPlus((double[]) a);
1058             }
1059             fail("Unknown type of array: " + a.getClass().getName());
1060             return -1;
1061         }
1062 
checkSumPlus(int[] a)1063         private int checkSumPlus(int[] a) {
1064             int checkSum = 0;
1065 
1066             for (int e : a) {
1067                 checkSum += e;
1068             }
1069             return checkSum;
1070         }
1071 
checkSumPlus(long[] a)1072         private int checkSumPlus(long[] a) {
1073             long checkSum = 0;
1074 
1075             for (long e : a) {
1076                 checkSum += e;
1077             }
1078             return (int) checkSum;
1079         }
1080 
checkSumPlus(byte[] a)1081         private int checkSumPlus(byte[] a) {
1082             byte checkSum = 0;
1083 
1084             for (byte e : a) {
1085                 checkSum += e;
1086             }
1087             return (int) checkSum;
1088         }
1089 
checkSumPlus(char[] a)1090         private int checkSumPlus(char[] a) {
1091             char checkSum = 0;
1092 
1093             for (char e : a) {
1094                 checkSum += e;
1095             }
1096             return (int) checkSum;
1097         }
1098 
checkSumPlus(short[] a)1099         private int checkSumPlus(short[] a) {
1100             short checkSum = 0;
1101 
1102             for (short e : a) {
1103                 checkSum += e;
1104             }
1105             return (int) checkSum;
1106         }
1107 
checkSumPlus(float[] a)1108         private int checkSumPlus(float[] a) {
1109             int checkSum = 0;
1110 
1111             for (float e : a) {
1112                 checkSum += (int) e;
1113             }
1114             return checkSum;
1115         }
1116 
checkSumPlus(double[] a)1117         private int checkSumPlus(double[] a) {
1118             int checkSum = 0;
1119 
1120             for (double e : a) {
1121                 checkSum += (int) e;
1122             }
1123             return checkSum;
1124         }
1125 
sortByInsertionSort(Object a)1126         private void sortByInsertionSort(Object a) {
1127             if (a instanceof int[]) {
1128                 sortByInsertionSort((int[]) a);
1129             } else if (a instanceof long[]) {
1130                 sortByInsertionSort((long[]) a);
1131             } else if (a instanceof byte[]) {
1132                 sortByInsertionSort((byte[]) a);
1133             } else if (a instanceof char[]) {
1134                 sortByInsertionSort((char[]) a);
1135             } else if (a instanceof short[]) {
1136                 sortByInsertionSort((short[]) a);
1137             } else if (a instanceof float[]) {
1138                 sortByInsertionSort((float[]) a);
1139             } else if (a instanceof double[]) {
1140                 sortByInsertionSort((double[]) a);
1141             } else {
1142                 fail("Unknown type of array: " + a.getClass().getName());
1143             }
1144         }
1145 
sortByInsertionSort(int[] a)1146         private void sortByInsertionSort(int[] a) {
1147             for (int j, i = 1; i < a.length; i++) {
1148                 int ai = a[i];
1149 
1150                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1151                     a[j + 1] = a[j];
1152                 }
1153                 a[j + 1] = ai;
1154             }
1155         }
1156 
sortByInsertionSort(long[] a)1157         private void sortByInsertionSort(long[] a) {
1158             for (int j, i = 1; i < a.length; i++) {
1159                 long ai = a[i];
1160 
1161                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1162                     a[j + 1] = a[j];
1163                 }
1164                 a[j + 1] = ai;
1165             }
1166         }
1167 
sortByInsertionSort(byte[] a)1168         private void sortByInsertionSort(byte[] a) {
1169             for (int j, i = 1; i < a.length; i++) {
1170                 byte ai = a[i];
1171 
1172                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1173                     a[j + 1] = a[j];
1174                 }
1175                 a[j + 1] = ai;
1176             }
1177         }
1178 
sortByInsertionSort(char[] a)1179         private void sortByInsertionSort(char[] a) {
1180             for (int j, i = 1; i < a.length; i++) {
1181                 char ai = a[i];
1182 
1183                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1184                     a[j + 1] = a[j];
1185                 }
1186                 a[j + 1] = ai;
1187             }
1188         }
1189 
sortByInsertionSort(short[] a)1190         private void sortByInsertionSort(short[] a) {
1191             for (int j, i = 1; i < a.length; i++) {
1192                 short ai = a[i];
1193 
1194                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1195                     a[j + 1] = a[j];
1196                 }
1197                 a[j + 1] = ai;
1198             }
1199         }
1200 
sortByInsertionSort(float[] a)1201         private void sortByInsertionSort(float[] a) {
1202             for (int j, i = 1; i < a.length; i++) {
1203                 float ai = a[i];
1204 
1205                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1206                     a[j + 1] = a[j];
1207                 }
1208                 a[j + 1] = ai;
1209             }
1210         }
1211 
sortByInsertionSort(double[] a)1212         private void sortByInsertionSort(double[] a) {
1213             for (int j, i = 1; i < a.length; i++) {
1214                 double ai = a[i];
1215 
1216                 for (j = i - 1; j >= 0 && ai < a[j]; j--) {
1217                     a[j + 1] = a[j];
1218                 }
1219                 a[j + 1] = ai;
1220             }
1221         }
1222 
checkSubArray(Object a, int fromIndex, int toIndex)1223         private void checkSubArray(Object a, int fromIndex, int toIndex) {
1224             if (a instanceof int[]) {
1225                 checkSubArray((int[]) a, fromIndex, toIndex);
1226             } else if (a instanceof long[]) {
1227                 checkSubArray((long[]) a, fromIndex, toIndex);
1228             } else if (a instanceof byte[]) {
1229                 checkSubArray((byte[]) a, fromIndex, toIndex);
1230             } else if (a instanceof char[]) {
1231                 checkSubArray((char[]) a, fromIndex, toIndex);
1232             } else if (a instanceof short[]) {
1233                 checkSubArray((short[]) a, fromIndex, toIndex);
1234             } else if (a instanceof float[]) {
1235                 checkSubArray((float[]) a, fromIndex, toIndex);
1236             } else if (a instanceof double[]) {
1237                 checkSubArray((double[]) a, fromIndex, toIndex);
1238             } else {
1239                 fail("Unknown type of array: " + a.getClass().getName());
1240             }
1241         }
1242 
checkSubArray(int[] a, int fromIndex, int toIndex)1243         private void checkSubArray(int[] a, int fromIndex, int toIndex) {
1244             for (int i = 0; i < fromIndex; i++) {
1245                 if (a[i] != A380) {
1246                     fail("Range sort changes left element at position " + i + hex(a[i], A380));
1247                 }
1248             }
1249 
1250             for (int i = fromIndex; i < toIndex - 1; i++) {
1251                 if (a[i] > a[i + 1]) {
1252                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1253                             + 1]);
1254                 }
1255             }
1256 
1257             for (int i = toIndex; i < a.length; i++) {
1258                 if (a[i] != B747) {
1259                     fail("Range sort changes right element at position " + i + hex(a[i], B747));
1260                 }
1261             }
1262         }
1263 
checkSubArray(long[] a, int fromIndex, int toIndex)1264         private void checkSubArray(long[] a, int fromIndex, int toIndex) {
1265             for (int i = 0; i < fromIndex; i++) {
1266                 if (a[i] != (long) A380) {
1267                     fail("Range sort changes left element at position " + i + hex(a[i], A380));
1268                 }
1269             }
1270 
1271             for (int i = fromIndex; i < toIndex - 1; i++) {
1272                 if (a[i] > a[i + 1]) {
1273                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1274                             + 1]);
1275                 }
1276             }
1277 
1278             for (int i = toIndex; i < a.length; i++) {
1279                 if (a[i] != (long) B747) {
1280                     fail("Range sort changes right element at position " + i + hex(a[i], B747));
1281                 }
1282             }
1283         }
1284 
checkSubArray(byte[] a, int fromIndex, int toIndex)1285         private void checkSubArray(byte[] a, int fromIndex, int toIndex) {
1286             for (int i = 0; i < fromIndex; i++) {
1287                 if (a[i] != (byte) A380) {
1288                     fail("Range sort changes left element at position " + i + hex(a[i], A380));
1289                 }
1290             }
1291 
1292             for (int i = fromIndex; i < toIndex - 1; i++) {
1293                 if (a[i] > a[i + 1]) {
1294                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1295                             + 1]);
1296                 }
1297             }
1298 
1299             for (int i = toIndex; i < a.length; i++) {
1300                 if (a[i] != (byte) B747) {
1301                     fail("Range sort changes right element at position " + i + hex(a[i], B747));
1302                 }
1303             }
1304         }
1305 
checkSubArray(char[] a, int fromIndex, int toIndex)1306         private void checkSubArray(char[] a, int fromIndex, int toIndex) {
1307             for (int i = 0; i < fromIndex; i++) {
1308                 if (a[i] != (char) A380) {
1309                     fail("Range sort changes left element at position " + i + hex(a[i], A380));
1310                 }
1311             }
1312 
1313             for (int i = fromIndex; i < toIndex - 1; i++) {
1314                 if (a[i] > a[i + 1]) {
1315                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1316                             + 1]);
1317                 }
1318             }
1319 
1320             for (int i = toIndex; i < a.length; i++) {
1321                 if (a[i] != (char) B747) {
1322                     fail("Range sort changes right element at position " + i + hex(a[i], B747));
1323                 }
1324             }
1325         }
1326 
checkSubArray(short[] a, int fromIndex, int toIndex)1327         private void checkSubArray(short[] a, int fromIndex, int toIndex) {
1328             for (int i = 0; i < fromIndex; i++) {
1329                 if (a[i] != (short) A380) {
1330                     fail("Range sort changes left element at position " + i + hex(a[i], A380));
1331                 }
1332             }
1333 
1334             for (int i = fromIndex; i < toIndex - 1; i++) {
1335                 if (a[i] > a[i + 1]) {
1336                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1337                             + 1]);
1338                 }
1339             }
1340 
1341             for (int i = toIndex; i < a.length; i++) {
1342                 if (a[i] != (short) B747) {
1343                     fail("Range sort changes right element at position " + i + hex(a[i], B747));
1344                 }
1345             }
1346         }
1347 
checkSubArray(float[] a, int fromIndex, int toIndex)1348         private void checkSubArray(float[] a, int fromIndex, int toIndex) {
1349             for (int i = 0; i < fromIndex; i++) {
1350                 if (a[i] != (float) A380) {
1351                     fail("Range sort changes left element at position " + i + hex((long) a[i],
1352                             A380));
1353                 }
1354             }
1355 
1356             for (int i = fromIndex; i < toIndex - 1; i++) {
1357                 if (a[i] > a[i + 1]) {
1358                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1359                             + 1]);
1360                 }
1361             }
1362 
1363             for (int i = toIndex; i < a.length; i++) {
1364                 if (a[i] != (float) B747) {
1365                     fail("Range sort changes right element at position " + i + hex((long) a[i],
1366                             B747));
1367                 }
1368             }
1369         }
1370 
checkSubArray(double[] a, int fromIndex, int toIndex)1371         private void checkSubArray(double[] a, int fromIndex, int toIndex) {
1372             for (int i = 0; i < fromIndex; i++) {
1373                 if (a[i] != (double) A380) {
1374                     fail("Range sort changes left element at position " + i + hex((long) a[i],
1375                             A380));
1376                 }
1377             }
1378 
1379             for (int i = fromIndex; i < toIndex - 1; i++) {
1380                 if (a[i] > a[i + 1]) {
1381                     fail("Array is not sorted at " + i + "-th position: " + a[i] + " and " + a[i
1382                             + 1]);
1383                 }
1384             }
1385 
1386             for (int i = toIndex; i < a.length; i++) {
1387                 if (a[i] != (double) B747) {
1388                     fail("Range sort changes right element at position " + i + hex((long) a[i],
1389                             B747));
1390                 }
1391             }
1392         }
1393 
checkRange(Object a, int m)1394         private void checkRange(Object a, int m) {
1395             if (a instanceof int[]) {
1396                 checkRange((int[]) a, m);
1397             } else if (a instanceof long[]) {
1398                 checkRange((long[]) a, m);
1399             } else if (a instanceof byte[]) {
1400                 checkRange((byte[]) a, m);
1401             } else if (a instanceof char[]) {
1402                 checkRange((char[]) a, m);
1403             } else if (a instanceof short[]) {
1404                 checkRange((short[]) a, m);
1405             } else if (a instanceof float[]) {
1406                 checkRange((float[]) a, m);
1407             } else if (a instanceof double[]) {
1408                 checkRange((double[]) a, m);
1409             } else {
1410                 fail("Unknown type of array: " + a.getClass().getName());
1411             }
1412         }
1413 
checkRange(int[] a, int m)1414         private void checkRange(int[] a, int m) {
1415             try {
1416                 sortingHelper.sort(a, m + 1, m);
1417                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1418                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1419             } catch (IllegalArgumentException iae) {
1420                 try {
1421                     sortingHelper.sort(a, -m, a.length);
1422                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1423                             "as expected: fromIndex = " + (-m));
1424                 } catch (ArrayIndexOutOfBoundsException aoe) {
1425                     try {
1426                         sortingHelper.sort(a, 0, a.length + m);
1427                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1428                                 "as expected: toIndex = " + (a.length + m));
1429                     } catch (ArrayIndexOutOfBoundsException expected) {
1430                     }
1431                 }
1432             }
1433         }
1434 
checkRange(long[] a, int m)1435         private void checkRange(long[] a, int m) {
1436             try {
1437                 sortingHelper.sort(a, m + 1, m);
1438                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1439                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1440             } catch (IllegalArgumentException iae) {
1441                 try {
1442                     sortingHelper.sort(a, -m, a.length);
1443                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1444                             "as expected: fromIndex = " + (-m));
1445                 } catch (ArrayIndexOutOfBoundsException aoe) {
1446                     try {
1447                         sortingHelper.sort(a, 0, a.length + m);
1448                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1449                                 "as expected: toIndex = " + (a.length + m));
1450                     } catch (ArrayIndexOutOfBoundsException expected) {
1451                     }
1452                 }
1453             }
1454         }
1455 
checkRange(byte[] a, int m)1456         private void checkRange(byte[] a, int m) {
1457             try {
1458                 sortingHelper.sort(a, m + 1, m);
1459                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1460                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1461             } catch (IllegalArgumentException iae) {
1462                 try {
1463                     sortingHelper.sort(a, -m, a.length);
1464                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1465                             "as expected: fromIndex = " + (-m));
1466                 } catch (ArrayIndexOutOfBoundsException aoe) {
1467                     try {
1468                         sortingHelper.sort(a, 0, a.length + m);
1469                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1470                                 "as expected: toIndex = " + (a.length + m));
1471                     } catch (ArrayIndexOutOfBoundsException expected) {
1472                     }
1473                 }
1474             }
1475         }
1476 
checkRange(char[] a, int m)1477         private void checkRange(char[] a, int m) {
1478             try {
1479                 sortingHelper.sort(a, m + 1, m);
1480                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1481                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1482             } catch (IllegalArgumentException iae) {
1483                 try {
1484                     sortingHelper.sort(a, -m, a.length);
1485                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1486                             "as expected: fromIndex = " + (-m));
1487                 } catch (ArrayIndexOutOfBoundsException aoe) {
1488                     try {
1489                         sortingHelper.sort(a, 0, a.length + m);
1490                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1491                                 "as expected: toIndex = " + (a.length + m));
1492                     } catch (ArrayIndexOutOfBoundsException expected) {
1493                     }
1494                 }
1495             }
1496         }
1497 
checkRange(short[] a, int m)1498         private void checkRange(short[] a, int m) {
1499             try {
1500                 sortingHelper.sort(a, m + 1, m);
1501                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1502                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1503             } catch (IllegalArgumentException iae) {
1504                 try {
1505                     sortingHelper.sort(a, -m, a.length);
1506                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1507                             "as expected: fromIndex = " + (-m));
1508                 } catch (ArrayIndexOutOfBoundsException aoe) {
1509                     try {
1510                         sortingHelper.sort(a, 0, a.length + m);
1511                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1512                                 "as expected: toIndex = " + (a.length + m));
1513                     } catch (ArrayIndexOutOfBoundsException expected) {
1514                     }
1515                 }
1516             }
1517         }
1518 
checkRange(float[] a, int m)1519         private void checkRange(float[] a, int m) {
1520             try {
1521                 sortingHelper.sort(a, m + 1, m);
1522                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1523                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1524             } catch (IllegalArgumentException iae) {
1525                 try {
1526                     sortingHelper.sort(a, -m, a.length);
1527                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1528                             "as expected: fromIndex = " + (-m));
1529                 } catch (ArrayIndexOutOfBoundsException aoe) {
1530                     try {
1531                         sortingHelper.sort(a, 0, a.length + m);
1532                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1533                                 "as expected: toIndex = " + (a.length + m));
1534                     } catch (ArrayIndexOutOfBoundsException expected) {
1535                     }
1536                 }
1537             }
1538         }
1539 
checkRange(double[] a, int m)1540         private void checkRange(double[] a, int m) {
1541             try {
1542                 sortingHelper.sort(a, m + 1, m);
1543                 fail(sortingHelper + " does not throw IllegalArgumentException " +
1544                         "as expected: fromIndex = " + (m + 1) + " toIndex = " + m);
1545             } catch (IllegalArgumentException iae) {
1546                 try {
1547                     sortingHelper.sort(a, -m, a.length);
1548                     fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1549                             "as expected: fromIndex = " + (-m));
1550                 } catch (ArrayIndexOutOfBoundsException aoe) {
1551                     try {
1552                         sortingHelper.sort(a, 0, a.length + m);
1553                         fail(sortingHelper + " does not throw ArrayIndexOutOfBoundsException " +
1554                                 "as expected: toIndex = " + (a.length + m));
1555                     } catch (ArrayIndexOutOfBoundsException expected) {
1556                     }
1557                 }
1558             }
1559         }
1560 
copy(Object dst, Object src)1561         private void copy(Object dst, Object src) {
1562             if (src instanceof float[]) {
1563                 copy((float[]) dst, (float[]) src);
1564             } else if (src instanceof double[]) {
1565                 copy((double[]) dst, (double[]) src);
1566             } else {
1567                 fail("Unknown type of array: " + src.getClass().getName());
1568             }
1569         }
1570 
copy(float[] dst, float[] src)1571         private void copy(float[] dst, float[] src) {
1572             System.arraycopy(src, 0, dst, 0, src.length);
1573         }
1574 
copy(double[] dst, double[] src)1575         private void copy(double[] dst, double[] src) {
1576             System.arraycopy(src, 0, dst, 0, src.length);
1577         }
1578 
printTestName(String test, TestRandom random, int length)1579         private void printTestName(String test, TestRandom random, int length) {
1580             printTestName(test, random, length, "");
1581         }
1582 
createData(int length)1583         private void createData(int length) {
1584             gold = new Object[]{
1585                     new int[length], new long[length],
1586                     new byte[length], new char[length], new short[length],
1587                     new float[length], new double[length]
1588             };
1589 
1590             test = new Object[]{
1591                     new int[length], new long[length],
1592                     new byte[length], new char[length], new short[length],
1593                     new float[length], new double[length]
1594             };
1595         }
1596 
convertData(int length)1597         private void convertData(int length) {
1598             for (int i = 1; i < gold.length; i++) {
1599                 TypeConverter converter = TypeConverter.values()[i - 1];
1600                 converter.convert((int[]) gold[0], gold[i]);
1601             }
1602 
1603             for (int i = 0; i < gold.length; i++) {
1604                 System.arraycopy(gold[i], 0, test[i], 0, length);
1605             }
1606         }
1607 
hex(long a, int b)1608         private String hex(long a, int b) {
1609             return ": " + Long.toHexString(a) + ", must be " + Integer.toHexString(b);
1610         }
1611 
printTestName(String test, TestRandom random, int length, String message)1612         private void printTestName(String test, TestRandom random, int length, String message) {
1613             out.println("[" + sortingHelper + "] '" + test +
1614                     "' length = " + length + ", random = " + random + message);
1615         }
1616     }
1617 
1618     private static enum TypeConverter {
1619         LONG {
convert(int[] src, Object dst)1620             void convert(int[] src, Object dst) {
1621                 long[] b = (long[]) dst;
1622 
1623                 for (int i = 0; i < src.length; i++) {
1624                     b[i] = (long) src[i];
1625                 }
1626             }
1627         },
1628 
1629         BYTE {
convert(int[] src, Object dst)1630             void convert(int[] src, Object dst) {
1631                 byte[] b = (byte[]) dst;
1632 
1633                 for (int i = 0; i < src.length; i++) {
1634                     b[i] = (byte) src[i];
1635                 }
1636             }
1637         },
1638 
1639         CHAR {
convert(int[] src, Object dst)1640             void convert(int[] src, Object dst) {
1641                 char[] b = (char[]) dst;
1642 
1643                 for (int i = 0; i < src.length; i++) {
1644                     b[i] = (char) src[i];
1645                 }
1646             }
1647         },
1648 
1649         SHORT {
convert(int[] src, Object dst)1650             void convert(int[] src, Object dst) {
1651                 short[] b = (short[]) dst;
1652 
1653                 for (int i = 0; i < src.length; i++) {
1654                     b[i] = (short) src[i];
1655                 }
1656             }
1657         },
1658 
1659         FLOAT {
convert(int[] src, Object dst)1660             void convert(int[] src, Object dst) {
1661                 float[] b = (float[]) dst;
1662 
1663                 for (int i = 0; i < src.length; i++) {
1664                     b[i] = (float) src[i];
1665                 }
1666             }
1667         },
1668 
1669         DOUBLE {
convert(int[] src, Object dst)1670             void convert(int[] src, Object dst) {
1671                 double[] b = (double[]) dst;
1672 
1673                 for (int i = 0; i < src.length; i++) {
1674                     b[i] = (double) src[i];
1675                 }
1676             }
1677         };
1678 
convert(int[] src, Object dst)1679         abstract void convert(int[] src, Object dst);
1680     }
1681 
1682     private static enum SortedBuilder {
1683         STEPS {
build(int[] a, int m)1684             void build(int[] a, int m) {
1685                 for (int i = 0; i < m; i++) {
1686                     a[i] = 0;
1687                 }
1688 
1689                 for (int i = m; i < a.length; i++) {
1690                     a[i] = 1;
1691                 }
1692             }
1693         };
1694 
build(int[] a, int m)1695         abstract void build(int[] a, int m);
1696     }
1697 
1698     private static enum UnsortedBuilder {
1699         RANDOM {
build(int[] a, int m, Random random)1700             void build(int[] a, int m, Random random) {
1701                 for (int i = 0; i < a.length; i++) {
1702                     a[i] = random.nextInt();
1703                 }
1704             }
1705         },
1706 
1707         ASCENDING {
build(int[] a, int m, Random random)1708             void build(int[] a, int m, Random random) {
1709                 for (int i = 0; i < a.length; i++) {
1710                     a[i] = m + i;
1711                 }
1712             }
1713         },
1714 
1715         DESCENDING {
build(int[] a, int m, Random random)1716             void build(int[] a, int m, Random random) {
1717                 for (int i = 0; i < a.length; i++) {
1718                     a[i] = a.length - m - i;
1719                 }
1720             }
1721         },
1722 
1723         EQUAL {
build(int[] a, int m, Random random)1724             void build(int[] a, int m, Random random) {
1725                 for (int i = 0; i < a.length; i++) {
1726                     a[i] = m;
1727                 }
1728             }
1729         },
1730 
1731         SAW {
build(int[] a, int m, Random random)1732             void build(int[] a, int m, Random random) {
1733                 int incCount = 1;
1734                 int decCount = a.length;
1735                 int i = 0;
1736                 int period = m--;
1737 
1738                 while (true) {
1739                     for (int k = 1; k <= period; k++) {
1740                         if (i >= a.length) {
1741                             return;
1742                         }
1743                         a[i++] = incCount++;
1744                     }
1745                     period += m;
1746 
1747                     for (int k = 1; k <= period; k++) {
1748                         if (i >= a.length) {
1749                             return;
1750                         }
1751                         a[i++] = decCount--;
1752                     }
1753                     period += m;
1754                 }
1755             }
1756         },
1757 
1758         REPEATED {
build(int[] a, int m, Random random)1759             void build(int[] a, int m, Random random) {
1760                 for (int i = 0; i < a.length; i++) {
1761                     a[i] = i % m;
1762                 }
1763             }
1764         },
1765 
1766         DUPLICATED {
build(int[] a, int m, Random random)1767             void build(int[] a, int m, Random random) {
1768                 for (int i = 0; i < a.length; i++) {
1769                     a[i] = random.nextInt(m);
1770                 }
1771             }
1772         },
1773 
1774         ORGAN_PIPES {
build(int[] a, int m, Random random)1775             void build(int[] a, int m, Random random) {
1776                 int middle = a.length / (m + 1);
1777 
1778                 for (int i = 0; i < middle; i++) {
1779                     a[i] = i;
1780                 }
1781 
1782                 for (int i = middle; i < a.length; i++) {
1783                     a[i] = a.length - i - 1;
1784                 }
1785             }
1786         },
1787 
1788         STAGGER {
build(int[] a, int m, Random random)1789             void build(int[] a, int m, Random random) {
1790                 for (int i = 0; i < a.length; i++) {
1791                     a[i] = (i * m + i) % a.length;
1792                 }
1793             }
1794         },
1795 
1796         PLATEAU {
build(int[] a, int m, Random random)1797             void build(int[] a, int m, Random random) {
1798                 for (int i = 0; i < a.length; i++) {
1799                     a[i] = Math.min(i, m);
1800                 }
1801             }
1802         },
1803 
1804         SHUFFLE {
build(int[] a, int m, Random random)1805             void build(int[] a, int m, Random random) {
1806                 int x = 0, y = 0;
1807 
1808                 for (int i = 0; i < a.length; i++) {
1809                     a[i] = random.nextBoolean() ? (x += 2) : (y += 2);
1810                 }
1811             }
1812         },
1813 
1814         LATCH {
build(int[] a, int m, Random random)1815             void build(int[] a, int m, Random random) {
1816                 int max = a.length / m;
1817                 max = max < 2 ? 2 : max;
1818 
1819                 for (int i = 0; i < a.length; i++) {
1820                     a[i] = i % max;
1821                 }
1822             }
1823         };
1824 
1825         abstract void build(int[] a, int m, Random random);
1826     }
1827 
1828     private static enum MergingBuilder {
1829         ASCENDING {
1830             void build(int[] a, int m) {
1831                 int period = a.length / m;
1832                 int v = 1, i = 0;
1833 
1834                 for (int k = 0; k < m; k++) {
1835                     v = 1;
1836 
1837                     for (int p = 0; p < period; p++) {
1838                         a[i++] = v++;
1839                     }
1840                 }
1841 
1842                 for (int j = i; j < a.length - 1; j++) {
1843                     a[j] = v++;
1844                 }
1845 
1846                 a[a.length - 1] = 0;
1847             }
1848         },
1849 
1850         DESCENDING {
1851             void build(int[] a, int m) {
1852                 int period = a.length / m;
1853                 int v = -1, i = 0;
1854 
1855                 for (int k = 0; k < m; k++) {
1856                     v = -1;
1857 
1858                     for (int p = 0; p < period; p++) {
1859                         a[i++] = v--;
1860                     }
1861                 }
1862 
1863                 for (int j = i; j < a.length - 1; j++) {
1864                     a[j] = v--;
1865                 }
1866 
1867                 a[a.length - 1] = 0;
1868             }
1869         },
1870 
1871         POINT {
1872             void build(int[] a, int m) {
1873                 for (int i = 0; i < a.length; i++) {
1874                     a[i] = 0;
1875                 }
1876                 a[a.length / 2] = m;
1877             }
1878         },
1879 
1880         LINE {
1881             void build(int[] a, int m) {
1882                 for (int i = 0; i < a.length; i++) {
1883                     a[i] = i;
1884                 }
1885                 reverse(a, 0, a.length - 1);
1886             }
1887         },
1888 
1889         PEARL {
1890             void build(int[] a, int m) {
1891                 for (int i = 0; i < a.length; i++) {
1892                     a[i] = i;
1893                 }
1894                 reverse(a, 0, 2);
1895             }
1896         },
1897 
1898         RING {
1899             void build(int[] a, int m) {
1900                 int k1 = a.length / 3;
1901                 int k2 = a.length / 3 * 2;
1902                 int level = a.length / 3;
1903 
1904                 for (int i = 0, k = level; i < k1; i++) {
1905                     a[i] = k--;
1906                 }
1907 
1908                 for (int i = k1; i < k2; i++) {
1909                     a[i] = 0;
1910                 }
1911 
1912                 for (int i = k2, k = level; i < a.length; i++) {
1913                     a[i] = k--;
1914                 }
1915             }
1916         };
1917 
1918         abstract void build(int[] a, int m);
1919 
1920         private static void reverse(int[] a, int lo, int hi) {
1921             for (--hi; lo < hi; ) {
1922                 int tmp = a[lo];
1923                 a[lo++] = a[hi];
1924                 a[hi--] = tmp;
1925             }
1926         }
1927     }
1928 
1929     private static enum NegativeZeroBuilder {
1930         FLOAT {
1931             void build(Object o, Random random) {
1932                 float[] a = (float[]) o;
1933 
1934                 for (int i = 0; i < a.length; i++) {
1935                     a[i] = random.nextBoolean() ? -0.0f : 0.0f;
1936                 }
1937             }
1938         },
1939 
1940         DOUBLE {
1941             void build(Object o, Random random) {
1942                 double[] a = (double[]) o;
1943 
1944                 for (int i = 0; i < a.length; i++) {
1945                     a[i] = random.nextBoolean() ? -0.0d : 0.0d;
1946                 }
1947             }
1948         };
1949 
1950         abstract void build(Object o, Random random);
1951     }
1952 
1953     private static enum FloatingPointBuilder {
1954         FLOAT {
1955             void build(Object o, int a, int g, int z, int n, int p, Random random) {
1956                 float negativeValue = -random.nextFloat();
1957                 float positiveValue =  random.nextFloat();
1958                 float[] x = (float[]) o;
1959                 int fromIndex = 0;
1960 
1961                 writeValue(x, negativeValue, fromIndex, n);
1962                 fromIndex += n;
1963 
1964                 writeValue(x, -0.0f, fromIndex, g);
1965                 fromIndex += g;
1966 
1967                 writeValue(x, 0.0f, fromIndex, z);
1968                 fromIndex += z;
1969 
1970                 writeValue(x, positiveValue, fromIndex, p);
1971                 fromIndex += p;
1972 
1973                 writeValue(x, Float.NaN, fromIndex, a);
1974             }
1975         },
1976 
1977         DOUBLE {
1978             void build(Object o, int a, int g, int z, int n, int p, Random random) {
1979                 double negativeValue = -random.nextFloat();
1980                 double positiveValue =  random.nextFloat();
1981                 double[] x = (double[]) o;
1982                 int fromIndex = 0;
1983 
1984                 writeValue(x, negativeValue, fromIndex, n);
1985                 fromIndex += n;
1986 
1987                 writeValue(x, -0.0d, fromIndex, g);
1988                 fromIndex += g;
1989 
1990                 writeValue(x, 0.0d, fromIndex, z);
1991                 fromIndex += z;
1992 
1993                 writeValue(x, positiveValue, fromIndex, p);
1994                 fromIndex += p;
1995 
1996                 writeValue(x, Double.NaN, fromIndex, a);
1997             }
1998         };
1999 
2000         abstract void build(Object o, int a, int g, int z, int n, int p, Random random);
2001 
2002         private static void writeValue(float[] a, float value, int fromIndex, int count) {
2003             for (int i = fromIndex; i < fromIndex + count; i++) {
2004                 a[i] = value;
2005             }
2006         }
2007 
2008         private static void writeValue(double[] a, double value, int fromIndex, int count) {
2009             for (int i = fromIndex; i < fromIndex + count; i++) {
2010                 a[i] = value;
2011             }
2012         }
2013     }
2014 
2015     private static Comparator<Pair> pairComparator = new Comparator<Pair>() {
2016 
2017         @Override
2018         public int compare(Pair p1, Pair p2) {
2019             return p1.compareTo(p2);
2020         }
2021     };
2022 
2023     private static class Pair implements Comparable<Pair> {
2024 
2025         private Pair(int key, int value) {
2026             this.key = key;
2027             this.value = value;
2028         }
2029 
2030         int getKey() {
2031             return key;
2032         }
2033 
2034         int getValue() {
2035             return value;
2036         }
2037 
2038         @Override
2039         public int compareTo(Pair pair) {
2040             return Integer.compare(key, pair.key);
2041         }
2042 
2043         @Override
2044         public String toString() {
2045             return "(" + key + ", " + value + ")";
2046         }
2047 
2048         private int key;
2049         private int value;
2050     }
2051 
2052     private static class TestRandom extends Random {
2053 
2054         private static final TestRandom BABA = new TestRandom(0xBABA);
2055         private static final TestRandom DEDA = new TestRandom(0xDEDA);
2056         private static final TestRandom C0FFEE = new TestRandom(0xC0FFEE);
2057 
2058         private TestRandom(long seed) {
2059             super(seed);
2060             this.seed = Long.toHexString(seed).toUpperCase();
2061         }
2062 
2063         @Override
2064         public String toString() {
2065             return seed;
2066         }
2067 
2068         private String seed;
2069     }
2070 }
2071