Arrays.java 70 KB
Newer Older
Tom Tromey committed
1
/* Arrays.java -- Utility class with methods to operate on arrays
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Tom Tromey committed
3 4 5 6 7 8 9

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
10

Tom Tromey committed
11 12 13 14 15 16 17 18 19 20
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */
Tom Tromey committed
37 38 39 40


package java.util;

41 42 43
import java.io.Serializable;
import java.lang.reflect.Array;

Tom Tromey committed
44 45 46
/**
 * This class contains various static utility methods performing operations on
 * arrays, and a method to provide a List "view" of an array to facilitate
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
 * using arrays with Collection-based APIs. All methods throw a
 * {@link NullPointerException} if the parameter array is null.
 * <p>
 *
 * Implementations may use their own algorithms, but must obey the general
 * properties; for example, the sort must be stable and n*log(n) complexity.
 * Sun's implementation of sort, and therefore ours, is a tuned quicksort,
 * adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort
 * Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265
 * (November 1993). This algorithm offers n*log(n) performance on many data
 * sets that cause other quicksorts to degrade to quadratic performance.
 *
 * @author Original author unknown
 * @author Bryce McKinlay
 * @author Eric Blake <ebb9@email.byu.edu>
 * @see Comparable
 * @see Comparator
 * @since 1.2
 * @status updated to 1.4
Tom Tromey committed
66
 */
67 68
public class Arrays
{
Tom Tromey committed
69 70 71
  /**
   * This class is non-instantiable.
   */
72 73
  private Arrays()
  {
Tom Tromey committed
74 75
  }

76 77

// binarySearch
Tom Tromey committed
78 79 80 81 82 83 84 85 86 87
  /**
   * Perform a binary search of a byte array for a key. The array must be
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
88 89 90
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
91
   */
92
  public static int binarySearch(byte[] a, byte key)
93
  {
Tom Tromey committed
94 95 96
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
97 98
    while (low <= hi)
      {
99 100 101 102 103 104 105 106 107
        mid = (low + hi) >> 1;
        final byte d = a[mid];
        if (d == key)
          return mid;
        else if (d > key)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop.
          low = ++mid;
Tom Tromey committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121
      }
    return -mid - 1;
  }

  /**
   * Perform a binary search of a char array for a key. The array must be
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
122 123 124
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
125
   */
126
  public static int binarySearch(char[] a, char key)
127
  {
Tom Tromey committed
128 129 130
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
131 132
    while (low <= hi)
      {
133 134 135 136 137 138 139 140 141
        mid = (low + hi) >> 1;
        final char d = a[mid];
        if (d == key)
          return mid;
        else if (d > key)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop.
          low = ++mid;
Tom Tromey committed
142 143 144 145 146
      }
    return -mid - 1;
  }

  /**
147
   * Perform a binary search of a short array for a key. The array must be
Tom Tromey committed
148 149 150 151 152 153 154 155
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
156 157 158
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
159
   */
160
  public static int binarySearch(short[] a, short key)
161
  {
Tom Tromey committed
162 163 164
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
165 166
    while (low <= hi)
      {
167 168 169 170 171 172 173 174 175
        mid = (low + hi) >> 1;
        final short d = a[mid];
        if (d == key)
          return mid;
        else if (d > key)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop.
          low = ++mid;
Tom Tromey committed
176 177 178 179 180
      }
    return -mid - 1;
  }

  /**
181
   * Perform a binary search of an int array for a key. The array must be
Tom Tromey committed
182 183 184 185 186 187 188 189
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
190 191 192
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
193
   */
194
  public static int binarySearch(int[] a, int key)
195
  {
Tom Tromey committed
196 197 198
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
199 200
    while (low <= hi)
      {
201 202 203 204 205 206 207 208 209
        mid = (low + hi) >> 1;
        final int d = a[mid];
        if (d == key)
          return mid;
        else if (d > key)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop.
          low = ++mid;
Tom Tromey committed
210 211 212 213 214
      }
    return -mid - 1;
  }

  /**
215
   * Perform a binary search of a long array for a key. The array must be
Tom Tromey committed
216 217 218 219 220 221 222 223
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
224 225 226
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
227
   */
228
  public static int binarySearch(long[] a, long key)
229
  {
Tom Tromey committed
230 231 232
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
233 234
    while (low <= hi)
      {
235 236 237 238 239 240 241 242 243
        mid = (low + hi) >> 1;
        final long d = a[mid];
        if (d == key)
          return mid;
        else if (d > key)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop.
          low = ++mid;
Tom Tromey committed
244 245 246 247 248
      }
    return -mid - 1;
  }

  /**
249
   * Perform a binary search of a float array for a key. The array must be
Tom Tromey committed
250 251 252 253 254 255 256 257
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
258 259 260
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
261
   */
262
  public static int binarySearch(float[] a, float key)
263
  {
264
    // Must use Float.compare to take into account NaN, +-0.
Tom Tromey committed
265 266 267
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
268 269
    while (low <= hi)
      {
270 271 272 273 274 275 276 277 278
        mid = (low + hi) >> 1;
        final int r = Float.compare(a[mid], key);
        if (r == 0)
          return mid;
        else if (r > 0)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop
          low = ++mid;
Tom Tromey committed
279 280 281 282 283
      }
    return -mid - 1;
  }

  /**
284
   * Perform a binary search of a double array for a key. The array must be
Tom Tromey committed
285 286 287 288 289 290 291 292
   * sorted (as by the sort() method) - if it is not, the behaviour of this
   * method is undefined, and may be an infinite loop. If the array contains
   * the key more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
293 294 295
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
Tom Tromey committed
296
   */
297
  public static int binarySearch(double[] a, double key)
298
  {
299
    // Must use Double.compare to take into account NaN, +-0.
Tom Tromey committed
300 301 302
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
303 304
    while (low <= hi)
      {
305 306 307 308 309 310 311 312 313
        mid = (low + hi) >> 1;
        final int r = Double.compare(a[mid], key);
        if (r == 0)
          return mid;
        else if (r > 0)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop
          low = ++mid;
Tom Tromey committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
      }
    return -mid - 1;
  }

  /**
   * Perform a binary search of an Object array for a key, using the natural
   * ordering of the elements. The array must be sorted (as by the sort()
   * method) - if it is not, the behaviour of this method is undefined, and may
   * be an infinite loop. Further, the key must be comparable with every item
   * in the array. If the array contains the key more than once, any one of
   * them may be found. Note: although the specification allows for an infinite
   * loop if the array is unsorted, it will not happen in this (JCL)
   * implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
330 331 332 333 334 335
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
   * @throws ClassCastException if key could not be compared with one of the
   *         elements of a
   * @throws NullPointerException if a null element in a is compared
Tom Tromey committed
336
   */
337
  public static int binarySearch(Object[] a, Object key)
338
  {
339
    return binarySearch(a, key, null);
Tom Tromey committed
340 341 342 343 344 345 346 347 348 349 350 351 352 353
  }

  /**
   * Perform a binary search of an Object array for a key, using a supplied
   * Comparator. The array must be sorted (as by the sort() method with the
   * same Comparator) - if it is not, the behaviour of this method is
   * undefined, and may be an infinite loop. Further, the key must be
   * comparable with every item in the array. If the array contains the key
   * more than once, any one of them may be found. Note: although the
   * specification allows for an infinite loop if the array is unsorted, it
   * will not happen in this (JCL) implementation.
   *
   * @param a the array to search (must be sorted)
   * @param key the value to search for
354 355 356 357 358 359 360 361 362
   * @param c the comparator by which the array is sorted; or null to
   *        use the elements' natural order
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value.
   * @throws ClassCastException if key could not be compared with one of the
   *         elements of a
   * @throws NullPointerException if a null element is compared with natural
   *         ordering (only possible when c is null)
Tom Tromey committed
363
   */
364
  public static int binarySearch(Object[] a, Object key, Comparator c)
365
  {
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
    int low = 0;
    int hi = a.length - 1;
    int mid = 0;
    while (low <= hi)
      {
        mid = (low + hi) >> 1;
        final int d = Collections.compare(key, a[mid], c);
        if (d == 0)
          return mid;
        else if (d < 0)
          hi = mid - 1;
        else
          // This gets the insertion point right on the last loop
          low = ++mid;
      }
    return -mid - 1;
Tom Tromey committed
382 383
  }

384 385

// equals
Tom Tromey committed
386
  /**
387
   * Compare two boolean arrays for equality.
Tom Tromey committed
388 389 390
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
391 392
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
393
   */
394
  public static boolean equals(boolean[] a1, boolean[] a2)
395
  {
Tom Tromey committed
396 397
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
398
    if (a1 == a2)
399 400
      return true;

401 402 403 404 405
    if (null == a1 || null == a2)
      return false;
    
    // If they're the same length, test each element
    if (a1.length == a2.length)
406
      {
407 408 409 410 411
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
412
      }
Tom Tromey committed
413 414 415 416
    return false;
  }

  /**
417
   * Compare two byte arrays for equality.
Tom Tromey committed
418 419 420
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
421 422
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
423
   */
424
  public static boolean equals(byte[] a1, byte[] a2)
425
  {
Tom Tromey committed
426 427
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
428
    if (a1 == a2)
429 430
      return true;

431 432 433 434 435
    if (null == a1 || null == a2)
      return false;

    // If they're the same length, test each element
    if (a1.length == a2.length)
436
      {
437 438 439 440 441
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
442
      }
Tom Tromey committed
443 444 445 446
    return false;
  }

  /**
447
   * Compare two char arrays for equality.
Tom Tromey committed
448 449 450
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
451 452
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
453
   */
454
  public static boolean equals(char[] a1, char[] a2)
455
  {
Tom Tromey committed
456 457
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
458
    if (a1 == a2)
459 460
      return true;

461 462 463 464 465
    if (null == a1 || null == a2)
      return false;
    
    // If they're the same length, test each element
    if (a1.length == a2.length)
466
      {
467 468 469 470 471
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
472
      }
Tom Tromey committed
473 474 475 476
    return false;
  }

  /**
477
   * Compare two short arrays for equality.
Tom Tromey committed
478 479 480
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
481 482
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
483
   */
484
  public static boolean equals(short[] a1, short[] a2)
485
  {
Tom Tromey committed
486 487
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
488
    if (a1 == a2)
489 490
      return true;

491 492 493 494 495
    if (null == a1 || null == a2)
      return false;

    // If they're the same length, test each element
    if (a1.length == a2.length)
496
      {
497 498 499 500 501
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
502
      }
Tom Tromey committed
503 504 505 506
    return false;
  }

  /**
507
   * Compare two int arrays for equality.
Tom Tromey committed
508 509 510
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
511 512
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
513
   */
514
  public static boolean equals(int[] a1, int[] a2)
515
  {
Tom Tromey committed
516 517
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
518
    if (a1 == a2)
519 520
      return true;

521 522 523 524 525
    if (null == a1 || null == a2)
      return false;

    // If they're the same length, test each element
    if (a1.length == a2.length)
526
      {
527 528 529 530 531
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
532
      }
Tom Tromey committed
533 534 535 536
    return false;
  }

  /**
537
   * Compare two long arrays for equality.
Tom Tromey committed
538 539 540
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
541 542
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
543
   */
544
  public static boolean equals(long[] a1, long[] a2)
545
  {
Tom Tromey committed
546 547
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
548
    if (a1 == a2)
549 550
      return true;

551 552 553 554 555
    if (null == a1 || null == a2)
      return false;

    // If they're the same length, test each element
    if (a1.length == a2.length)
556
      {
557 558 559 560 561
	int i = a1.length;
	while (--i >= 0)
	  if (a1[i] != a2[i])
	    return false;
	return true;
562
      }
Tom Tromey committed
563 564 565 566
    return false;
  }

  /**
567
   * Compare two float arrays for equality.
Tom Tromey committed
568 569 570
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
571 572
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
573
   */
574
  public static boolean equals(float[] a1, float[] a2)
575
  {
Tom Tromey committed
576 577
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
578
    if (a1 == a2)
579 580
      return true;

581 582 583
    if (null == a1 || null == a2)
      return false;

584
    // Must use Float.compare to take into account NaN, +-0.
585 586
    // If they're the same length, test each element
    if (a1.length == a2.length)
587
      {
588 589 590 591 592
	int i = a1.length;
	while (--i >= 0)
	  if (Float.compare(a1[i], a2[i]) != 0)
	    return false;
	return true;
593
      }
Tom Tromey committed
594 595 596 597
    return false;
  }

  /**
598
   * Compare two double arrays for equality.
Tom Tromey committed
599 600 601
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
602 603
   * @return true if a1 and a2 are both null, or if a2 is of the same length
   *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
Tom Tromey committed
604
   */
605
  public static boolean equals(double[] a1, double[] a2)
606
  {
Tom Tromey committed
607 608
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
609
    if (a1 == a2)
610 611
      return true;

612 613 614
    if (null == a1 || null == a2)
      return false;
    
615
    // Must use Double.compare to take into account NaN, +-0.
616 617
    // If they're the same length, test each element
    if (a1.length == a2.length)
618
      {
619 620 621 622 623
	int i = a1.length;
	while (--i >= 0)
	  if (Double.compare(a1[i], a2[i]) != 0)
	    return false;
	return true;
624
      }
Tom Tromey committed
625 626 627 628 629 630 631 632
    return false;
  }

  /**
   * Compare two Object arrays for equality.
   *
   * @param a1 the first array to compare
   * @param a2 the second array to compare
633 634 635
   * @return true if a1 and a2 are both null, or if a1 is of the same length
   *         as a2, and for each 0 <= i < a.length, a1[i] == null ?
   *         a2[i] == null : a1[i].equals(a2[i]).
Tom Tromey committed
636
   */
637
  public static boolean equals(Object[] a1, Object[] a2)
638
  {
Tom Tromey committed
639 640
    // Quick test which saves comparing elements of the same array, and also
    // catches the case that both are null.
641
    if (a1 == a2)
642 643
      return true;

644 645 646 647 648
    if (null == a1 || null == a2)
      return false;
    
    // If they're the same length, test each element
    if (a1.length == a2.length)
649
      {
650 651 652 653 654
	int i = a1.length;
	while (--i >= 0)
	  if (! AbstractCollection.equals(a1[i], a2[i]))
	    return false;
	return true;
655
      }
Tom Tromey committed
656 657 658
    return false;
  }

659 660

// fill
Tom Tromey committed
661 662 663 664 665 666
  /**
   * Fill an array with a boolean value.
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
667
  public static void fill(boolean[] a, boolean val)
668
  {
Tom Tromey committed
669 670 671 672 673 674 675 676 677 678
    fill(a, 0, a.length, val);
  }

  /**
   * Fill a range of an array with a boolean value.
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
679 680 681
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
682
   */
683
  public static void fill(boolean[] a, int fromIndex, int toIndex, boolean val)
684
  {
685 686
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
687
    for (int i = fromIndex; i < toIndex; i++)
688
      a[i] = val;
Tom Tromey committed
689 690 691 692 693 694 695 696
  }

  /**
   * Fill an array with a byte value.
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
697
  public static void fill(byte[] a, byte val)
698
  {
Tom Tromey committed
699 700 701 702 703 704 705 706 707 708
    fill(a, 0, a.length, val);
  }

  /**
   * Fill a range of an array with a byte value.
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
709 710 711
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
712
   */
713
  public static void fill(byte[] a, int fromIndex, int toIndex, byte val)
714
  {
715 716
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
717
    for (int i = fromIndex; i < toIndex; i++)
718
      a[i] = val;
Tom Tromey committed
719 720 721 722 723 724 725 726
  }

  /**
   * Fill an array with a char value.
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
727
  public static void fill(char[] a, char val)
728
  {
Tom Tromey committed
729 730 731 732 733 734 735 736 737 738
    fill(a, 0, a.length, val);
  }

  /**
   * Fill a range of an array with a char value.
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
739 740 741
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
742
   */
743
  public static void fill(char[] a, int fromIndex, int toIndex, char val)
744
  {
745 746
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
747
    for (int i = fromIndex; i < toIndex; i++)
748
      a[i] = val;
Tom Tromey committed
749 750 751
  }

  /**
752
   * Fill an array with a short value.
Tom Tromey committed
753 754 755 756
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
757
  public static void fill(short[] a, short val)
758
  {
Tom Tromey committed
759 760 761 762
    fill(a, 0, a.length, val);
  }

  /**
763
   * Fill a range of an array with a short value.
Tom Tromey committed
764 765 766 767 768
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
769 770 771
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
772
   */
773
  public static void fill(short[] a, int fromIndex, int toIndex, short val)
774
  {
775 776
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
777
    for (int i = fromIndex; i < toIndex; i++)
778
      a[i] = val;
Tom Tromey committed
779 780 781
  }

  /**
782
   * Fill an array with an int value.
Tom Tromey committed
783 784 785 786
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
787
  public static void fill(int[] a, int val)
788
  {
Tom Tromey committed
789 790 791 792
    fill(a, 0, a.length, val);
  }

  /**
793
   * Fill a range of an array with an int value.
Tom Tromey committed
794 795 796 797 798
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
799 800 801
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
802
   */
803
  public static void fill(int[] a, int fromIndex, int toIndex, int val)
804
  {
805 806
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
807
    for (int i = fromIndex; i < toIndex; i++)
808
      a[i] = val;
Tom Tromey committed
809 810 811
  }

  /**
812
   * Fill an array with a long value.
Tom Tromey committed
813 814 815 816
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
817
  public static void fill(long[] a, long val)
818
  {
Tom Tromey committed
819 820 821 822
    fill(a, 0, a.length, val);
  }

  /**
823
   * Fill a range of an array with a long value.
Tom Tromey committed
824 825 826 827 828
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
829 830 831
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
832
   */
833
  public static void fill(long[] a, int fromIndex, int toIndex, long val)
834
  {
835 836
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
837
    for (int i = fromIndex; i < toIndex; i++)
838
      a[i] = val;
Tom Tromey committed
839 840 841
  }

  /**
842
   * Fill an array with a float value.
Tom Tromey committed
843 844 845 846
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
847
  public static void fill(float[] a, float val)
848
  {
Tom Tromey committed
849 850 851 852
    fill(a, 0, a.length, val);
  }

  /**
853
   * Fill a range of an array with a float value.
Tom Tromey committed
854 855 856 857 858
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
859 860 861
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
862
   */
863
  public static void fill(float[] a, int fromIndex, int toIndex, float val)
864
  {
865 866
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
867
    for (int i = fromIndex; i < toIndex; i++)
868
      a[i] = val;
Tom Tromey committed
869 870 871
  }

  /**
872
   * Fill an array with a double value.
Tom Tromey committed
873 874 875 876
   *
   * @param a the array to fill
   * @param val the value to fill it with
   */
877
  public static void fill(double[] a, double val)
878
  {
Tom Tromey committed
879 880 881 882
    fill(a, 0, a.length, val);
  }

  /**
883
   * Fill a range of an array with a double value.
Tom Tromey committed
884 885 886 887 888
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
889 890 891
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
892
   */
893
  public static void fill(double[] a, int fromIndex, int toIndex, double val)
894
  {
895 896
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
897
    for (int i = fromIndex; i < toIndex; i++)
898
      a[i] = val;
Tom Tromey committed
899 900 901 902 903 904 905
  }

  /**
   * Fill an array with an Object value.
   *
   * @param a the array to fill
   * @param val the value to fill it with
906 907
   * @throws ClassCastException if val is not an instance of the element
   *         type of a.
Tom Tromey committed
908
   */
909
  public static void fill(Object[] a, Object val)
910
  {
Tom Tromey committed
911 912 913 914 915 916 917 918 919 920
    fill(a, 0, a.length, val);
  }

  /**
   * Fill a range of an array with an Object value.
   *
   * @param a the array to fill
   * @param fromIndex the index to fill from, inclusive
   * @param toIndex the index to fill to, exclusive
   * @param val the value to fill with
921 922 923 924 925
   * @throws ClassCastException if val is not an instance of the element
   *         type of a.
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
Tom Tromey committed
926
   */
927
  public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
928
  {
929 930
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
931
    for (int i = fromIndex; i < toIndex; i++)
932
      a[i] = val;
Tom Tromey committed
933 934
  }

935 936

// sort
Tom Tromey committed
937
  // Thanks to Paul Fisher <rao@gnu.org> for finding this quicksort algorithm
938 939 940 941 942 943
  // as specified by Sun and porting it to Java. The algorithm is an optimised
  // quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
  // "Engineering a Sort Function", Software-Practice and Experience, Vol.
  // 23(11) P. 1249-1265 (November 1993). This algorithm gives n*log(n)
  // performance on many arrays that would take quadratic time with a standard
  // quicksort.
Tom Tromey committed
944 945

  /**
946 947
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
Tom Tromey committed
948
   *
949
   * @param a the byte array to sort
Tom Tromey committed
950
   */
951
  public static void sort(byte[] a)
952
  {
Tom Tromey committed
953 954 955
    qsort(a, 0, a.length);
  }

956 957 958 959 960 961 962 963 964 965 966
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the byte array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
967 968
  public static void sort(byte[] a, int fromIndex, int toIndex)
  {
969 970 971
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
Tom Tromey committed
972 973
  }

974 975 976 977 978 979 980 981 982 983
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, byte[] d)
984
  {
985 986 987
    return (d[a] < d[b]
            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
Tom Tromey committed
988
  }
989

990 991 992 993 994 995 996 997
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, byte[] a)
998
  {
Tom Tromey committed
999 1000 1001 1002 1003
    byte c = a[i];
    a[i] = a[j];
    a[j] = c;
  }

1004 1005 1006 1007 1008 1009 1010 1011 1012
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, byte[] a)
1013
  {
1014
    for ( ; n > 0; i++, j++, n--)
Tom Tromey committed
1015 1016 1017 1018
      swap(i, j, a);
  }

  /**
1019
   * Performs a recursive modified quicksort.
Tom Tromey committed
1020 1021
   *
   * @param a the array to sort
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
   */
  private static void qsort(byte[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
            swap(j, j - 1, array);
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1044
        lo = med3(lo, lo + s, lo + 2 * s, array);
1045
        mid = med3(mid - s, mid, mid + s, array);
1046
        hi = med3(hi - 2 * s, hi - s, hi, array);
1047 1048 1049 1050 1051 1052 1053 1054
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1055 1056
    a = b = from;
    c = d = from + count - 1;
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = array[b] - array[from]) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = array[c] - array[from]) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1090
    hi = from + count;
1091 1092 1093 1094 1095
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1096
    vecswap(b, hi - span, span, array);
1097 1098 1099 1100 1101 1102 1103

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1104
      qsort(array, hi - span, span);
1105 1106 1107 1108 1109 1110 1111
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the char array to sort
Tom Tromey committed
1112
   */
1113
  public static void sort(char[] a)
1114
  {
Tom Tromey committed
1115 1116 1117
    qsort(a, 0, a.length);
  }

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the char array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
1129 1130
  public static void sort(char[] a, int fromIndex, int toIndex)
  {
1131 1132 1133
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
1134 1135
  }

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, char[] d)
1146
  {
1147 1148 1149
    return (d[a] < d[b]
            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
Tom Tromey committed
1150
  }
1151

1152 1153 1154 1155 1156 1157 1158 1159
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, char[] a)
1160
  {
Tom Tromey committed
1161 1162 1163 1164 1165
    char c = a[i];
    a[i] = a[j];
    a[j] = c;
  }

1166 1167 1168 1169 1170 1171 1172 1173 1174
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, char[] a)
1175
  {
1176
    for ( ; n > 0; i++, j++, n--)
Tom Tromey committed
1177 1178 1179 1180
      swap(i, j, a);
  }

  /**
1181
   * Performs a recursive modified quicksort.
Tom Tromey committed
1182 1183
   *
   * @param a the array to sort
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
   */
  private static void qsort(char[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
            swap(j, j - 1, array);
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1206
        lo = med3(lo, lo + s, lo + 2 * s, array);
1207
        mid = med3(mid - s, mid, mid + s, array);
1208
        hi = med3(hi - 2 * s, hi - s, hi, array);
1209 1210 1211 1212 1213 1214 1215 1216
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1217 1218
    a = b = from;
    c = d = from + count - 1;
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = array[b] - array[from]) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = array[c] - array[from]) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1252
    hi = from + count;
1253 1254 1255 1256 1257
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1258
    vecswap(b, hi - span, span, array);
1259 1260 1261 1262 1263 1264 1265

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1266
      qsort(array, hi - span, span);
1267 1268 1269 1270 1271 1272 1273
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the short array to sort
Tom Tromey committed
1274
   */
1275
  public static void sort(short[] a)
1276
  {
Tom Tromey committed
1277 1278 1279
    qsort(a, 0, a.length);
  }

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the short array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
  public static void sort(short[] a, int fromIndex, int toIndex)
1292
  {
1293 1294 1295
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
Tom Tromey committed
1296 1297
  }

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, short[] d)
1308
  {
1309 1310 1311
    return (d[a] < d[b]
            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
Tom Tromey committed
1312
  }
1313

1314 1315 1316 1317 1318 1319 1320 1321
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, short[] a)
1322
  {
1323
    short c = a[i];
Tom Tromey committed
1324 1325 1326 1327
    a[i] = a[j];
    a[j] = c;
  }

1328 1329 1330 1331 1332 1333 1334 1335 1336
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, short[] a)
1337
  {
1338
    for ( ; n > 0; i++, j++, n--)
Tom Tromey committed
1339 1340 1341 1342
      swap(i, j, a);
  }

  /**
1343
   * Performs a recursive modified quicksort.
Tom Tromey committed
1344 1345
   *
   * @param a the array to sort
1346 1347
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
Tom Tromey committed
1348
   */
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
  private static void qsort(short[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
            swap(j, j - 1, array);
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1368
        lo = med3(lo, lo + s, lo + 2 * s, array);
1369
        mid = med3(mid - s, mid, mid + s, array);
1370
        hi = med3(hi - 2 * s, hi - s, hi, array);
1371 1372 1373 1374 1375 1376 1377 1378
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1379 1380
    a = b = from;
    c = d = from + count - 1;
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = array[b] - array[from]) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = array[c] - array[from]) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1414
    hi = from + count;
1415 1416 1417 1418 1419
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1420
    vecswap(b, hi - span, span, array);
1421 1422 1423 1424 1425 1426 1427

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1428
      qsort(array, hi - span, span);
1429 1430 1431 1432 1433 1434 1435 1436 1437
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the int array to sort
   */
  public static void sort(int[] a)
1438
  {
Tom Tromey committed
1439 1440 1441
    qsort(a, 0, a.length);
  }

1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the int array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
  public static void sort(int[] a, int fromIndex, int toIndex)
1454
  {
1455 1456 1457
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
1458 1459
  }

1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, int[] d)
1470
  {
1471 1472 1473
    return (d[a] < d[b]
            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
Tom Tromey committed
1474 1475
  }

1476 1477 1478 1479 1480 1481 1482 1483
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, int[] a)
1484
  {
1485
    int c = a[i];
Tom Tromey committed
1486 1487 1488 1489
    a[i] = a[j];
    a[j] = c;
  }

1490 1491 1492 1493 1494 1495 1496 1497 1498
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, int[] a)
1499
  {
1500 1501
    for ( ; n > 0; i++, j++, n--)
      swap(i, j, a);
Tom Tromey committed
1502 1503
  }

1504 1505 1506 1507 1508 1509 1510 1511
  /**
   * Compares two integers in natural order, since a - b is inadequate.
   *
   * @param a the first int
   * @param b the second int
   * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
   */
  private static int compare(int a, int b)
1512
  {
1513
    return a < b ? -1 : a == b ? 0 : 1;
Tom Tromey committed
1514 1515 1516
  }

  /**
1517
   * Performs a recursive modified quicksort.
Tom Tromey committed
1518 1519
   *
   * @param a the array to sort
1520 1521
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
Tom Tromey committed
1522
   */
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
  private static void qsort(int[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
            swap(j, j - 1, array);
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1542
        lo = med3(lo, lo + s, lo + 2 * s, array);
1543
        mid = med3(mid - s, mid, mid + s, array);
1544
        hi = med3(hi - 2 * s, hi - s, hi, array);
1545 1546 1547 1548 1549 1550 1551 1552
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1553 1554
    a = b = from;
    c = d = from + count - 1;
1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = compare(array[b], array[from])) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = compare(array[c], array[from])) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1588
    hi = from + count;
1589 1590 1591 1592 1593
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1594
    vecswap(b, hi - span, span, array);
1595 1596 1597 1598 1599 1600 1601

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1602
      qsort(array, hi - span, span);
1603 1604 1605 1606 1607 1608 1609 1610 1611
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the long array to sort
   */
  public static void sort(long[] a)
1612
  {
Tom Tromey committed
1613 1614 1615
    qsort(a, 0, a.length);
  }

1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the long array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
  public static void sort(long[] a, int fromIndex, int toIndex)
1628
  {
1629 1630 1631
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
1632 1633
  }

1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, long[] d)
1644
  {
1645 1646 1647
    return (d[a] < d[b]
            ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
            : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
Tom Tromey committed
1648
  }
1649

1650 1651 1652 1653 1654 1655 1656 1657
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, long[] a)
1658
  {
1659
    long c = a[i];
Tom Tromey committed
1660 1661 1662 1663
    a[i] = a[j];
    a[j] = c;
  }

1664 1665 1666 1667 1668 1669 1670 1671 1672
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, long[] a)
1673
  {
1674 1675
    for ( ; n > 0; i++, j++, n--)
      swap(i, j, a);
Tom Tromey committed
1676 1677
  }

1678 1679 1680 1681 1682 1683 1684 1685
  /**
   * Compares two longs in natural order, since a - b is inadequate.
   *
   * @param a the first long
   * @param b the second long
   * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
   */
  private static int compare(long a, long b)
1686
  {
1687
    return a < b ? -1 : a == b ? 0 : 1;
Tom Tromey committed
1688 1689 1690
  }

  /**
1691
   * Performs a recursive modified quicksort.
Tom Tromey committed
1692 1693
   *
   * @param a the array to sort
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
   */
  private static void qsort(long[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
            swap(j, j - 1, array);
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1716
        lo = med3(lo, lo + s, lo + 2 * s, array);
1717
        mid = med3(mid - s, mid, mid + s, array);
1718
        hi = med3(hi - 2 * s, hi - s, hi, array);
1719 1720 1721 1722 1723 1724 1725 1726
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1727 1728
    a = b = from;
    c = d = from + count - 1;
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = compare(array[b], array[from])) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = compare(array[c], array[from])) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1762
    hi = from + count;
1763 1764 1765 1766 1767
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1768
    vecswap(b, hi - span, span, array);
1769 1770 1771 1772 1773 1774 1775

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1776
      qsort(array, hi - span, span);
1777 1778 1779 1780 1781 1782 1783
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the float array to sort
Tom Tromey committed
1784
   */
1785
  public static void sort(float[] a)
1786
  {
Tom Tromey committed
1787 1788 1789
    qsort(a, 0, a.length);
  }

1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the float array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
  public static void sort(float[] a, int fromIndex, int toIndex)
1802
  {
1803 1804 1805
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
1806 1807
  }

1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, float[] d)
1818
  {
1819 1820 1821 1822 1823
    return (Float.compare(d[a], d[b]) < 0
            ? (Float.compare(d[b], d[c]) < 0 ? b
               : Float.compare(d[a], d[c]) < 0 ? c : a)
            : (Float.compare(d[b], d[c]) > 0 ? b
               : Float.compare(d[a], d[c]) > 0 ? c : a));
Tom Tromey committed
1824
  }
1825

1826 1827 1828 1829 1830 1831 1832 1833
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, float[] a)
1834
  {
1835
    float c = a[i];
Tom Tromey committed
1836 1837 1838 1839
    a[i] = a[j];
    a[j] = c;
  }

1840 1841 1842 1843 1844 1845 1846 1847 1848
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, float[] a)
1849
  {
1850
    for ( ; n > 0; i++, j++, n--)
Tom Tromey committed
1851 1852 1853 1854
      swap(i, j, a);
  }

  /**
1855
   * Performs a recursive modified quicksort.
Tom Tromey committed
1856 1857
   *
   * @param a the array to sort
1858 1859
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
Tom Tromey committed
1860
   */
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
  private static void qsort(float[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i;
               j > 0 && Float.compare(array[j - 1], array[j]) > 0;
               j--)
            {
              swap(j, j - 1, array);
            }
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
1884
        lo = med3(lo, lo + s, lo + 2 * s, array);
1885
        mid = med3(mid - s, mid, mid + s, array);
1886
        hi = med3(hi - 2 * s, hi - s, hi, array);
1887 1888 1889 1890 1891 1892 1893 1894
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
1895 1896
    a = b = from;
    c = d = from + count - 1;
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = Float.compare(array[b], array[from])) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = Float.compare(array[c], array[from])) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
1930
    hi = from + count;
1931 1932 1933 1934 1935
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
1936
    vecswap(b, hi - span, span, array);
1937 1938 1939 1940 1941 1942 1943

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
1944
      qsort(array, hi - span, span);
1945 1946 1947 1948 1949 1950 1951 1952 1953
  }

  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the double array to sort
   */
  public static void sort(double[] a)
1954
  {
Tom Tromey committed
1955 1956 1957
    qsort(a, 0, a.length);
  }

1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
  /**
   * Performs a stable sort on the elements, arranging them according to their
   * natural order.
   *
   * @param a the double array to sort
   * @param fromIndex the first index to sort (inclusive)
   * @param toIndex the last index to sort (exclusive)
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
   * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
   *         || toIndex &gt; a.length
   */
  public static void sort(double[] a, int fromIndex, int toIndex)
1970
  {
1971 1972 1973
    if (fromIndex > toIndex)
      throw new IllegalArgumentException();
    qsort(a, fromIndex, toIndex - fromIndex);
Tom Tromey committed
1974 1975
  }

1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
  /**
   * Finds the index of the median of three array elements.
   *
   * @param a the first index
   * @param b the second index
   * @param c the third index
   * @param d the array
   * @return the index (a, b, or c) which has the middle value of the three
   */
  private static int med3(int a, int b, int c, double[] d)
1986
  {
1987 1988 1989 1990 1991
    return (Double.compare(d[a], d[b]) < 0
            ? (Double.compare(d[b], d[c]) < 0 ? b
               : Double.compare(d[a], d[c]) < 0 ? c : a)
            : (Double.compare(d[b], d[c]) > 0 ? b
               : Double.compare(d[a], d[c]) > 0 ? c : a));
Tom Tromey committed
1992
  }
1993

1994 1995 1996 1997 1998 1999 2000 2001
  /**
   * Swaps the elements at two locations of an array
   *
   * @param i the first index
   * @param j the second index
   * @param a the array
   */
  private static void swap(int i, int j, double[] a)
2002
  {
2003
    double c = a[i];
Tom Tromey committed
2004 2005 2006 2007
    a[i] = a[j];
    a[j] = c;
  }

2008 2009 2010 2011 2012 2013 2014 2015 2016
  /**
   * Swaps two ranges of an array.
   *
   * @param i the first range start
   * @param j the second range start
   * @param n the element count
   * @param a the array
   */
  private static void vecswap(int i, int j, int n, double[] a)
2017
  {
2018
    for ( ; n > 0; i++, j++, n--)
Tom Tromey committed
2019 2020 2021 2022
      swap(i, j, a);
  }

  /**
2023 2024 2025 2026 2027
   * Performs a recursive modified quicksort.
   *
   * @param a the array to sort
   * @param from the start index (inclusive)
   * @param count the number of elements to sort
Tom Tromey committed
2028
   */
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051
  private static void qsort(double[] array, int from, int count)
  {
    // Use an insertion sort on small arrays.
    if (count <= 7)
      {
        for (int i = from + 1; i < from + count; i++)
          for (int j = i;
               j > 0 && Double.compare(array[j - 1], array[j]) > 0;
               j--)
            {
              swap(j, j - 1, array);
            }
        return;
      }

    // Determine a good median element.
    int mid = count / 2;
    int lo = from;
    int hi = from + count - 1;

    if (count > 40)
      { // big arrays, pseudomedian of 9
        int s = count / 8;
2052
        lo = med3(lo, lo + s, lo + 2 * s, array);
2053
        mid = med3(mid - s, mid, mid + s, array);
2054
        hi = med3(hi - 2 * s, hi - s, hi, array);
2055 2056 2057 2058 2059 2060 2061 2062
      }
    mid = med3(lo, mid, hi, array);

    int a, b, c, d;
    int comp;

    // Pull the median element out of the fray, and use it as a pivot.
    swap(from, mid, array);
2063 2064
    a = b = from;
    c = d = from + count - 1;
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097

    // Repeatedly move b and c to each other, swapping elements so
    // that all elements before index b are less than the pivot, and all
    // elements after index c are greater than the pivot. a and b track
    // the elements equal to the pivot.
    while (true)
      {
        while (b <= c && (comp = Double.compare(array[b], array[from])) <= 0)
          {
            if (comp == 0)
              {
                swap(a, b, array);
                a++;
              }
            b++;
          }
        while (c >= b && (comp = Double.compare(array[c], array[from])) >= 0)
          {
            if (comp == 0)
              {
                swap(c, d, array);
                d--;
              }
            c--;
          }
        if (b > c)
          break;
        swap(b, c, array);
        b++;
        c--;
      }

    // Swap pivot(s) back in place, the recurse on left and right sections.
2098
    hi = from + count;
2099 2100 2101 2102 2103
    int span;
    span = Math.min(a - from, b - a);
    vecswap(from, b - span, span, array);

    span = Math.min(d - c, hi - d - 1);
2104
    vecswap(b, hi - span, span, array);
2105 2106 2107 2108 2109 2110 2111

    span = b - a;
    if (span > 1)
      qsort(array, from, span);

    span = d - c;
    if (span > 1)
2112
      qsort(array, hi - span, span);
Tom Tromey committed
2113 2114 2115 2116 2117 2118 2119
  }

  /**
   * Sort an array of Objects according to their natural ordering. The sort is
   * guaranteed to be stable, that is, equal elements will not be reordered.
   * The sort algorithm is a mergesort with the merge omitted if the last
   * element of one half comes before the first element of the other half. This
2120
   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
Tom Tromey committed
2121 2122 2123
   * copy of the array.
   *
   * @param a the array to be sorted
2124 2125 2126 2127 2128
   * @throws ClassCastException if any two elements are not mutually
   *         comparable
   * @throws NullPointerException if an element is null (since
   *         null.compareTo cannot work)
   * @see Comparable
Tom Tromey committed
2129
   */
2130
  public static void sort(Object[] a)
2131
  {
2132
    sort(a, 0, a.length, null);
Tom Tromey committed
2133 2134 2135 2136 2137 2138 2139
  }

  /**
   * Sort an array of Objects according to a Comparator. The sort is
   * guaranteed to be stable, that is, equal elements will not be reordered.
   * The sort algorithm is a mergesort with the merge omitted if the last
   * element of one half comes before the first element of the other half. This
2140
   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
Tom Tromey committed
2141 2142 2143
   * copy of the array.
   *
   * @param a the array to be sorted
2144 2145 2146 2147 2148 2149
   * @param c a Comparator to use in sorting the array; or null to indicate
   *        the elements' natural order
   * @throws ClassCastException if any two elements are not mutually
   *         comparable by the Comparator provided
   * @throws NullPointerException if a null element is compared with natural
   *         ordering (only possible when c is null)
Tom Tromey committed
2150
   */
2151
  public static void sort(Object[] a, Comparator c)
2152
  {
2153
    sort(a, 0, a.length, c);
Tom Tromey committed
2154 2155 2156 2157 2158 2159 2160
  }

  /**
   * Sort an array of Objects according to their natural ordering. The sort is
   * guaranteed to be stable, that is, equal elements will not be reordered.
   * The sort algorithm is a mergesort with the merge omitted if the last
   * element of one half comes before the first element of the other half. This
2161
   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
Tom Tromey committed
2162 2163 2164
   * copy of the array.
   *
   * @param a the array to be sorted
2165 2166 2167 2168 2169 2170
   * @param fromIndex the index of the first element to be sorted
   * @param toIndex the index of the last element to be sorted plus one
   * @throws ClassCastException if any two elements are not mutually
   *         comparable
   * @throws NullPointerException if an element is null (since
   *         null.compareTo cannot work)
2171
   * @throws ArrayIndexOutOfBoundsException if fromIndex and toIndex
2172
   *         are not in range.
2173
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
Tom Tromey committed
2174
   */
2175
  public static void sort(Object[] a, int fromIndex, int toIndex)
2176
  {
2177
    sort(a, fromIndex, toIndex, null);
Tom Tromey committed
2178 2179 2180 2181 2182 2183 2184
  }

  /**
   * Sort an array of Objects according to a Comparator. The sort is
   * guaranteed to be stable, that is, equal elements will not be reordered.
   * The sort algorithm is a mergesort with the merge omitted if the last
   * element of one half comes before the first element of the other half. This
2185
   * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
Tom Tromey committed
2186 2187 2188
   * copy of the array.
   *
   * @param a the array to be sorted
2189 2190 2191 2192 2193 2194
   * @param fromIndex the index of the first element to be sorted
   * @param toIndex the index of the last element to be sorted plus one
   * @param c a Comparator to use in sorting the array; or null to indicate
   *        the elements' natural order
   * @throws ClassCastException if any two elements are not mutually
   *         comparable by the Comparator provided
2195
   * @throws ArrayIndexOutOfBoundsException if fromIndex and toIndex
2196
   *         are not in range.
2197
   * @throws IllegalArgumentException if fromIndex &gt; toIndex
2198 2199
   * @throws NullPointerException if a null element is compared with natural
   *         ordering (only possible when c is null)
Tom Tromey committed
2200
   */
2201
  public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c)
2202
  {
Tom Tromey committed
2203
    if (fromIndex > toIndex)
2204
      throw new IllegalArgumentException("fromIndex " + fromIndex
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316
                                         + " > toIndex " + toIndex);

    // In general, the code attempts to be simple rather than fast, the
    // idea being that a good optimising JIT will be able to optimise it
    // better than I can, and if I try it will make it more confusing for
    // the JIT. First presort the array in chunks of length 6 with insertion
    // sort. A mergesort would give too much overhead for this length.
    for (int chunk = fromIndex; chunk < toIndex; chunk += 6)
      {
        int end = Math.min(chunk + 6, toIndex);
        for (int i = chunk + 1; i < end; i++)
          {
            if (Collections.compare(a[i - 1], a[i], c) > 0)
              {
                // not already sorted
                int j = i;
                Object elem = a[j];
                do
                  {
                    a[j] = a[j - 1];
                    j--;
                  }
                while (j > chunk
                       && Collections.compare(a[j - 1], elem, c) > 0);
                a[j] = elem;
              }
          }
      }

    int len = toIndex - fromIndex;
    // If length is smaller or equal 6 we are done.
    if (len <= 6)
      return;

    Object[] src = a;
    Object[] dest = new Object[len];
    Object[] t = null; // t is used for swapping src and dest

    // The difference of the fromIndex of the src and dest array.
    int srcDestDiff = -fromIndex;

    // The merges are done in this loop
    for (int size = 6; size < len; size <<= 1)
      {
        for (int start = fromIndex; start < toIndex; start += size << 1)
          {
            // mid is the start of the second sublist;
            // end the start of the next sublist (or end of array).
            int mid = start + size;
            int end = Math.min(toIndex, mid + size);

            // The second list is empty or the elements are already in
            // order - no need to merge
            if (mid >= end
                || Collections.compare(src[mid - 1], src[mid], c) <= 0)
              {
                System.arraycopy(src, start,
                                 dest, start + srcDestDiff, end - start);

                // The two halves just need swapping - no need to merge
              }
            else if (Collections.compare(src[start], src[end - 1], c) > 0)
              {
                System.arraycopy(src, start,
                                 dest, end - size + srcDestDiff, size);
                System.arraycopy(src, mid,
                                 dest, start + srcDestDiff, end - mid);

              }
            else
              {
                // Declare a lot of variables to save repeating
                // calculations.  Hopefully a decent JIT will put these
                // in registers and make this fast
                int p1 = start;
                int p2 = mid;
                int i = start + srcDestDiff;

                // The main merge loop; terminates as soon as either
                // half is ended
                while (p1 < mid && p2 < end)
                  {
                    dest[i++] =
                      src[(Collections.compare(src[p1], src[p2], c) <= 0
                           ? p1++ : p2++)];
                  }

                // Finish up by copying the remainder of whichever half
                // wasn't finished.
                if (p1 < mid)
                  System.arraycopy(src, p1, dest, i, mid - p1);
                else
                  System.arraycopy(src, p2, dest, i, end - p2);
              }
          }
        // swap src and dest ready for the next merge
        t = src;
        src = dest;
        dest = t;
        fromIndex += srcDestDiff;
        toIndex += srcDestDiff;
        srcDestDiff = -srcDestDiff;
      }

    // make sure the result ends up back in the right place.  Note
    // that src and dest may have been swapped above, so src
    // contains the sorted array.
    if (src != a)
      {
        // Note that fromIndex == 0.
        System.arraycopy(src, 0, a, srcDestDiff, toIndex);
      }
Tom Tromey committed
2317 2318 2319 2320 2321
  }

  /**
   * Returns a list "view" of the specified array. This method is intended to
   * make it easy to use the Collections API with existing array-based APIs and
2322 2323 2324 2325
   * programs. Changes in the list or the array show up in both places. The
   * list does not support element addition or removal, but does permit
   * value modification. The returned list implements both Serializable and
   * RandomAccess.
Tom Tromey committed
2326 2327
   *
   * @param a the array to return a view of
2328 2329 2330 2331
   * @return a fixed-size list, changes to which "write through" to the array
   * @see Serializable
   * @see RandomAccess
   * @see Arrays.ArrayList
Tom Tromey committed
2332
   */
2333
  public static List asList(final Object[] a)
2334
  {
2335
    return new Arrays.ArrayList(a);
Tom Tromey committed
2336 2337 2338
  }

  /**
2339 2340 2341 2342 2343 2344 2345
   * Inner class used by {@link #asList(Object[])} to provide a list interface
   * to an array. The name, though it clashes with java.util.ArrayList, is
   * Sun's choice for Serialization purposes. Element addition and removal
   * is prohibited, but values can be modified.
   *
   * @author Eric Blake <ebb9@email.byu.edu>
   * @status updated to 1.4
Tom Tromey committed
2346
   */
2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
  private static final class ArrayList extends AbstractList
    implements Serializable, RandomAccess
  {
    // We override the necessary methods, plus others which will be much
    // more efficient with direct iteration rather than relying on iterator().

    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -2764017481108945198L;

    /**
     * The array we are viewing.
     * @serial the array
     */
    private final Object[] a;

    /**
     * Construct a list view of the array.
     * @param a the array to view
     * @throws NullPointerException if a is null
     */
    ArrayList(Object[] a)
2370
    {
2371 2372 2373
      // We have to explicitly check.
      if (a == null)
        throw new NullPointerException();
Tom Tromey committed
2374 2375 2376
      this.a = a;
    }

2377 2378
    public Object get(int index)
    {
Tom Tromey committed
2379 2380 2381
      return a[index];
    }

2382 2383
    public int size()
    {
Tom Tromey committed
2384 2385 2386
      return a.length;
    }

2387 2388
    public Object set(int index, Object element)
    {
Tom Tromey committed
2389 2390 2391 2392 2393
      Object old = a[index];
      a[index] = element;
      return old;
    }

2394 2395 2396 2397 2398 2399 2400 2401 2402
    public boolean contains(Object o)
    {
      return lastIndexOf(o) >= 0;
    }

    public int indexOf(Object o)
    {
      int size = a.length;
      for (int i = 0; i < size; i++)
Mark Wielaard committed
2403
        if (this.equals(o, a[i]))
2404 2405 2406 2407 2408 2409 2410 2411
          return i;
      return -1;
    }

    public int lastIndexOf(Object o)
    {
      int i = a.length;
      while (--i >= 0)
Mark Wielaard committed
2412
        if (this.equals(o, a[i]))
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433
          return i;
      return -1;
    }

    public Object[] toArray()
    {
      return (Object[]) a.clone();
    }

    public Object[] toArray(Object[] array)
    {
      int size = a.length;
      if (array.length < size)
        array = (Object[])
          Array.newInstance(array.getClass().getComponentType(), size);
      else if (array.length > size)
        array[size] = null;

      System.arraycopy(a, 0, array, 0, size);
      return array;
    }
Tom Tromey committed
2434 2435
  }
}