/[classpath]/classpath/java/util/Arrays.java
ViewVC logotype

Diff of /classpath/java/util/Arrays.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10 by bryce, Wed Feb 7 09:33:38 2001 UTC revision 1.11 by ericb, Fri Oct 19 00:17:44 2001 UTC
# Line 1  Line 1 
1  /* Arrays.java -- Utility class with methods to operate on arrays  /* Arrays.java -- Utility class with methods to operate on arrays
2     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 25  This exception does not however invalida Line 25  This exception does not however invalida
25  executable file might be covered by the GNU General Public License. */  executable file might be covered by the GNU General Public License. */
26    
27    
 // TO DO:  
 // ~ Fix the behaviour of sort and binarySearch as applied to float and double  
 //   arrays containing NaN values. See the JDC, bug ID 4143272.  
   
28  package java.util;  package java.util;
29    
30    import java.io.Serializable;
31    import java.lang.reflect.Array;
32    
33  /**  /**
34   * This class contains various static utility methods performing operations on   * This class contains various static utility methods performing operations on
35   * arrays, and a method to provide a List "view" of an array to facilitate   * arrays, and a method to provide a List "view" of an array to facilitate
36   * using arrays with Collection-based APIs.   * using arrays with Collection-based APIs. All methods throw a
37     * {@link NullPointerException} if the parameter array is null.
38     * <p>
39     *
40     * Implementations may use their own algorithms, but must obey the general
41     * properties; for example, the sort must be stable and n*log(n) complexity.
42     * Sun's implementation of sort, and therefore ours, is a tuned quicksort,
43     * adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort
44     * Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265
45     * (November 1993). This algorithm offers n*log(n) performance on many data
46     * sets that cause other quicksorts to degrade to quadratic performance.
47     *
48     * @author Original author unknown
49     * @author Eric Blake <ebb9@email.byu.edu>
50     * @see Comparable
51     * @see Comparator
52     * @since 1.2
53     * @status updated to 1.4
54   */   */
55  public class Arrays  public class Arrays
56  {  {
# Line 45  public class Arrays Line 61  public class Arrays
61    {    {
62    }    }
63    
64    private static Comparator defaultComparator = new Comparator()  
65    {  // binarySearch
     public int compare(Object o1, Object o2)  
     {  
       return ((Comparable) o1).compareTo(o2);  
     }  
   };  
   
66    /**    /**
67     * Perform a binary search of a byte array for a key. The array must be     * Perform a binary search of a byte array for a key. The array must be
68     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
# Line 63  public class Arrays Line 73  public class Arrays
73     *     *
74     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
75     * @param key the value to search for     * @param key the value to search for
76     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
77     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
78     *   a.length if there is no such value.     *         a.length if there is no such value.
79     */     */
80    public static int binarySearch(byte[]a, byte key)    public static int binarySearch(byte[] a, byte key)
81    {    {
82      int low = 0;      int low = 0;
83      int hi = a.length - 1;      int hi = a.length - 1;
84      int mid = 0;      int mid = 0;
85      while (low <= hi)      while (low <= hi)
86        {        {
87          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
88          final byte d = a[mid];          final byte d = a[mid];
89          if (d == key)          if (d == key)
90            {            return mid;
91              return mid;          else if (d > key)
92            }            hi = mid - 1;
93          else if (d > key)          else
94            {            // This gets the insertion point right on the last loop.
95              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
96        }        }
97      return -mid - 1;      return -mid - 1;
98    }    }
# Line 103  public class Arrays Line 107  public class Arrays
107     *     *
108     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
109     * @param key the value to search for     * @param key the value to search for
110     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
111     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
112     *   a.length if there is no such value.     *         a.length if there is no such value.
113     */     */
114    public static int binarySearch(char[]a, char key)    public static int binarySearch(char[] a, char key)
115    {    {
116      int low = 0;      int low = 0;
117      int hi = a.length - 1;      int hi = a.length - 1;
118      int mid = 0;      int mid = 0;
119      while (low <= hi)      while (low <= hi)
120        {        {
121          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
122          final char d = a[mid];          final char d = a[mid];
123          if (d == key)          if (d == key)
124            {            return mid;
125              return mid;          else if (d > key)
126            }            hi = mid - 1;
127          else if (d > key)          else
128            {            // This gets the insertion point right on the last loop.
129              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
130        }        }
131      return -mid - 1;      return -mid - 1;
132    }    }
133    
134    /**    /**
135     * Perform a binary search of a double array for a key. The array must be     * Perform a binary search of a short array for a key. The array must be
136     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
137     * method is undefined, and may be an infinite loop. If the array contains     * method is undefined, and may be an infinite loop. If the array contains
138     * the key more than once, any one of them may be found. Note: although the     * the key more than once, any one of them may be found. Note: although the
# Line 143  public class Arrays Line 141  public class Arrays
141     *     *
142     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
143     * @param key the value to search for     * @param key the value to search for
144     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
145     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
146     *   a.length if there is no such value.     *         a.length if there is no such value.
147     */     */
148    public static int binarySearch(double[]a, double key)    public static int binarySearch(short[] a, short key)
149    {    {
150      int low = 0;      int low = 0;
151      int hi = a.length - 1;      int hi = a.length - 1;
152      int mid = 0;      int mid = 0;
153      while (low <= hi)      while (low <= hi)
154        {        {
155          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
156          final double d = a[mid];          final short d = a[mid];
157          if (d == key)          if (d == key)
158            {            return mid;
159              return mid;          else if (d > key)
160            }            hi = mid - 1;
161          else if (d > key)          else
162            {            // This gets the insertion point right on the last loop.
163              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
164        }        }
165      return -mid - 1;      return -mid - 1;
166    }    }
167    
168    /**    /**
169     * Perform a binary search of a float array for a key. The array must be     * Perform a binary search of an int array for a key. The array must be
170     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
171     * method is undefined, and may be an infinite loop. If the array contains     * method is undefined, and may be an infinite loop. If the array contains
172     * the key more than once, any one of them may be found. Note: although the     * the key more than once, any one of them may be found. Note: although the
# Line 183  public class Arrays Line 175  public class Arrays
175     *     *
176     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
177     * @param key the value to search for     * @param key the value to search for
178     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
179     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
180     *   a.length if there is no such value.     *         a.length if there is no such value.
181     */     */
182    public static int binarySearch(float[]a, float key)    public static int binarySearch(int[] a, int key)
183    {    {
184      int low = 0;      int low = 0;
185      int hi = a.length - 1;      int hi = a.length - 1;
186      int mid = 0;      int mid = 0;
187      while (low <= hi)      while (low <= hi)
188        {        {
189          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
190          final float d = a[mid];          final int d = a[mid];
191          if (d == key)          if (d == key)
192            {            return mid;
193              return mid;          else if (d > key)
194            }            hi = mid - 1;
195          else if (d > key)          else
196            {            // This gets the insertion point right on the last loop.
197              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
198        }        }
199      return -mid - 1;      return -mid - 1;
200    }    }
201    
202    /**    /**
203     * Perform a binary search of an int array for a key. The array must be     * Perform a binary search of a long array for a key. The array must be
204     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
205     * method is undefined, and may be an infinite loop. If the array contains     * method is undefined, and may be an infinite loop. If the array contains
206     * the key more than once, any one of them may be found. Note: although the     * the key more than once, any one of them may be found. Note: although the
# Line 223  public class Arrays Line 209  public class Arrays
209     *     *
210     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
211     * @param key the value to search for     * @param key the value to search for
212     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
213     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
214     *   a.length if there is no such value.     *         a.length if there is no such value.
215     */     */
216    public static int binarySearch(int[]a, int key)    public static int binarySearch(long[] a, long key)
217    {    {
218      int low = 0;      int low = 0;
219      int hi = a.length - 1;      int hi = a.length - 1;
220      int mid = 0;      int mid = 0;
221      while (low <= hi)      while (low <= hi)
222        {        {
223          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
224          final int d = a[mid];          final long d = a[mid];
225          if (d == key)          if (d == key)
226            {            return mid;
227              return mid;          else if (d > key)
228            }            hi = mid - 1;
229          else if (d > key)          else
230            {            // This gets the insertion point right on the last loop.
231              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
232        }        }
233      return -mid - 1;      return -mid - 1;
234    }    }
235    
236    /**    /**
237     * Perform a binary search of a long array for a key. The array must be     * Perform a binary search of a float array for a key. The array must be
238     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
239     * method is undefined, and may be an infinite loop. If the array contains     * method is undefined, and may be an infinite loop. If the array contains
240     * the key more than once, any one of them may be found. Note: although the     * the key more than once, any one of them may be found. Note: although the
# Line 263  public class Arrays Line 243  public class Arrays
243     *     *
244     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
245     * @param key the value to search for     * @param key the value to search for
246     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
247     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
248     *   a.length if there is no such value.     *         a.length if there is no such value.
249     */     */
250    public static int binarySearch(long[]a, long key)    public static int binarySearch(float[] a, float key)
251    {    {
252        // Must use Float.compare to take into account NaN, +-0.
253      int low = 0;      int low = 0;
254      int hi = a.length - 1;      int hi = a.length - 1;
255      int mid = 0;      int mid = 0;
256      while (low <= hi)      while (low <= hi)
257        {        {
258          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
259          final long d = a[mid];          final int r = Float.compare(a[mid], key);
260          if (d == key)          if (r == 0)
261            {            return mid;
262              return mid;          else if (r > 0)
263            }            hi = mid - 1;
264          else if (d > key)          else
265            {            // This gets the insertion point right on the last loop
266              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
267        }        }
268      return -mid - 1;      return -mid - 1;
269    }    }
270    
271    /**    /**
272     * Perform a binary search of a short array for a key. The array must be     * Perform a binary search of a double array for a key. The array must be
273     * sorted (as by the sort() method) - if it is not, the behaviour of this     * sorted (as by the sort() method) - if it is not, the behaviour of this
274     * method is undefined, and may be an infinite loop. If the array contains     * method is undefined, and may be an infinite loop. If the array contains
275     * the key more than once, any one of them may be found. Note: although the     * the key more than once, any one of them may be found. Note: although the
# Line 303  public class Arrays Line 278  public class Arrays
278     *     *
279     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
280     * @param key the value to search for     * @param key the value to search for
281     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
282     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
283     *   a.length if there is no such value.     *         a.length if there is no such value.
284     */     */
285    public static int binarySearch(short[]a, short key)    public static int binarySearch(double[] a, double key)
286    {    {
287        // Must use Double.compare to take into account NaN, +-0.
288      int low = 0;      int low = 0;
289      int hi = a.length - 1;      int hi = a.length - 1;
290      int mid = 0;      int mid = 0;
291      while (low <= hi)      while (low <= hi)
292        {        {
293          mid = (low + hi) >> 1;          mid = (low + hi) >> 1;
294          final short d = a[mid];          final int r = Double.compare(a[mid], key);
295          if (d == key)          if (r == 0)
296            {            return mid;
297              return mid;          else if (r > 0)
298            }            hi = mid - 1;
299          else if (d > key)          else
300            {            // This gets the insertion point right on the last loop
301              hi = mid - 1;            low = ++mid;
           }  
         else  
           {  
             // This gets the insertion point right on the last loop  
             low = ++mid;  
           }  
       }  
     return -mid - 1;  
   }  
   
   /**  
    * This method does the work for the Object binary search methods.  
    * @exception NullPointerException if the specified comparator is null.  
    * @exception ClassCastException if the objects are not comparable by c.  
    */  
   private static int objectSearch(Object[]a, Object key, final Comparator c)  
   {  
     int low = 0;  
     int hi = a.length - 1;  
     int mid = 0;  
     while (low <= hi)  
       {  
         mid = (low + hi) >> 1;  
         final int d = c.compare(key, a[mid]);  
         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;  
           }          
302        }        }
303      return -mid - 1;      return -mid - 1;
304    }    }
# Line 376  public class Arrays Line 315  public class Arrays
315     *     *
316     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
317     * @param key the value to search for     * @param key the value to search for
318     * @returns the index at which the key was found, or -n-1 if it was not     * @return the index at which the key was found, or -n-1 if it was not
319     *   found, where n is the index of the first value higher than key or     *         found, where n is the index of the first value higher than key or
320     *   a.length if there is no such value.     *         a.length if there is no such value.
321     * @exception ClassCastException if key could not be compared with one of the     * @throws ClassCastException if key could not be compared with one of the
322     *   elements of a     *         elements of a
323     * @exception NullPointerException if a null element has compareTo called     * @throws NullPointerException if a null element in a is compared
324     */     */
325    public static int binarySearch(Object[]a, Object key)    public static int binarySearch(Object[] a, Object key)
326    {    {
327      return objectSearch(a, key, defaultComparator);      return binarySearch(a, key, null);
328    }    }
329    
330    /**    /**
# Line 400  public class Arrays Line 339  public class Arrays
339     *     *
340     * @param a the array to search (must be sorted)     * @param a the array to search (must be sorted)
341     * @param key the value to search for     * @param key the value to search for
342     * @param c the comparator by which the array is sorted     * @param c the comparator by which the array is sorted; or null to
343     * @returns the index at which the key was found, or -n-1 if it was not     *        use the elements' natural order
344     *   found, where n is the index of the first value higher than key or     * @return the index at which the key was found, or -n-1 if it was not
345     *   a.length if there is no such value.     *         found, where n is the index of the first value higher than key or
346     * @exception ClassCastException if key could not be compared with one of the     *         a.length if there is no such value.
347     *   elements of a     * @throws ClassCastException if key could not be compared with one of the
348       *         elements of a
349       * @throws NullPointerException if a null element is compared with natural
350       *         ordering (only possible when c is null)
351     */     */
352    public static int binarySearch(Object[]a, Object key, Comparator c)    public static int binarySearch(Object[] a, Object key, Comparator c)
353    {    {
354      return objectSearch(a, key, c);      int low = 0;
355        int hi = a.length - 1;
356        int mid = 0;
357        while (low <= hi)
358          {
359            mid = (low + hi) >> 1;
360            final int d = Collections.compare(key, a[mid], c);
361            if (d == 0)
362              return mid;
363            else if (d < 0)
364              hi = mid - 1;
365            else
366              // This gets the insertion point right on the last loop
367              low = ++mid;
368          }
369        return -mid - 1;
370    }    }
371    
372    
373    // equals
374    /**    /**
375     * Compare two byte arrays for equality.     * Compare two boolean arrays for equality.
376     *     *
377     * @param a1 the first array to compare     * @param a1 the first array to compare
378     * @param a2 the second array to compare     * @param a2 the second array to compare
379     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
380     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
381     */     */
382    public static boolean equals(byte[]a1, byte[]a2)    public static boolean equals(boolean[] a1, boolean[] a2)
383    {    {
384      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
385      // catches the case that both are null.      // catches the case that both are null.
386      if (a1 == a2)      if (a1 == a2)
387        {        return true;
388          return true;  
       }  
         
389      try      try
390        {        {
391          // If they're the same length, test each element          // If they're the same length, test each element
392          if (a1.length == a2.length)          if (a1.length == a2.length)
393            {            {
394              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
395                {                if (a1[i] != a2[i])
396                  if (a1[i] != a2[i])                  return false;
397                    {              return true;
398                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
399        }        }
400      catch (NullPointerException e)      catch (NullPointerException e)
401        {        {
402            // If one is null, we get a harmless NullPointerException
403        }        }
404    
405      return false;      return false;
406    }    }
407    
408    /**    /**
409     * Compare two char arrays for equality.     * Compare two byte arrays for equality.
410     *     *
411     * @param a1 the first array to compare     * @param a1 the first array to compare
412     * @param a2 the second array to compare     * @param a2 the second array to compare
413     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
414     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
415     */     */
416    public static boolean equals(char[]a1, char[]a2)    public static boolean equals(byte[] a1, byte[] a2)
417    {    {
418      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
419      // catches the case that both are null.      // catches the case that both are null.
420      if (a1 == a2)      if (a1 == a2)
421        {        return true;
422          return true;  
       }  
         
423      try      try
424        {        {
425          // If they're the same length, test each element          // If they're the same length, test each element
426          if (a1.length == a2.length)          if (a1.length == a2.length)
427            {            {
428              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
429                {                if (a1[i] != a2[i])
430                  if (a1[i] != a2[i])                  return false;
431                    {              return true;
432                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
433        }        }
434      catch (NullPointerException e)      catch (NullPointerException e)
435        {        {
436            // If one is null, we get a harmless NullPointerException
437        }        }
   
438      return false;      return false;
439    }    }
440    
441    /**    /**
442     * Compare two double arrays for equality.     * Compare two char arrays for equality.
443     *     *
444     * @param a1 the first array to compare     * @param a1 the first array to compare
445     * @param a2 the second array to compare     * @param a2 the second array to compare
446     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
447     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
448     */     */
449    public static boolean equals(double[]a1, double[]a2)    public static boolean equals(char[] a1, char[] a2)
450    {    {
451      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
452      // catches the case that both are null.      // catches the case that both are null.
453      if (a1 == a2)      if (a1 == a2)
454        {        {
455          return true;          return true;
456        }        }
457          
458      try      try
459        {        {
460          // If they're the same length, test each element          // If they're the same length, test each element
461          if (a1.length == a2.length)          if (a1.length == a2.length)
462            {            {
463              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
464                {                if (a1[i] != a2[i])
465                  if (a1[i] != a2[i])                  return false;
466                    {              return true;
467                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
468        }        }
469      catch (NullPointerException e)      catch (NullPointerException e)
470        {        {
471            // If one is null, we get a harmless NullPointerException
472        }        }
   
473      return false;      return false;
474    }    }
475    
476    /**    /**
477     * Compare two float arrays for equality.     * Compare two short arrays for equality.
478     *     *
479     * @param a1 the first array to compare     * @param a1 the first array to compare
480     * @param a2 the second array to compare     * @param a2 the second array to compare
481     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
482     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
483     */     */
484    public static boolean equals(float[]a1, float[]a2)    public static boolean equals(short[] a1, short[] a2)
485    {    {
486      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
487      // catches the case that both are null.      // catches the case that both are null.
488      if (a1 == a2)      if (a1 == a2)
489        {        return true;
490          return true;  
       }  
         
491      try      try
492        {        {
493          // If they're the same length, test each element          // If they're the same length, test each element
494          if (a1.length == a2.length)          if (a1.length == a2.length)
495            {            {
496              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
497                {                if (a1[i] != a2[i])
498                  if (a1[i] != a2[i])                  return false;
499                    {              return true;
500                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
501        }        }
502      catch (NullPointerException e)      catch (NullPointerException e)
503        {        {
504            // If one is null, we get a harmless NullPointerException
505        }        }
   
506      return false;      return false;
507    }    }
508    
509    /**    /**
510     * Compare two long arrays for equality.     * Compare two int arrays for equality.
511     *     *
512     * @param a1 the first array to compare     * @param a1 the first array to compare
513     * @param a2 the second array to compare     * @param a2 the second array to compare
514     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
515     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
516     */     */
517    public static boolean equals(long[]a1, long[]a2)    public static boolean equals(int[] a1, int[] a2)
518    {    {
519      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
520      // catches the case that both are null.      // catches the case that both are null.
521      if (a1 == a2)      if (a1 == a2)
522        {        return true;
523          return true;  
       }  
         
524      try      try
525        {        {
526          // If they're the same length, test each element          // If they're the same length, test each element
527          if (a1.length == a2.length)          if (a1.length == a2.length)
528            {            {
529              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
530                {                if (a1[i] != a2[i])
531                  if (a1[i] != a2[i])                  return false;
532                    {              return true;
533                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
534        }        }
535      catch (NullPointerException e)      catch (NullPointerException e)
536        {        {
537            // If one is null, we get a harmless NullPointerException
538        }        }
   
539      return false;      return false;
540    }    }
541    
542    /**    /**
543     * Compare two short arrays for equality.     * Compare two long arrays for equality.
544     *     *
545     * @param a1 the first array to compare     * @param a1 the first array to compare
546     * @param a2 the second array to compare     * @param a2 the second array to compare
547     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
548     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
549     */     */
550    public static boolean equals(short[]a1, short[]a2)    public static boolean equals(long[] a1, long[] a2)
551    {    {
552      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
553      // catches the case that both are null.      // catches the case that both are null.
554      if (a1 == a2)      if (a1 == a2)
555        {        return true;
556          return true;  
       }  
         
557      try      try
558        {        {
559          // If they're the same length, test each element          // If they're the same length, test each element
560          if (a1.length == a2.length)          if (a1.length == a2.length)
561            {            {
562              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
563                {                if (a1[i] != a2[i])
564                  if (a1[i] != a2[i])                  return false;
565                    {              return true;
566                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
567        }        }
568      catch (NullPointerException e)      catch (NullPointerException e)
569        {        {
570            // If one is null, we get a harmless NullPointerException
571        }        }
   
572      return false;      return false;
573    }    }
574    
575    /**    /**
576     * Compare two boolean arrays for equality.     * Compare two float arrays for equality.
577     *     *
578     * @param a1 the first array to compare     * @param a1 the first array to compare
579     * @param a2 the second array to compare     * @param a2 the second array to compare
580     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
581     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
582     */     */
583    public static boolean equals(boolean[]a1, boolean[]a2)    public static boolean equals(float[] a1, float[] a2)
584    {    {
585      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
586      // catches the case that both are null.      // catches the case that both are null.
587      if (a1 == a2)      if (a1 == a2)
588        {        return true;
589          return true;  
590        }      // Must use Float.compare to take into account NaN, +-0.
         
591      try      try
592        {        {
593          // If they're the same length, test each element          // If they're the same length, test each element
594          if (a1.length == a2.length)          if (a1.length == a2.length)
595            {            {
596              for (int i = 0; i < a1.length; i++)              for (int i = a1.length - 1; i >= 0; i--)
597                {                if (Float.compare(a1[i], a2[i]) != 0)
598                  if (a1[i] != a2[i])                  return false;
599                    {              return true;
600                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
601        }        }
602      catch (NullPointerException e)      catch (NullPointerException e)
603        {        {
604            // If one is null, we get a harmless NullPointerException
605        }        }
   
606      return false;      return false;
607    }    }
608    
609    /**    /**
610     * Compare two int arrays for equality.     * Compare two double arrays for equality.
611     *     *
612     * @param a1 the first array to compare     * @param a1 the first array to compare
613     * @param a2 the second array to compare     * @param a2 the second array to compare
614     * @returns true if a1 and a2 are both null, or if a2 is of the same length     * @return true if a1 and a2 are both null, or if a2 is of the same length
615     *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]     *         as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
616     */     */
617    public static boolean equals(int[]a1, int[]a2)    public static boolean equals(double[] a1, double[] a2)
618    {    {
619      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
620      // catches the case that both are null.      // catches the case that both are null.
621      if (a1 == a2)      if (a1 == a2)
622        {        return true;
623          return true;  
624        }      // Must use Double.compare to take into account NaN, +-0.
         
625      try      try
626        {        {
627          // If they're the same length, test each element          // If they're the same length, test each element
628          if (a1.length == a2.length)          if (a1.length == a2.length)
629            {            {
630              for (int i = 0; i < a1.length; i++)              for (int i = a1.length - 1; i >= 0; i--)
631                {                if (Double.compare(a1[i], a2[i]) != 0)
632                  if (a1[i] != a2[i])                  return false;
633                    {              return true;
634                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
635        }        }
636      catch (NullPointerException e)      catch (NullPointerException e)
637        {        {
638            // If one is null, we get a harmless NullPointerException
639        }        }
   
640      return false;      return false;
641    }    }
642    
# Line 745  public class Arrays Line 645  public class Arrays
645     *     *
646     * @param a1 the first array to compare     * @param a1 the first array to compare
647     * @param a2 the second array to compare     * @param a2 the second array to compare
648     * @returns true if a1 and a2 are both null, or if a1 is of the same length     * @return true if a1 and a2 are both null, or if a1 is of the same length
649     *   as a2, and for each 0 <= i < a.length, a1[i] == null ? a2[i] == null :     *         as a2, and for each 0 <= i < a.length, a1[i] == null ?
650     *   a1[i].equals(a2[i]).     *         a2[i] == null : a1[i].equals(a2[i]).
651     */     */
652    public static boolean equals(Object[]a1, Object[]a2)    public static boolean equals(Object[] a1, Object[] a2)
653    {    {
654      // Quick test which saves comparing elements of the same array, and also      // Quick test which saves comparing elements of the same array, and also
655      // catches the case that both are null.      // catches the case that both are null.
656      if (a1 == a2)      if (a1 == a2)
657        {        return true;
658          return true;  
       }  
         
659      try      try
660        {        {
661          // If they're the same length, test each element          // If they're the same length, test each element
662          if (a1.length == a2.length)          if (a1.length == a2.length)
663            {            {
664              for (int i = 0; i < a1.length; i++)              for (int i = 0; i < a1.length; i++)
665                {                if (! AbstractCollection.equals(a1[i], a2[i]))
666                  if (!(a1[i] == null ? a2[i] == null : a1[i].equals(a2[i])))                  return false;
667                    {              return true;
668                      return false;            }
                   }  
               }  
             return true;  
           }  
   
         // If a1 == null or a2 == null but not both then we will get a NullPointer  
669        }        }
670      catch (NullPointerException e)      catch (NullPointerException e)
671        {        {
672            // If one is null, we get a harmless NullPointerException
673        }        }
   
674      return false;      return false;
675    }    }
676    
677    
678    // fill
679    /**    /**
680     * Fill an array with a boolean value.     * Fill an array with a boolean value.
681     *     *
682     * @param a the array to fill     * @param a the array to fill
683     * @param val the value to fill it with     * @param val the value to fill it with
684     */     */
685    public static void fill(boolean[]a, boolean val)    public static void fill(boolean[] a, boolean val)
686    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
687      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
688    }    }
689    
# Line 803  public class Arrays Line 694  public class Arrays
694     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
695     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
696     * @param val the value to fill with     * @param val the value to fill with
697       * @throws IllegalArgumentException if fromIndex &gt; toIndex
698       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
699       *         || toIndex &gt; a.length
700     */     */
701    public static void fill(boolean[]a, int fromIndex, int toIndex, boolean val)    public static void fill(boolean[] a, int fromIndex, int toIndex, boolean val)
702    {    {
703        if (fromIndex > toIndex)
704          throw new IllegalArgumentException();
705      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
706        {        a[i] = val;
         a[i] = val;  
       }  
707    }    }
708    
709    /**    /**
# Line 818  public class Arrays Line 712  public class Arrays
712     * @param a the array to fill     * @param a the array to fill
713     * @param val the value to fill it with     * @param val the value to fill it with
714     */     */
715    public static void fill(byte[]a, byte val)    public static void fill(byte[] a, byte val)
716    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
717      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
718    }    }
719    
# Line 833  public class Arrays Line 724  public class Arrays
724     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
725     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
726     * @param val the value to fill with     * @param val the value to fill with
727       * @throws IllegalArgumentException if fromIndex &gt; toIndex
728       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
729       *         || toIndex &gt; a.length
730     */     */
731    public static void fill(byte[]a, int fromIndex, int toIndex, byte val)    public static void fill(byte[] a, int fromIndex, int toIndex, byte val)
732    {    {
733        if (fromIndex > toIndex)
734          throw new IllegalArgumentException();
735      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
736        {        a[i] = val;
         a[i] = val;  
       }  
737    }    }
738    
739    /**    /**
# Line 848  public class Arrays Line 742  public class Arrays
742     * @param a the array to fill     * @param a the array to fill
743     * @param val the value to fill it with     * @param val the value to fill it with
744     */     */
745    public static void fill(char[]a, char val)    public static void fill(char[] a, char val)
746    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
747      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
748    }    }
749    
# Line 863  public class Arrays Line 754  public class Arrays
754     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
755     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
756     * @param val the value to fill with     * @param val the value to fill with
757       * @throws IllegalArgumentException if fromIndex &gt; toIndex
758       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
759       *         || toIndex &gt; a.length
760     */     */
761    public static void fill(char[]a, int fromIndex, int toIndex, char val)    public static void fill(char[] a, int fromIndex, int toIndex, char val)
762    {    {
763        if (fromIndex > toIndex)
764          throw new IllegalArgumentException();
765      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
766        {        a[i] = val;
         a[i] = val;  
       }  
767    }    }
768    
769    /**    /**
770     * Fill an array with a double value.     * Fill an array with a short value.
771     *     *
772     * @param a the array to fill     * @param a the array to fill
773     * @param val the value to fill it with     * @param val the value to fill it with
774     */     */
775    public static void fill(double[]a, double val)    public static void fill(short[] a, short val)
776    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
777      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
778    }    }
779    
780    /**    /**
781     * Fill a range of an array with a double value.     * Fill a range of an array with a short value.
782     *     *
783     * @param a the array to fill     * @param a the array to fill
784     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
785     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
786     * @param val the value to fill with     * @param val the value to fill with
787       * @throws IllegalArgumentException if fromIndex &gt; toIndex
788       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
789       *         || toIndex &gt; a.length
790     */     */
791    public static void fill(double[]a, int fromIndex, int toIndex, double val)    public static void fill(short[] a, int fromIndex, int toIndex, short val)
792    {    {
793        if (fromIndex > toIndex)
794          throw new IllegalArgumentException();
795      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
796        {        a[i] = val;
         a[i] = val;  
       }  
797    }    }
798    
799    /**    /**
800     * Fill an array with a float value.     * Fill an array with an int value.
801     *     *
802     * @param a the array to fill     * @param a the array to fill
803     * @param val the value to fill it with     * @param val the value to fill it with
804     */     */
805    public static void fill(float[]a, float val)    public static void fill(int[] a, int val)
806    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
807      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
808    }    }
809    
810    /**    /**
811     * Fill a range of an array with a float value.     * Fill a range of an array with an int value.
812     *     *
813     * @param a the array to fill     * @param a the array to fill
814     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
815     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
816     * @param val the value to fill with     * @param val the value to fill with
817       * @throws IllegalArgumentException if fromIndex &gt; toIndex
818       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
819       *         || toIndex &gt; a.length
820     */     */
821    public static void fill(float[]a, int fromIndex, int toIndex, float val)    public static void fill(int[] a, int fromIndex, int toIndex, int val)
822    {    {
823        if (fromIndex > toIndex)
824          throw new IllegalArgumentException();
825      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
826        {        a[i] = val;
         a[i] = val;  
       }  
827    }    }
828    
829    /**    /**
830     * Fill an array with an int value.     * Fill an array with a long value.
831     *     *
832     * @param a the array to fill     * @param a the array to fill
833     * @param val the value to fill it with     * @param val the value to fill it with
834     */     */
835    public static void fill(int[]a, int val)    public static void fill(long[] a, long val)
836    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
837      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
838    }    }
839    
840    /**    /**
841     * Fill a range of an array with an int value.     * Fill a range of an array with a long value.
842     *     *
843     * @param a the array to fill     * @param a the array to fill
844     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
845     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
846     * @param val the value to fill with     * @param val the value to fill with
847       * @throws IllegalArgumentException if fromIndex &gt; toIndex
848       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
849       *         || toIndex &gt; a.length
850     */     */
851    public static void fill(int[]a, int fromIndex, int toIndex, int val)    public static void fill(long[] a, int fromIndex, int toIndex, long val)
852    {    {
853        if (fromIndex > toIndex)
854          throw new IllegalArgumentException();
855      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
856        {        a[i] = val;
         a[i] = val;  
       }  
857    }    }
858    
859    /**    /**
860     * Fill an array with a long value.     * Fill an array with a float value.
861     *     *
862     * @param a the array to fill     * @param a the array to fill
863     * @param val the value to fill it with     * @param val the value to fill it with
864     */     */
865    public static void fill(long[]a, long val)    public static void fill(float[] a, float val)
866    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
867      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
868    }    }
869    
870    /**    /**
871     * Fill a range of an array with a long value.     * Fill a range of an array with a float value.
872     *     *
873     * @param a the array to fill     * @param a the array to fill
874     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
875     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
876     * @param val the value to fill with     * @param val the value to fill with
877       * @throws IllegalArgumentException if fromIndex &gt; toIndex
878       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
879       *         || toIndex &gt; a.length
880     */     */
881    public static void fill(long[]a, int fromIndex, int toIndex, long val)    public static void fill(float[] a, int fromIndex, int toIndex, float val)
882    {    {
883        if (fromIndex > toIndex)
884          throw new IllegalArgumentException();
885      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
886        {        a[i] = val;
         a[i] = val;  
       }  
887    }    }
888    
889    /**    /**
890     * Fill an array with a short value.     * Fill an array with a double value.
891     *     *
892     * @param a the array to fill     * @param a the array to fill
893     * @param val the value to fill it with     * @param val the value to fill it with
894     */     */
895    public static void fill(short[]a, short val)    public static void fill(double[] a, double val)
896    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
897      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
898    }    }
899    
900    /**    /**
901     * Fill a range of an array with a short value.     * Fill a range of an array with a double value.
902     *     *
903     * @param a the array to fill     * @param a the array to fill
904     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
905     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
906     * @param val the value to fill with     * @param val the value to fill with
907       * @throws IllegalArgumentException if fromIndex &gt; toIndex
908       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
909       *         || toIndex &gt; a.length
910     */     */
911    public static void fill(short[]a, int fromIndex, int toIndex, short val)    public static void fill(double[] a, int fromIndex, int toIndex, double val)
912    {    {
913        if (fromIndex > toIndex)
914          throw new IllegalArgumentException();
915      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
916        {        a[i] = val;
         a[i] = val;  
       }  
917    }    }
918    
919    /**    /**
# Line 1027  public class Arrays Line 921  public class Arrays
921     *     *
922     * @param a the array to fill     * @param a the array to fill
923     * @param val the value to fill it with     * @param val the value to fill it with
924     * @exception ClassCastException if val is not an instance of the element     * @throws ClassCastException if val is not an instance of the element
925     *   type of a.     *         type of a.
926     */     */
927    public static void fill(Object[]a, Object val)    public static void fill(Object[] a, Object val)
928    {    {
     // This implementation is slightly inefficient timewise, but the extra  
     // effort over inlining it is O(1) and small, and I refuse to repeat code  
     // if it can be helped.  
929      fill(a, 0, a.length, val);      fill(a, 0, a.length, val);
930    }    }
931    
# Line 1045  public class Arrays Line 936  public class Arrays
936     * @param fromIndex the index to fill from, inclusive     * @param fromIndex the index to fill from, inclusive
937     * @param toIndex the index to fill to, exclusive     * @param toIndex the index to fill to, exclusive
938     * @param val the value to fill with     * @param val the value to fill with
939     * @exception ClassCastException if val is not an instance of the element     * @throws ClassCastException if val is not an instance of the element
940     *   type of a.     *         type of a.
941       * @throws IllegalArgumentException if fromIndex &gt; toIndex
942       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
943       *         || toIndex &gt; a.length
944     */     */
945    public static void fill(Object[]a, int fromIndex, int toIndex, Object val)    public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
946    {    {
947        if (fromIndex > toIndex)
948          throw new IllegalArgumentException();
949      for (int i = fromIndex; i < toIndex; i++)      for (int i = fromIndex; i < toIndex; i++)
950        {        a[i] = val;
         a[i] = val;  
       }  
951    }    }
952    
953    
954    // sort
955    // Thanks to Paul Fisher <rao@gnu.org> for finding this quicksort algorithm    // Thanks to Paul Fisher <rao@gnu.org> for finding this quicksort algorithm
956    // as specified by Sun and porting it to Java.    // as specified by Sun and porting it to Java. The algorithm is an optimised
957      // quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
958      // "Engineering a Sort Function", Software-Practice and Experience, Vol.
959      // 23(11) P. 1249-1265 (November 1993). This algorithm gives n*log(n)
960      // performance on many arrays that would take quadratic time with a standard
961      // quicksort.
962    
963    /**    /**
964     * Sort a byte array into ascending order. The sort algorithm is an optimised     * Performs a stable sort on the elements, arranging them according to their
965     * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's     * natural order.
    * "Engineering a Sort Function", Software-Practice and Experience, Vol.  
    * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort.  
966     *     *
967     * @param a the array to sort     * @param a the byte array to sort
968     */     */
969    public static void sort(byte[]a)    public static void sort(byte[] a)
970    {    {
971      qsort(a, 0, a.length);      qsort(a, 0, a.length);
972    }    }
973    
974      /**
975       * Performs a stable sort on the elements, arranging them according to their
976       * natural order.
977       *
978       * @param a the byte array to sort
979       * @param fromIndex the first index to sort (inclusive)
980       * @param toIndex the last index to sort (exclusive)
981       * @throws IllegalArgumentException if fromIndex &gt; toIndex
982       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
983       *         || toIndex &gt; a.length
984       */
985    public static void sort(byte[] a, int fromIndex, int toIndex)    public static void sort(byte[] a, int fromIndex, int toIndex)
986    {    {
987      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
988          throw new IllegalArgumentException();
989        qsort(a, fromIndex, toIndex - fromIndex);
990    }    }
991    
992    private static int med3(int a, int b, int c, byte[]d)    /**
993       * Finds the index of the median of three array elements.
994       *
995       * @param a the first index
996       * @param b the second index
997       * @param c the third index
998       * @param d the array
999       * @return the index (a, b, or c) which has the middle value of the three
1000       */
1001      private static int med3(int a, int b, int c, byte[] d)
1002    {    {
1003      return d[a] < d[b] ?      return (d[a] < d[b]
1004                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
1005               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);              : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
1006    }    }
1007    
1008    private static void swap(int i, int j, byte[]a)    /**
1009       * Swaps the elements at two locations of an array
1010       *
1011       * @param i the first index
1012       * @param j the second index
1013       * @param a the array
1014       */
1015      private static void swap(int i, int j, byte[] a)
1016    {    {
1017      byte c = a[i];      byte c = a[i];
1018      a[i] = a[j];      a[i] = a[j];
1019      a[j] = c;      a[j] = c;
1020    }    }
1021    
1022    private static void qsort(byte[]a, int start, int n)    /**
1023       * Swaps two ranges of an array.
1024       *
1025       * @param i the first range start
1026       * @param j the second range start
1027       * @param n the element count
1028       * @param a the array
1029       */
1030      private static void vecswap(int i, int j, int n, byte[] a)
1031    {    {
1032      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1033      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     int r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1034    }    }
1035    
1036    private static void vecswap(int i, int j, int n, byte[]a)    /**
1037       * Performs a recursive modified quicksort.
1038       *
1039       * @param a the array to sort
1040       * @param from the start index (inclusive)
1041       * @param count the number of elements to sort
1042       */
1043      private static void qsort(byte[] array, int from, int count)
1044    {    {
1045      for (; n > 0; i++, j++, n--)      // Use an insertion sort on small arrays.
1046        swap(i, j, a);      if (count <= 7)
1047          {
1048            for (int i = from + 1; i < from + count; i++)
1049              for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
1050                swap(j, j - 1, array);
1051            return;
1052          }
1053    
1054        // Determine a good median element.
1055        int mid = count / 2;
1056        int lo = from;
1057        int hi = from + count - 1;
1058    
1059        if (count > 40)
1060          { // big arrays, pseudomedian of 9
1061            int s = count / 8;
1062            lo = med3(lo, lo + s, lo + s + s, array);
1063            mid = med3(mid - s, mid, mid + s, array);
1064            hi = med3(hi - s - s, hi - s, hi, array);
1065          }
1066        mid = med3(lo, mid, hi, array);
1067    
1068        int a, b, c, d;
1069        int comp;
1070    
1071        // Pull the median element out of the fray, and use it as a pivot.
1072        swap(from, mid, array);
1073        a = b = from + 1;
1074        c = d = hi;
1075    
1076        // Repeatedly move b and c to each other, swapping elements so
1077        // that all elements before index b are less than the pivot, and all
1078        // elements after index c are greater than the pivot. a and b track
1079        // the elements equal to the pivot.
1080        while (true)
1081          {
1082            while (b <= c && (comp = array[b] - array[from]) <= 0)
1083              {
1084                if (comp == 0)
1085                  {
1086                    swap(a, b, array);
1087                    a++;
1088                  }
1089                b++;
1090              }
1091            while (c >= b && (comp = array[c] - array[from]) >= 0)
1092              {
1093                if (comp == 0)
1094                  {
1095                    swap(c, d, array);
1096                    d--;
1097                  }
1098                c--;
1099              }
1100            if (b > c)
1101              break;
1102            swap(b, c, array);
1103            b++;
1104            c--;
1105          }
1106    
1107        // Swap pivot(s) back in place, the recurse on left and right sections.
1108        int span;
1109        span = Math.min(a - from, b - a);
1110        vecswap(from, b - span, span, array);
1111    
1112        span = Math.min(d - c, hi - d - 1);
1113        vecswap(b, hi - span + 1, span, array);
1114    
1115        span = b - a;
1116        if (span > 1)
1117          qsort(array, from, span);
1118    
1119        span = d - c;
1120        if (span > 1)
1121          qsort(array, hi - span + 1, span);
1122    }    }
1123    
1124    /**    /**
1125     * Sort a char array into ascending order. The sort algorithm is an optimised     * Performs a stable sort on the elements, arranging them according to their
1126     * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's     * natural order.
    * "Engineering a Sort Function", Software-Practice and Experience, Vol.  
    * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort.  
1127     *     *
1128     * @param a the array to sort     * @param a the char array to sort
1129     */     */
1130    public static void sort(char[]a)    public static void sort(char[] a)
1131    {    {
1132      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1133    }    }
1134    
1135      /**
1136       * Performs a stable sort on the elements, arranging them according to their
1137       * natural order.
1138       *
1139       * @param a the char array to sort
1140       * @param fromIndex the first index to sort (inclusive)
1141       * @param toIndex the last index to sort (exclusive)
1142       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1143       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1144       *         || toIndex &gt; a.length
1145       */
1146    public static void sort(char[] a, int fromIndex, int toIndex)    public static void sort(char[] a, int fromIndex, int toIndex)
1147    {    {
1148      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1149          throw new IllegalArgumentException();
1150        qsort(a, fromIndex, toIndex - fromIndex);
1151    }    }
1152    
1153    private static int med3(int a, int b, int c, char[]d)    /**
1154       * Finds the index of the median of three array elements.
1155       *
1156       * @param a the first index
1157       * @param b the second index
1158       * @param c the third index
1159       * @param d the array
1160       * @return the index (a, b, or c) which has the middle value of the three
1161       */
1162      private static int med3(int a, int b, int c, char[] d)
1163    {    {
1164      return d[a] < d[b] ?      return (d[a] < d[b]
1165                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
1166               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);              : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
1167    }    }
1168    
1169    private static void swap(int i, int j, char[]a)    /**
1170       * Swaps the elements at two locations of an array
1171       *
1172       * @param i the first index
1173       * @param j the second index
1174       * @param a the array
1175       */
1176      private static void swap(int i, int j, char[] a)
1177    {    {
1178      char c = a[i];      char c = a[i];
1179      a[i] = a[j];      a[i] = a[j];
1180      a[j] = c;      a[j] = c;
1181    }    }
1182    
1183    private static void qsort(char[]a, int start, int n)    /**
1184       * Swaps two ranges of an array.
1185       *
1186       * @param i the first range start
1187       * @param j the second range start
1188       * @param n the element count
1189       * @param a the array
1190       */
1191      private static void vecswap(int i, int j, int n, char[] a)
1192    {    {
1193      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1194      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     int r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1195    }    }
1196    
1197    private static void vecswap(int i, int j, int n, char[]a)    /**
1198       * Performs a recursive modified quicksort.
1199       *
1200       * @param a the array to sort
1201       * @param from the start index (inclusive)
1202       * @param count the number of elements to sort
1203       */
1204      private static void qsort(char[] array, int from, int count)
1205    {    {
1206      for (; n > 0; i++, j++, n--)      // Use an insertion sort on small arrays.
1207        swap(i, j, a);      if (count <= 7)
1208          {
1209            for (int i = from + 1; i < from + count; i++)
1210              for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
1211                swap(j, j - 1, array);
1212            return;
1213          }
1214    
1215        // Determine a good median element.
1216        int mid = count / 2;
1217        int lo = from;
1218        int hi = from + count - 1;
1219    
1220        if (count > 40)
1221          { // big arrays, pseudomedian of 9
1222            int s = count / 8;
1223            lo = med3(lo, lo + s, lo + s + s, array);
1224            mid = med3(mid - s, mid, mid + s, array);
1225            hi = med3(hi - s - s, hi - s, hi, array);
1226          }
1227        mid = med3(lo, mid, hi, array);
1228    
1229        int a, b, c, d;
1230        int comp;
1231    
1232        // Pull the median element out of the fray, and use it as a pivot.
1233        swap(from, mid, array);
1234        a = b = from + 1;
1235        c = d = hi;
1236    
1237        // Repeatedly move b and c to each other, swapping elements so
1238        // that all elements before index b are less than the pivot, and all
1239        // elements after index c are greater than the pivot. a and b track
1240        // the elements equal to the pivot.
1241        while (true)
1242          {
1243            while (b <= c && (comp = array[b] - array[from]) <= 0)
1244              {
1245                if (comp == 0)
1246                  {
1247                    swap(a, b, array);
1248                    a++;
1249                  }
1250                b++;
1251              }
1252            while (c >= b && (comp = array[c] - array[from]) >= 0)
1253              {
1254                if (comp == 0)
1255                  {
1256                    swap(c, d, array);
1257                    d--;
1258                  }
1259                c--;
1260              }
1261            if (b > c)
1262              break;
1263            swap(b, c, array);
1264            b++;
1265            c--;
1266          }
1267    
1268        // Swap pivot(s) back in place, the recurse on left and right sections.
1269        int span;
1270        span = Math.min(a - from, b - a);
1271        vecswap(from, b - span, span, array);
1272    
1273        span = Math.min(d - c, hi - d - 1);
1274        vecswap(b, hi - span + 1, span, array);
1275    
1276        span = b - a;
1277        if (span > 1)
1278          qsort(array, from, span);
1279    
1280        span = d - c;
1281        if (span > 1)
1282          qsort(array, hi - span + 1, span);
1283    }    }
1284    
1285    /**    /**
1286     * Sort a double array into ascending order. The sort algorithm is an     * Performs a stable sort on the elements, arranging them according to their
1287     * optimised quicksort, as described in Jon L. Bentley and M. Douglas     * natural order.
    * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,  
    * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort. Note that this implementation, like Sun's, has undefined  
    * behaviour if the array contains any NaN values.  
1288     *     *
1289     * @param a the array to sort     * @param a the short array to sort
1290     */     */
1291    public static void sort(double[]a)    public static void sort(short[] a)
1292    {    {
1293      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1294    }    }
1295    
1296    public static void sort(double[] a, int fromIndex, int toIndex)    /**
1297       * Performs a stable sort on the elements, arranging them according to their
1298       * natural order.
1299       *
1300       * @param a the short array to sort
1301       * @param fromIndex the first index to sort (inclusive)
1302       * @param toIndex the last index to sort (exclusive)
1303       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1304       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1305       *         || toIndex &gt; a.length
1306       */
1307      public static void sort(short[] a, int fromIndex, int toIndex)
1308    {    {
1309      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1310          throw new IllegalArgumentException();
1311        qsort(a, fromIndex, toIndex - fromIndex);
1312    }    }
1313    
1314    private static int med3(int a, int b, int c, double[]d)    /**
1315       * Finds the index of the median of three array elements.
1316       *
1317       * @param a the first index
1318       * @param b the second index
1319       * @param c the third index
1320       * @param d the array
1321       * @return the index (a, b, or c) which has the middle value of the three
1322       */
1323      private static int med3(int a, int b, int c, short[] d)
1324    {    {
1325      return d[a] < d[b] ?      return (d[a] < d[b]
1326                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
1327               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);              : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
1328    }    }
1329    
1330    private static void swap(int i, int j, double[]a)    /**
1331       * Swaps the elements at two locations of an array
1332       *
1333       * @param i the first index
1334       * @param j the second index
1335       * @param a the array
1336       */
1337      private static void swap(int i, int j, short[] a)
1338    {    {
1339      double c = a[i];      short c = a[i];
1340      a[i] = a[j];      a[i] = a[j];
1341      a[j] = c;      a[j] = c;
1342    }    }
1343    
1344    private static void qsort(double[]a, int start, int n)    /**
1345       * Swaps two ranges of an array.
1346       *
1347       * @param i the first range start
1348       * @param j the second range start
1349       * @param n the element count
1350       * @param a the array
1351       */
1352      private static void vecswap(int i, int j, int n, short[] a)
1353    {    {
1354      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1355      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     double r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1356    }    }
1357    
1358    private static void vecswap(int i, int j, int n, double[]a)    /**
1359       * Performs a recursive modified quicksort.
1360       *
1361       * @param a the array to sort
1362       * @param from the start index (inclusive)
1363       * @param count the number of elements to sort
1364       */
1365      private static void qsort(short[] array, int from, int count)
1366    {    {
1367      for (; n > 0; i++, j++, n--)      // Use an insertion sort on small arrays.
1368        swap(i, j, a);      if (count <= 7)
1369          {
1370            for (int i = from + 1; i < from + count; i++)
1371              for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
1372                swap(j, j - 1, array);
1373            return;
1374          }
1375    
1376        // Determine a good median element.
1377        int mid = count / 2;
1378        int lo = from;
1379        int hi = from + count - 1;
1380    
1381        if (count > 40)
1382          { // big arrays, pseudomedian of 9
1383            int s = count / 8;
1384            lo = med3(lo, lo + s, lo + s + s, array);
1385            mid = med3(mid - s, mid, mid + s, array);
1386            hi = med3(hi - s - s, hi - s, hi, array);
1387          }
1388        mid = med3(lo, mid, hi, array);
1389    
1390        int a, b, c, d;
1391        int comp;
1392    
1393        // Pull the median element out of the fray, and use it as a pivot.
1394        swap(from, mid, array);
1395        a = b = from + 1;
1396        c = d = hi;
1397    
1398        // Repeatedly move b and c to each other, swapping elements so
1399        // that all elements before index b are less than the pivot, and all
1400        // elements after index c are greater than the pivot. a and b track
1401        // the elements equal to the pivot.
1402        while (true)
1403          {
1404            while (b <= c && (comp = array[b] - array[from]) <= 0)
1405              {
1406                if (comp == 0)
1407                  {
1408                    swap(a, b, array);
1409                    a++;
1410                  }
1411                b++;
1412              }
1413            while (c >= b && (comp = array[c] - array[from]) >= 0)
1414              {
1415                if (comp == 0)
1416                  {
1417                    swap(c, d, array);
1418                    d--;
1419                  }
1420                c--;
1421              }
1422            if (b > c)
1423              break;
1424            swap(b, c, array);
1425            b++;
1426            c--;
1427          }
1428    
1429        // Swap pivot(s) back in place, the recurse on left and right sections.
1430        int span;
1431        span = Math.min(a - from, b - a);
1432        vecswap(from, b - span, span, array);
1433    
1434        span = Math.min(d - c, hi - d - 1);
1435        vecswap(b, hi - span + 1, span, array);
1436    
1437        span = b - a;
1438        if (span > 1)
1439          qsort(array, from, span);
1440    
1441        span = d - c;
1442        if (span > 1)
1443          qsort(array, hi - span + 1, span);
1444    }    }
1445    
1446    /**    /**
1447     * Sort a float array into ascending order. The sort algorithm is an     * Performs a stable sort on the elements, arranging them according to their
1448     * optimised quicksort, as described in Jon L. Bentley and M. Douglas     * natural order.
    * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,  
    * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort. Note that this implementation, like Sun's, has undefined  
    * behaviour if the array contains any NaN values.  
1449     *     *
1450     * @param a the array to sort     * @param a the int array to sort
1451     */     */
1452    public static void sort(float[]a)    public static void sort(int[] a)
1453    {    {
1454      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1455    }    }
1456    
1457    public static void sort(float[] a, int fromIndex, int toIndex)    /**
1458       * Performs a stable sort on the elements, arranging them according to their
1459       * natural order.
1460       *
1461       * @param a the int array to sort
1462       * @param fromIndex the first index to sort (inclusive)
1463       * @param toIndex the last index to sort (exclusive)
1464       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1465       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1466       *         || toIndex &gt; a.length
1467       */
1468      public static void sort(int[] a, int fromIndex, int toIndex)
1469    {    {
1470      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1471          throw new IllegalArgumentException();
1472        qsort(a, fromIndex, toIndex - fromIndex);
1473    }    }
1474    
1475    private static int med3(int a, int b, int c, float[]d)    /**
1476       * Finds the index of the median of three array elements.
1477       *
1478       * @param a the first index
1479       * @param b the second index
1480       * @param c the third index
1481       * @param d the array
1482       * @return the index (a, b, or c) which has the middle value of the three
1483       */
1484      private static int med3(int a, int b, int c, int[] d)
1485    {    {
1486      return d[a] < d[b] ?      return (d[a] < d[b]
1487                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
1488               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);              : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
1489    }    }
1490    
1491    private static void swap(int i, int j, float[]a)    /**
1492       * Swaps the elements at two locations of an array
1493       *
1494       * @param i the first index
1495       * @param j the second index
1496       * @param a the array
1497       */
1498      private static void swap(int i, int j, int[] a)
1499    {    {
1500      float c = a[i];      int c = a[i];
1501      a[i] = a[j];      a[i] = a[j];
1502      a[j] = c;      a[j] = c;
1503    }    }
1504    
1505    private static void qsort(float[]a, int start, int n)    /**
1506       * Swaps two ranges of an array.
1507       *
1508       * @param i the first range start
1509       * @param j the second range start
1510       * @param n the element count
1511       * @param a the array
1512       */
1513      private static void vecswap(int i, int j, int n, int[] a)
1514    {    {
1515      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1516      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     float r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1517    }    }
1518    
1519    private static void vecswap(int i, int j, int n, float[]a)    /**
1520       * Compares two integers in natural order, since a - b is inadequate.
1521       *
1522       * @param a the first int
1523       * @param b the second int
1524       * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
1525       */
1526      private static int compare(int a, int b)
1527    {    {
1528      for (; n > 0; i++, j++, n--)      return a < b ? -1 : a == b ? 0 : 1;
       swap(i, j, a);  
1529    }    }
1530    
1531    /**    /**
1532     * Sort an int array into ascending order. The sort algorithm is an optimised     * Performs a recursive modified quicksort.
    * 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 nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort.  
1533     *     *
1534     * @param a the array to sort     * @param a the array to sort
1535       * @param from the start index (inclusive)
1536       * @param count the number of elements to sort
1537       */
1538      private static void qsort(int[] array, int from, int count)
1539      {
1540        // Use an insertion sort on small arrays.
1541        if (count <= 7)
1542          {
1543            for (int i = from + 1; i < from + count; i++)
1544              for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
1545                swap(j, j - 1, array);
1546            return;
1547          }
1548    
1549        // Determine a good median element.
1550        int mid = count / 2;
1551        int lo = from;
1552        int hi = from + count - 1;
1553    
1554        if (count > 40)
1555          { // big arrays, pseudomedian of 9
1556            int s = count / 8;
1557            lo = med3(lo, lo + s, lo + s + s, array);
1558            mid = med3(mid - s, mid, mid + s, array);
1559            hi = med3(hi - s - s, hi - s, hi, array);
1560          }
1561        mid = med3(lo, mid, hi, array);
1562    
1563        int a, b, c, d;
1564        int comp;
1565    
1566        // Pull the median element out of the fray, and use it as a pivot.
1567        swap(from, mid, array);
1568        a = b = from + 1;
1569        c = d = hi;
1570    
1571        // Repeatedly move b and c to each other, swapping elements so
1572        // that all elements before index b are less than the pivot, and all
1573        // elements after index c are greater than the pivot. a and b track
1574        // the elements equal to the pivot.
1575        while (true)
1576          {
1577            while (b <= c && (comp = compare(array[b], array[from])) <= 0)
1578              {
1579                if (comp == 0)
1580                  {
1581                    swap(a, b, array);
1582                    a++;
1583                  }
1584                b++;
1585              }
1586            while (c >= b && (comp = compare(array[c], array[from])) >= 0)
1587              {
1588                if (comp == 0)
1589                  {
1590                    swap(c, d, array);
1591                    d--;
1592                  }
1593                c--;
1594              }
1595            if (b > c)
1596              break;
1597            swap(b, c, array);
1598            b++;
1599            c--;
1600          }
1601    
1602        // Swap pivot(s) back in place, the recurse on left and right sections.
1603        int span;
1604        span = Math.min(a - from, b - a);
1605        vecswap(from, b - span, span, array);
1606    
1607        span = Math.min(d - c, hi - d - 1);
1608        vecswap(b, hi - span + 1, span, array);
1609    
1610        span = b - a;
1611        if (span > 1)
1612          qsort(array, from, span);
1613    
1614        span = d - c;
1615        if (span > 1)
1616          qsort(array, hi - span + 1, span);
1617      }
1618    
1619      /**
1620       * Performs a stable sort on the elements, arranging them according to their
1621       * natural order.
1622       *
1623       * @param a the long array to sort
1624     */     */
1625    public static void sort(int[]a)    public static void sort(long[] a)
1626    {    {
1627      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1628    }    }
1629    
1630    public static void sort(int[] a, int fromIndex, int toIndex)    /**
1631       * Performs a stable sort on the elements, arranging them according to their
1632       * natural order.
1633       *
1634       * @param a the long array to sort
1635       * @param fromIndex the first index to sort (inclusive)
1636       * @param toIndex the last index to sort (exclusive)
1637       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1638       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1639       *         || toIndex &gt; a.length
1640       */
1641      public static void sort(long[] a, int fromIndex, int toIndex)
1642    {    {
1643      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1644          throw new IllegalArgumentException();
1645        qsort(a, fromIndex, toIndex - fromIndex);
1646    }    }
1647    
1648    private static int med3(int a, int b, int c, int[]d)    /**
1649       * Finds the index of the median of three array elements.
1650       *
1651       * @param a the first index
1652       * @param b the second index
1653       * @param c the third index
1654       * @param d the array
1655       * @return the index (a, b, or c) which has the middle value of the three
1656       */
1657      private static int med3(int a, int b, int c, long[] d)
1658    {    {
1659      return d[a] < d[b] ?      return (d[a] < d[b]
1660                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
1661               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);              : (d[b] > d[c] ? b : d[a] > d[c] ? c : a));
1662    }    }
1663    
1664    private static void swap(int i, int j, int[]a)    /**
1665       * Swaps the elements at two locations of an array
1666       *
1667       * @param i the first index
1668       * @param j the second index
1669       * @param a the array
1670       */
1671      private static void swap(int i, int j, long[] a)
1672    {    {
1673      int c = a[i];      long c = a[i];
1674      a[i] = a[j];      a[i] = a[j];
1675      a[j] = c;      a[j] = c;
1676    }    }
1677    
1678    private static void qsort(int[]a, int start, int n)    /**
1679       * Swaps two ranges of an array.
1680       *
1681       * @param i the first range start
1682       * @param j the second range start
1683       * @param n the element count
1684       * @param a the array
1685       */
1686      private static void vecswap(int i, int j, int n, long[] a)
1687    {    {
1688      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1689      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     int r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1690    }    }
1691    
1692    private static void vecswap(int i, int j, int n, int[]a)    /**
1693       * Compares two longs in natural order, since a - b is inadequate.
1694       *
1695       * @param a the first long
1696       * @param b the second long
1697       * @return &lt; 0, 0, or &gt; 0 accorting to the comparison
1698       */
1699      private static int compare(long a, long b)
1700    {    {
1701      for (; n > 0; i++, j++, n--)      return a < b ? -1 : a == b ? 0 : 1;
       swap(i, j, a);  
1702    }    }
1703    
1704    /**    /**
1705     * Sort a long array into ascending order. The sort algorithm is an optimised     * Performs a recursive modified quicksort.
    * 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 nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort.  
1706     *     *
1707     * @param a the array to sort     * @param a the array to sort
1708       * @param from the start index (inclusive)
1709       * @param count the number of elements to sort
1710       */
1711      private static void qsort(long[] array, int from, int count)
1712      {
1713        // Use an insertion sort on small arrays.
1714        if (count <= 7)
1715          {
1716            for (int i = from + 1; i < from + count; i++)
1717              for (int j = i; j > 0 && array[j - 1] > array[j]; j--)
1718                swap(j, j - 1, array);
1719            return;
1720          }
1721    
1722        // Determine a good median element.
1723        int mid = count / 2;
1724        int lo = from;
1725        int hi = from + count - 1;
1726    
1727        if (count > 40)
1728          { // big arrays, pseudomedian of 9
1729            int s = count / 8;
1730            lo = med3(lo, lo + s, lo + s + s, array);
1731            mid = med3(mid - s, mid, mid + s, array);
1732            hi = med3(hi - s - s, hi - s, hi, array);
1733          }
1734        mid = med3(lo, mid, hi, array);
1735    
1736        int a, b, c, d;
1737        int comp;
1738    
1739        // Pull the median element out of the fray, and use it as a pivot.
1740        swap(from, mid, array);
1741        a = b = from + 1;
1742        c = d = hi;
1743    
1744        // Repeatedly move b and c to each other, swapping elements so
1745        // that all elements before index b are less than the pivot, and all
1746        // elements after index c are greater than the pivot. a and b track
1747        // the elements equal to the pivot.
1748        while (true)
1749          {
1750            while (b <= c && (comp = compare(array[b], array[from])) <= 0)
1751              {
1752                if (comp == 0)
1753                  {
1754                    swap(a, b, array);
1755                    a++;
1756                  }
1757                b++;
1758              }
1759            while (c >= b && (comp = compare(array[c], array[from])) >= 0)
1760              {
1761                if (comp == 0)
1762                  {
1763                    swap(c, d, array);
1764                    d--;
1765                  }
1766                c--;
1767              }
1768            if (b > c)
1769              break;
1770            swap(b, c, array);
1771            b++;
1772            c--;
1773          }
1774    
1775        // Swap pivot(s) back in place, the recurse on left and right sections.
1776        int span;
1777        span = Math.min(a - from, b - a);
1778        vecswap(from, b - span, span, array);
1779    
1780        span = Math.min(d - c, hi - d - 1);
1781        vecswap(b, hi - span + 1, span, array);
1782    
1783        span = b - a;
1784        if (span > 1)
1785          qsort(array, from, span);
1786    
1787        span = d - c;
1788        if (span > 1)
1789          qsort(array, hi - span + 1, span);
1790      }
1791    
1792      /**
1793       * Performs a stable sort on the elements, arranging them according to their
1794       * natural order.
1795       *
1796       * @param a the float array to sort
1797     */     */
1798    public static void sort(long[]a)    public static void sort(float[] a)
1799    {    {
1800      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1801    }    }
1802    
1803    public static void sort(long[] a, int fromIndex, int toIndex)    /**
1804       * Performs a stable sort on the elements, arranging them according to their
1805       * natural order.
1806       *
1807       * @param a the float array to sort
1808       * @param fromIndex the first index to sort (inclusive)
1809       * @param toIndex the last index to sort (exclusive)
1810       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1811       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1812       *         || toIndex &gt; a.length
1813       */
1814      public static void sort(float[] a, int fromIndex, int toIndex)
1815    {    {
1816      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1817          throw new IllegalArgumentException();
1818        qsort(a, fromIndex, toIndex - fromIndex);
1819    }    }
1820    
1821    private static int med3(int a, int b, int c, long[]d)    /**
1822       * Finds the index of the median of three array elements.
1823       *
1824       * @param a the first index
1825       * @param b the second index
1826       * @param c the third index
1827       * @param d the array
1828       * @return the index (a, b, or c) which has the middle value of the three
1829       */
1830      private static int med3(int a, int b, int c, float[] d)
1831    {    {
1832      return d[a] < d[b] ?      return (Float.compare(d[a], d[b]) < 0
1833                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (Float.compare(d[b], d[c]) < 0 ? b
1834               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);                 : Float.compare(d[a], d[c]) < 0 ? c : a)
1835                : (Float.compare(d[b], d[c]) > 0 ? b
1836                   : Float.compare(d[a], d[c]) > 0 ? c : a));
1837    }    }
1838    
1839    private static void swap(int i, int j, long[]a)    /**
1840       * Swaps the elements at two locations of an array
1841       *
1842       * @param i the first index
1843       * @param j the second index
1844       * @param a the array
1845       */
1846      private static void swap(int i, int j, float[] a)
1847    {    {
1848      long c = a[i];      float c = a[i];
1849      a[i] = a[j];      a[i] = a[j];
1850      a[j] = c;      a[j] = c;
1851    }    }
1852    
1853    private static void qsort(long[]a, int start, int n)    /**
1854       * Swaps two ranges of an array.
1855       *
1856       * @param i the first range start
1857       * @param j the second range start
1858       * @param n the element count
1859       * @param a the array
1860       */
1861      private static void vecswap(int i, int j, int n, float[] a)
1862    {    {
1863      // use an insertion sort on small arrays      for ( ; n > 0; i++, j++, n--)
1864      if (n <= 7)        swap(i, j, a);
       {  
         for (int i = start + 1; i < start + n; i++)  
           for (int j = i; j > 0 && a[j - 1] > a[j]; j--)  
             swap(j, j - 1, a);  
         return;  
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     long r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
1865    }    }
1866    
1867    private static void vecswap(int i, int j, int n, long[]a)    /**
1868       * Performs a recursive modified quicksort.
1869       *
1870       * @param a the array to sort
1871       * @param from the start index (inclusive)
1872       * @param count the number of elements to sort
1873       */
1874      private static void qsort(float[] array, int from, int count)
1875    {    {
1876      for (; n > 0; i++, j++, n--)      // Use an insertion sort on small arrays.
1877        swap(i, j, a);      if (count <= 7)
1878          {
1879            for (int i = from + 1; i < from + count; i++)
1880              for (int j = i;
1881                   j > 0 && Float.compare(array[j - 1], array[j]) > 0;
1882                   j--)
1883                {
1884                  swap(j, j - 1, array);
1885                }
1886            return;
1887          }
1888    
1889        // Determine a good median element.
1890        int mid = count / 2;
1891        int lo = from;
1892        int hi = from + count - 1;
1893    
1894        if (count > 40)
1895          { // big arrays, pseudomedian of 9
1896            int s = count / 8;
1897            lo = med3(lo, lo + s, lo + s + s, array);
1898            mid = med3(mid - s, mid, mid + s, array);
1899            hi = med3(hi - s - s, hi - s, hi, array);
1900          }
1901        mid = med3(lo, mid, hi, array);
1902    
1903        int a, b, c, d;
1904        int comp;
1905    
1906        // Pull the median element out of the fray, and use it as a pivot.
1907        swap(from, mid, array);
1908        a = b = from + 1;
1909        c = d = hi;
1910    
1911        // Repeatedly move b and c to each other, swapping elements so
1912        // that all elements before index b are less than the pivot, and all
1913        // elements after index c are greater than the pivot. a and b track
1914        // the elements equal to the pivot.
1915        while (true)
1916          {
1917            while (b <= c && (comp = Float.compare(array[b], array[from])) <= 0)
1918              {
1919                if (comp == 0)
1920                  {
1921                    swap(a, b, array);
1922                    a++;
1923                  }
1924                b++;
1925              }
1926            while (c >= b && (comp = Float.compare(array[c], array[from])) >= 0)
1927              {
1928                if (comp == 0)
1929                  {
1930                    swap(c, d, array);
1931                    d--;
1932                  }
1933                c--;
1934              }
1935            if (b > c)
1936              break;
1937            swap(b, c, array);
1938            b++;
1939            c--;
1940          }
1941    
1942        // Swap pivot(s) back in place, the recurse on left and right sections.
1943        int span;
1944        span = Math.min(a - from, b - a);
1945        vecswap(from, b - span, span, array);
1946    
1947        span = Math.min(d - c, hi - d - 1);
1948        vecswap(b, hi - span + 1, span, array);
1949    
1950        span = b - a;
1951        if (span > 1)
1952          qsort(array, from, span);
1953    
1954        span = d - c;
1955        if (span > 1)
1956          qsort(array, hi - span + 1, span);
1957    }    }
1958    
1959    /**    /**
1960     * Sort a short array into ascending order. The sort algorithm is an     * Performs a stable sort on the elements, arranging them according to their
1961     * optimised quicksort, as described in Jon L. Bentley and M. Douglas     * natural order.
    * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,  
    * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)  
    * performance on many arrays that would take quadratic time with a standard  
    * quicksort.  
1962     *     *
1963     * @param a the array to sort     * @param a the double array to sort
1964     */     */
1965    public static void sort(short[]a)    public static void sort(double[] a)
1966    {    {
1967      qsort(a, 0, a.length);      qsort(a, 0, a.length);
1968    }    }
1969    
1970    public static void sort(short[] a, int fromIndex, int toIndex)    /**
1971       * Performs a stable sort on the elements, arranging them according to their
1972       * natural order.
1973       *
1974       * @param a the double array to sort
1975       * @param fromIndex the first index to sort (inclusive)
1976       * @param toIndex the last index to sort (exclusive)
1977       * @throws IllegalArgumentException if fromIndex &gt; toIndex
1978       * @throws ArrayIndexOutOfBoundsException if fromIndex &lt; 0
1979       *         || toIndex &gt; a.length
1980       */
1981      public static void sort(double[] a, int fromIndex, int toIndex)
1982    {    {
1983      qsort(a, fromIndex, toIndex);      if (fromIndex > toIndex)
1984          throw new IllegalArgumentException();
1985        qsort(a, fromIndex, toIndex - fromIndex);
1986    }    }
1987    
1988    private static int med3(int a, int b, int c, short[]d)    /**
1989       * Finds the index of the median of three array elements.
1990       *
1991       * @param a the first index
1992       * @param b the second index
1993       * @param c the third index
1994       * @param d the array
1995       * @return the index (a, b, or c) which has the middle value of the three
1996       */
1997      private static int med3(int a, int b, int c, double[] d)
1998    {    {
1999      return d[a] < d[b] ?      return (Double.compare(d[a], d[b]) < 0
2000                 (d[b] < d[c] ? b : d[a] < d[c] ? c : a)              ? (Double.compare(d[b], d[c]) < 0 ? b
2001               : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);                 : Double.compare(d[a], d[c]) < 0 ? c : a)
2002                : (Double.compare(d[b], d[c]) > 0 ? b
2003                   : Double.compare(d[a], d[c]) > 0 ? c : a));
2004    }    }
2005    
2006    private static void swap(int i, int j, short[]a)    /**
2007       * Swaps the elements at two locations of an array
2008       *
2009       * @param i the first index
2010       * @param j the second index
2011       * @param a the array
2012       */
2013      private static void swap(int i, int j, double[] a)
2014    {    {
2015      short c = a[i];      double c = a[i];
2016      a[i] = a[j];      a[i] = a[j];
2017      a[j] = c;      a[j] = c;
2018    }    }
2019    
2020    private static void qsort(short[]a, int start, int n)    /**
2021    {     * Swaps two ranges of an array.
2022      // use an insertion sort on small arrays     *
2023      if (n <= 7)     * @param i the first range start
2024        {     * @param j the second range start
2025          for (int i = start + 1; i < start + n; i++)     * @param n the element count
2026            for (int j = i; j > 0 && a[j - 1] > a[j]; j--)     * @param a the array
2027              swap(j, j - 1, a);     */
2028          return;    private static void vecswap(int i, int j, int n, double[] a)
       }  
   
     int pm = n / 2;             // small arrays, middle element  
     if (n > 7)  
       {  
         int pl = start;  
         int pn = start + n - 1;  
   
         if (n > 40)  
           {                     // big arrays, pseudomedian of 9  
             int s = n / 8;  
             pl = med3(pl, pl + s, pl + 2 * s, a);  
             pm = med3(pm - s, pm, pm + s, a);  
             pn = med3(pn - 2 * s, pn - s, pn, a);  
           }  
         pm = med3(pl, pm, pn, a);       // mid-size, med of 3  
       }  
   
     int pa, pb, pc, pd, pv;  
     int r;  
   
     pv = start;  
     swap(pv, pm, a);  
     pa = pb = start;  
     pc = pd = start + n - 1;  
   
     for (;;)  
       {  
         while (pb <= pc && (r = a[pb] - a[pv]) <= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pa, pb, a);  
                 pa++;  
               }  
             pb++;  
           }  
         while (pc >= pb && (r = a[pc] - a[pv]) >= 0)  
           {  
             if (r == 0)  
               {  
                 swap(pc, pd, a);  
                 pd--;  
               }  
             pc--;  
           }  
         if (pb > pc)  
           break;  
         swap(pb, pc, a);  
         pb++;  
         pc--;  
       }  
     int pn = start + n;  
     int s;  
     s = Math.min(pa - start, pb - pa);  
     vecswap(start, pb - s, s, a);  
     s = Math.min(pd - pc, pn - pd - 1);  
     vecswap(pb, pn - s, s, a);  
     if ((s = pb - pa) > 1)  
       qsort(a, start, s);  
     if ((s = pd - pc) > 1)  
       qsort(a, pn - s, s);  
   }  
   
   private static void vecswap(int i, int j, int n, short[]a)  
2029    {    {
2030      for (; n > 0; i++, j++, n--)      for ( ; n > 0; i++, j++, n--)
2031        swap(i, j, a);        swap(i, j, a);
2032    }    }
2033    
2034    /**    /**
2035     * The bulk of the work for the object sort routines.  In general,     * Performs a recursive modified quicksort.
2036     * the code attempts to be simple rather than fast, the idea being     *
2037     * that a good optimising JIT will be able to optimise it better     * @param a the array to sort
2038     * than I can, and if I try it will make it more confusing for the     * @param from the start index (inclusive)
2039     * JIT.       * @param count the number of elements to sort
2040     */     */
2041    private static void mergeSort(Object[]a, int from, int to, Comparator c)    private static void qsort(double[] array, int from, int count)
2042    {    {
2043      // First presort the array in chunks of length 6 with insertion sort.      // Use an insertion sort on small arrays.
2044      // mergesort would give too much overhead for this length.      if (count <= 7)
     for (int chunk = from; chunk < to; chunk += 6)  
       {  
         int end = Math.min(chunk + 6, to);  
         for (int i = chunk + 1; i < end; i++)  
           {  
             if (c.compare(a[i - 1], a[i]) > 0)  
               {  
                 // not already sorted  
                 int j = i;  
                 Object elem = a[j];  
                 do  
                   {  
                     a[j] = a[j - 1];  
                     j--;  
                   }  
                 while (j > chunk && c.compare(a[j - 1], elem) > 0);  
                 a[j] = elem;  
               }  
           }  
       }  
   
     int len = to - from;  
     // 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 = -from;  
   
     // The merges are done in this loop  
     for (int size = 6; size < len; size <<= 1)  
       {  
         for (int start = from; start < to; start += size << 1)  
           {  
             // mid ist 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(to, mid + size);  
   
             // The second list is empty or the elements are already in  
             // order - no need to merge  
             if (mid >= end || c.compare(src[mid - 1], src[mid]) <= 0)  
               {  
                 System.arraycopy(src, start,  
                                  dest, start + srcDestDiff, end - start);  
   
                 // The two halves just need swapping - no need to merge  
               }  
             else if (c.compare(src[start], src[end - 1]) > 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[c.compare(src[p1], src[p2]) <= 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;  
         from += srcDestDiff;  
         to += 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)  
2045        {        {
2046          // Note that from == 0.          for (int i = from + 1; i < from + count; i++)
2047          System.arraycopy(src, 0, a, srcDestDiff, to);            for (int j = i;
2048        }                 j > 0 && Double.compare(array[j - 1], array[j]) > 0;
2049                   j--)
2050                {
2051                  swap(j, j - 1, array);
2052                }
2053            return;
2054          }
2055    
2056        // Determine a good median element.
2057        int mid = count / 2;
2058        int lo = from;
2059        int hi = from + count - 1;
2060    
2061        if (count > 40)
2062          { // big arrays, pseudomedian of 9
2063            int s = count / 8;
2064            lo = med3(lo, lo + s, lo + s + s, array);
2065            mid = med3(mid - s, mid, mid + s, array);
2066            hi = med3(hi - s - s, hi - s, hi, array);
2067          }
2068        mid = med3(lo, mid, hi, array);
2069    
2070        int a, b, c, d;
2071        int comp;
2072    
2073        // Pull the median element out of the fray, and use it as a pivot.
2074        swap(from, mid, array);
2075        a = b = from + 1;
2076        c = d = hi;
2077    
2078        // Repeatedly move b and c to each other, swapping elements so
2079        // that all elements before index b are less than the pivot, and all
2080        // elements after index c are greater than the pivot. a and b track
2081        // the elements equal to the pivot.
2082        while (true)
2083          {
2084            while (b <= c && (comp = Double.compare(array[b], array[from])) <= 0)
2085              {
2086                if (comp == 0)
2087                  {
2088                    swap(a, b, array);
2089                    a++;
2090                  }
2091                b++;
2092              }
2093            while (c >= b && (comp = Double.compare(array[c], array[from])) >= 0)
2094              {
2095                if (comp == 0)
2096                  {
2097                    swap(c, d, array);
2098                    d--;
2099                  }
2100                c--;
2101              }
2102            if (b > c)
2103              break;
2104            swap(b, c, array);
2105            b++;
2106            c--;
2107          }
2108    
2109        // Swap pivot(s) back in place, the recurse on left and right sections.
2110        int span;
2111        span = Math.min(a - from, b - a);
2112        vecswap(from, b - span, span, array);
2113    
2114        span = Math.min(d - c, hi - d - 1);
2115        vecswap(b, hi - span + 1, span, array);
2116    
2117        span = b - a;
2118        if (span > 1)
2119          qsort(array, from, span);
2120    
2121        span = d - c;
2122        if (span > 1)
2123          qsort(array, hi - span + 1, span);
2124    }    }
2125    
2126    /**    /**
# Line 1972  public class Arrays Line 2128  public class Arrays
2128     * guaranteed to be stable, that is, equal elements will not be reordered.     * guaranteed to be stable, that is, equal elements will not be reordered.
2129     * The sort algorithm is a mergesort with the merge omitted if the last     * The sort algorithm is a mergesort with the merge omitted if the last
2130     * element of one half comes before the first element of the other half. This     * element of one half comes before the first element of the other half. This
2131     * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a     * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
2132     * copy of the array.     * copy of the array.
2133     *     *
2134     * @param a the array to be sorted     * @param a the array to be sorted
2135     * @exception ClassCastException if any two elements are not mutually     * @throws ClassCastException if any two elements are not mutually
2136     *   comparable     *         comparable
2137     * @exception NullPointerException if an element is null (since     * @throws NullPointerException if an element is null (since
2138     *   null.compareTo cannot work)     *         null.compareTo cannot work)
2139       * @see Comparable
2140     */     */
2141    public static void sort(Object[]a)    public static void sort(Object[] a)
2142    {    {
2143      mergeSort(a, 0, a.length, defaultComparator);      sort(a, 0, a.length, null);
2144    }    }
2145    
2146    /**    /**
# Line 1991  public class Arrays Line 2148  public class Arrays
2148     * guaranteed to be stable, that is, equal elements will not be reordered.     * guaranteed to be stable, that is, equal elements will not be reordered.
2149     * The sort algorithm is a mergesort with the merge omitted if the last     * The sort algorithm is a mergesort with the merge omitted if the last
2150     * element of one half comes before the first element of the other half. This     * element of one half comes before the first element of the other half. This
2151     * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a     * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
2152     * copy of the array.     * copy of the array.
2153     *     *
2154     * @param a the array to be sorted     * @param a the array to be sorted
2155     * @param c a Comparator to use in sorting the array     * @param c a Comparator to use in sorting the array; or null to indicate
2156     * @exception ClassCastException if any two elements are not mutually     *        the elements' natural order
2157     *   comparable by the Comparator provided     * @throws ClassCastException if any two elements are not mutually
2158       *         comparable by the Comparator provided
2159       * @throws NullPointerException if a null element is compared with natural
2160       *         ordering (only possible when c is null)
2161     */     */
2162    public static void sort(Object[]a, Comparator c)    public static void sort(Object[] a, Comparator c)
2163    {    {
2164      mergeSort(a, 0, a.length, c);      sort(a, 0, a.length, c);
2165    }    }
2166    
2167    /**    /**
# Line 2009  public class Arrays Line 2169  public class Arrays
2169     * guaranteed to be stable, that is, equal elements will not be reordered.     * guaranteed to be stable, that is, equal elements will not be reordered.
2170     * The sort algorithm is a mergesort with the merge omitted if the last     * The sort algorithm is a mergesort with the merge omitted if the last
2171     * element of one half comes before the first element of the other half. This     * element of one half comes before the first element of the other half. This
2172     * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a     * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
2173     * copy of the array.     * copy of the array.
2174     *     *
2175     * @param a the array to be sorted     * @param a the array to be sorted
2176     * @param fromIndex the index of the first element to be sorted.     * @param fromIndex the index of the first element to be sorted
2177     * @param toIndex the index of the last element to be sorted plus one.     * @param toIndex the index of the last element to be sorted plus one
2178     * @exception ClassCastException if any two elements are not mutually     * @throws ClassCastException if any two elements are not mutually
2179     *   comparable by the Comparator provided     *         comparable
2180     * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex     * @throws NullPointerException if an element is null (since
2181     *   are not in range.     *         null.compareTo cannot work)
2182     * @exception IllegalArgumentException if fromIndex > toIndex     * @throws ArrayIndexOutOfBoundsException, if fromIndex and toIndex
2183       *         are not in range.
2184       * @throws IllegalArgumentException if fromIndex > toIndex
2185     */     */
2186    public static void sort(Object[]a, int fromIndex, int toIndex)    public static void sort(Object[] a, int fromIndex, int toIndex)
2187    {    {
2188      if (fromIndex > toIndex)      sort(a, fromIndex, toIndex, null);
       throw new IllegalArgumentException("fromIndex " + fromIndex  
                                          + " > toIndex " + toIndex);  
     mergeSort(a, fromIndex, toIndex, defaultComparator);  
2189    }    }
2190    
2191    /**    /**
# Line 2034  public class Arrays Line 2193  public class Arrays
2193     * guaranteed to be stable, that is, equal elements will not be reordered.     * guaranteed to be stable, that is, equal elements will not be reordered.
2194     * The sort algorithm is a mergesort with the merge omitted if the last     * The sort algorithm is a mergesort with the merge omitted if the last
2195     * element of one half comes before the first element of the other half. This     * element of one half comes before the first element of the other half. This
2196     * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a     * algorithm gives guaranteed O(n*log(n)) time, at the expense of making a
2197     * copy of the array.     * copy of the array.
2198     *     *
2199     * @param a the array to be sorted     * @param a the array to be sorted
2200     * @param fromIndex the index of the first element to be sorted.     * @param fromIndex the index of the first element to be sorted
2201     * @param toIndex the index of the last element to be sorted plus one.     * @param toIndex the index of the last element to be sorted plus one
2202     * @param c a Comparator to use in sorting the array     * @param c a Comparator to use in sorting the array; or null to indicate
2203     * @exception ClassCastException if any two elements are not mutually     *        the elements' natural order
2204     *   comparable by the Comparator provided     * @throws ClassCastException if any two elements are not mutually
2205     * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex     *         comparable by the Comparator provided
2206     *   are not in range.     * @throws ArrayIndexOutOfBoundsException, if fromIndex and toIndex
2207     * @exception IllegalArgumentException if fromIndex > toIndex     *         are not in range.
2208       * @throws IllegalArgumentException if fromIndex > toIndex
2209       * @throws NullPointerException if a null element is compared with natural
2210       *         ordering (only possible when c is null)
2211     */     */
2212    public static void sort(Object[]a, int fromIndex, int toIndex, Comparator c)    public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c)
2213    {    {
2214      if (fromIndex > toIndex)      if (fromIndex > toIndex)
2215        throw new IllegalArgumentException("fromIndex " + fromIndex        throw new IllegalArgumentException("fromIndex " + fromIndex
2216                                           + " > toIndex " + toIndex);                                           + " > toIndex " + toIndex);
2217      mergeSort(a, fromIndex, toIndex, c);  
2218        // In general, the code attempts to be simple rather than fast, the
2219        // idea being that a good optimising JIT will be able to optimise it
2220        // better than I can, and if I try it will make it more confusing for
2221        // the JIT. First presort the array in chunks of length 6 with insertion
2222        // sort. A mergesort would give too much overhead for this length.
2223        for (int chunk = fromIndex; chunk < toIndex; chunk += 6)
2224          {
2225            int end = Math.min(chunk + 6, toIndex);
2226            for (int i = chunk + 1; i < end; i++)
2227              {
2228                if (Collections.compare(a[i - 1], a[i], c) > 0)
2229                  {
2230                    // not already sorted
2231                    int j = i;
2232                    Object elem = a[j];
2233                    do
2234                      {
2235                        a[j] = a[j - 1];
2236                        j--;
2237                      }
2238                    while (j > chunk
2239                           && Collections.compare(a[j - 1], elem, c) > 0);
2240                    a[j] = elem;
2241                  }
2242              }
2243          }
2244    
2245        int len = toIndex - fromIndex;
2246        // If length is smaller or equal 6 we are done.
2247        if (len <= 6)
2248          return;
2249    
2250        Object[] src = a;
2251        Object[] dest = new Object[len];
2252        Object[] t = null; // t is used for swapping src and dest
2253    
2254        // The difference of the fromIndex of the src and dest array.
2255        int srcDestDiff = -fromIndex;
2256    
2257        // The merges are done in this loop
2258        for (int size = 6; size < len; size <<= 1)
2259          {
2260            for (int start = fromIndex; start < toIndex; start += size << 1)
2261              {
2262                // mid is the start of the second sublist;
2263                // end the start of the next sublist (or end of array).
2264                int mid = start + size;
2265                int end = Math.min(toIndex, mid + size);
2266    
2267                // The second list is empty or the elements are already in
2268                // order - no need to merge
2269                if (mid >= end
2270                    || Collections.compare(src[mid - 1], src[mid], c) <= 0)
2271                  {
2272                    System.arraycopy(src, start,
2273                                     dest, start + srcDestDiff, end - start);
2274    
2275                    // The two halves just need swapping - no need to merge
2276                  }
2277                else if (Collections.compare(src[start], src[end - 1], c) > 0)
2278                  {
2279                    System.arraycopy(src, start,
2280                                     dest, end - size + srcDestDiff, size);
2281                    System.arraycopy(src, mid,
2282                                     dest, start + srcDestDiff, end - mid);
2283    
2284                  }
2285                else
2286                  {
2287                    // Declare a lot of variables to save repeating
2288                    // calculations.  Hopefully a decent JIT will put these
2289                    // in registers and make this fast
2290                    int p1 = start;
2291                    int p2 = mid;
2292                    int i = start + srcDestDiff;
2293    
2294                    // The main merge loop; terminates as soon as either
2295                    // half is ended
2296                    while (p1 < mid && p2 < end)
2297                      {
2298                        dest[i++] =
2299                          src[(Collections.compare(src[p1], src[p2], c) <= 0
2300                               ? p1++ : p2++)];
2301                      }
2302    
2303                    // Finish up by copying the remainder of whichever half
2304                    // wasn't finished.
2305                    if (p1 < mid)
2306                      System.arraycopy(src, p1, dest, i, mid - p1);
2307                    else
2308                      System.arraycopy(src, p2, dest, i, end - p2);
2309                  }
2310              }
2311            // swap src and dest ready for the next merge
2312            t = src;
2313            src = dest;
2314            dest = t;
2315            fromIndex += srcDestDiff;
2316            toIndex += srcDestDiff;
2317            srcDestDiff = -srcDestDiff;
2318          }
2319    
2320        // make sure the result ends up back in the right place.  Note
2321        // that src and dest may have been swapped above, so src
2322        // contains the sorted array.
2323        if (src != a)
2324          {
2325            // Note that fromIndex == 0.
2326            System.arraycopy(src, 0, a, srcDestDiff, toIndex);
2327          }
2328    }    }
2329    
2330    
2331    // asList
2332    /**    /**
2333     * Returns a list "view" of the specified array. This method is intended to     * Returns a list "view" of the specified array. This method is intended to
2334     * make it easy to use the Collections API with existing array-based APIs and     * make it easy to use the Collections API with existing array-based APIs and
2335     * programs.     * programs. Changes in the list or the array show up in both places. The
2336       * list does not support element addition or removal, but does permit
2337       * value modification. The returned list implements both Serializable and
2338       * RandomAccess.
2339     *     *
2340     * @param a the array to return a view of     * @param a the array to return a view of
2341     * @returns a fixed-size list, changes to which "write through" to the array     * @return a fixed-size list, changes to which "write through" to the array
2342       * @see Serializable
2343       * @see RandomAccess
2344       * @see Arrays.ArrayList
2345     */     */
2346    public static List asList(final Object[]a)    public static List asList(final Object[] a)
2347    {    {
2348      if (a == null)      return new Arrays.ArrayList(a);
       {  
         throw new NullPointerException();  
       }  
   
     return new ListImpl(a);  
2349    }    }
2350    
   
2351    /**    /**
2352     * Inner class used by asList(Object[]) to provide a list interface     * Inner class used by {@link #asList(Object[])} to provide a list interface
2353     * to an array. The methods are all simple enough to be self documenting.     * to an array. The name, though it clashes with java.util.ArrayList, is
2354     * Note: When Sun fully specify serialized forms, this class will have to     * Sun's choice for Serialization purposes. Element addition and removal
2355     * be renamed.     * is prohibited, but values can be modified.
2356       *
2357       * @author Eric Blake <ebb9@email.byu.edu>
2358       * @status updated to 1.4
2359     */     */
2360    private static class ListImpl extends AbstractList    private static final class ArrayList extends AbstractList
2361        implements Serializable, RandomAccess
2362    {    {
2363      ListImpl(Object[]a)      // We override the necessary methods, plus others which will be much
2364        // more efficient with direct iteration rather than relying on iterator().
2365    
2366        /**
2367         * Compatible with JDK 1.4.
2368         */
2369        private static final long serialVersionUID = -2764017481108945198L;
2370    
2371        /**
2372         * The array we are viewing.
2373         * @serial the array
2374         */
2375        private final Object[] a;
2376    
2377        /**
2378         * Construct a list view of the array.
2379         * @param a the array to view
2380         * @throws NullPointerException if a is null
2381         */
2382        ArrayList(Object[] a)
2383      {      {
2384          // We have to explicitly check.
2385          if (a == null)
2386            throw new NullPointerException();
2387        this.a = a;        this.a = a;
2388      }      }
2389    
# Line 2104  public class Arrays Line 2404  public class Arrays
2404        return old;        return old;
2405      }      }
2406    
2407      private Object[] a;      public boolean contains(Object o)
2408        {
2409          for (int i = a.length - 1; i >= 0; i--)
2410            if (equals(o, a[i]))
2411              return true;
2412          return false;
2413        }
2414    
2415        public int indexOf(Object o)
2416        {
2417          int size = a.length;
2418          for (int i = 0; i < size; i++)
2419            if (equals(o, a[i]))
2420              return i;
2421          return -1;
2422        }
2423    
2424        public int lastIndexOf(Object o)
2425        {
2426          for (int i = a.length - 1; i >= 0; i--)
2427            if (equals(o, a[i]))
2428              return i;
2429          return -1;
2430        }
2431    
2432        public Object[] toArray()
2433        {
2434          return (Object[]) a.clone();
2435        }
2436    
2437        public Object[] toArray(Object[] array)
2438        {
2439          int size = a.length;
2440          if (array.length < size)
2441            array = (Object[])
2442              Array.newInstance(array.getClass().getComponentType(), size);
2443          else if (array.length > size)
2444            array[size] = null;
2445    
2446          System.arraycopy(a, 0, array, 0, size);
2447          return array;
2448        }
2449    }    }
2450  }  }

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26