001    /*
002     * Copyright (C) 2008 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.primitives;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkElementIndex;
021    import static com.google.common.base.Preconditions.checkNotNull;
022    import static com.google.common.base.Preconditions.checkPositionIndexes;
023    
024    import com.google.common.annotations.GwtCompatible;
025    
026    import java.io.Serializable;
027    import java.util.AbstractList;
028    import java.util.Arrays;
029    import java.util.Collection;
030    import java.util.Collections;
031    import java.util.Comparator;
032    import java.util.List;
033    import java.util.RandomAccess;
034    
035    /**
036     * Static utility methods pertaining to {@code double} primitives, that are not
037     * already found in either {@link Double} or {@link Arrays}.
038     *
039     * @author Kevin Bourrillion
040     * @since 1
041     */
042    @GwtCompatible
043    public final class Doubles {
044      private Doubles() {}
045    
046      /**
047       * Returns a hash code for {@code value}; equal to the result of invoking
048       * {@code ((Double) value).hashCode()}.
049       *
050       * @param value a primitive {@code double} value
051       * @return a hash code for the value
052       */
053      public static int hashCode(double value) {
054        return ((Double) value).hashCode();
055        // TODO(kevinb): do it this way when we can (GWT problem):
056        // long bits = Double.doubleToLongBits(value);
057        // return (int)(bits ^ (bits >>> 32));
058      }
059    
060      /**
061       * Compares the two specified {@code double} values. The sign of the value
062       * returned is the same as that of <code>((Double) a).{@linkplain
063       * Double#compareTo compareTo}(b)</code>. As with that method, {@code NaN} is
064       * treated as greater than all other values, and {@code 0.0 > -0.0}.
065       *
066       * @param a the first {@code double} to compare
067       * @param b the second {@code double} to compare
068       * @return a negative value if {@code a} is less than {@code b}; a positive
069       *     value if {@code a} is greater than {@code b}; or zero if they are equal
070       */
071      public static int compare(double a, double b) {
072        return Double.compare(a, b);
073      }
074    
075      /**
076       * Returns {@code true} if {@code target} is present as an element anywhere in
077       * {@code array}. Note that this always returns {@code false} when {@code
078       * target} is {@code NaN}.
079       *
080       * @param array an array of {@code double} values, possibly empty
081       * @param target a primitive {@code double} value
082       * @return {@code true} if {@code array[i] == target} for some value of {@code
083       *     i}
084       */
085      public static boolean contains(double[] array, double target) {
086        for (double value : array) {
087          if (value == target) {
088            return true;
089          }
090        }
091        return false;
092      }
093    
094      /**
095       * Returns the index of the first appearance of the value {@code target} in
096       * {@code array}. Note that this always returns {@code -1} when {@code target}
097       * is {@code NaN}.
098       *
099       * @param array an array of {@code double} values, possibly empty
100       * @param target a primitive {@code double} value
101       * @return the least index {@code i} for which {@code array[i] == target}, or
102       *     {@code -1} if no such index exists.
103       */
104      public static int indexOf(double[] array, double target) {
105        return indexOf(array, target, 0, array.length);
106      }
107    
108      // TODO(kevinb): consider making this public
109      private static int indexOf(
110          double[] array, double target, int start, int end) {
111        for (int i = start; i < end; i++) {
112          if (array[i] == target) {
113            return i;
114          }
115        }
116        return -1;
117      }
118    
119      /**
120       * Returns the start position of the first occurrence of the specified {@code
121       * target} within {@code array}, or {@code -1} if there is no such occurrence.
122       *
123       * <p>More formally, returns the lowest index {@code i} such that {@code
124       * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
125       * the same elements as {@code target}.
126       *
127       * <p>Note that this always returns {@code -1} when {@code target} contains
128       * {@code NaN}.
129       *
130       * @param array the array to search for the sequence {@code target}
131       * @param target the array to search for as a sub-sequence of {@code array}
132       */
133      public static int indexOf(double[] array, double[] target) {
134        checkNotNull(array, "array");
135        checkNotNull(target, "target");
136        if (target.length == 0) {
137          return 0;
138        }
139    
140        outer:
141        for (int i = 0; i < array.length - target.length + 1; i++) {
142          for (int j = 0; j < target.length; j++) {
143            if (array[i + j] != target[j]) {
144              continue outer;
145            }
146          }
147          return i;
148        }
149        return -1;
150      }
151    
152      /**
153       * Returns the index of the last appearance of the value {@code target} in
154       * {@code array}. Note that this always returns {@code -1} when {@code target}
155       * is {@code NaN}.
156       *
157       * @param array an array of {@code double} values, possibly empty
158       * @param target a primitive {@code double} value
159       * @return the greatest index {@code i} for which {@code array[i] == target},
160       *     or {@code -1} if no such index exists.
161       */
162      public static int lastIndexOf(double[] array, double target) {
163        return lastIndexOf(array, target, 0, array.length);
164      }
165    
166      // TODO(kevinb): consider making this public
167      private static int lastIndexOf(
168          double[] array, double target, int start, int end) {
169        for (int i = end - 1; i >= start; i--) {
170          if (array[i] == target) {
171            return i;
172          }
173        }
174        return -1;
175      }
176    
177      /**
178       * Returns the least value present in {@code array}, using the same rules of
179       * comparison as {@link Math#min(double, double)}.
180       *
181       * @param array a <i>nonempty</i> array of {@code double} values
182       * @return the value present in {@code array} that is less than or equal to
183       *     every other value in the array
184       * @throws IllegalArgumentException if {@code array} is empty
185       */
186      public static double min(double... array) {
187        checkArgument(array.length > 0);
188        double min = array[0];
189        for (int i = 1; i < array.length; i++) {
190          min = Math.min(min, array[i]);
191        }
192        return min;
193      }
194    
195      /**
196       * Returns the greatest value present in {@code array}, using the same rules
197       * of comparison as {@link Math#max(double, double)}.
198       *
199       * @param array a <i>nonempty</i> array of {@code double} values
200       * @return the value present in {@code array} that is greater than or equal to
201       *     every other value in the array
202       * @throws IllegalArgumentException if {@code array} is empty
203       */
204      public static double max(double... array) {
205        checkArgument(array.length > 0);
206        double max = array[0];
207        for (int i = 1; i < array.length; i++) {
208          max = Math.max(max, array[i]);
209        }
210        return max;
211      }
212    
213      /**
214       * Returns the values from each provided array combined into a single array.
215       * For example, {@code concat(new double[] {a, b}, new double[] {}, new
216       * double[] {c}} returns the array {@code {a, b, c}}.
217       *
218       * @param arrays zero or more {@code double} arrays
219       * @return a single array containing all the values from the source arrays, in
220       *     order
221       */
222      public static double[] concat(double[]... arrays) {
223        int length = 0;
224        for (double[] array : arrays) {
225          length += array.length;
226        }
227        double[] result = new double[length];
228        int pos = 0;
229        for (double[] array : arrays) {
230          System.arraycopy(array, 0, result, pos, array.length);
231          pos += array.length;
232        }
233        return result;
234      }
235    
236      /**
237       * Returns an array containing the same values as {@code array}, but
238       * guaranteed to be of a specified minimum length. If {@code array} already
239       * has a length of at least {@code minLength}, it is returned directly.
240       * Otherwise, a new array of size {@code minLength + padding} is returned,
241       * containing the values of {@code array}, and zeroes in the remaining places.
242       *
243       * @param array the source array
244       * @param minLength the minimum length the returned array must guarantee
245       * @param padding an extra amount to "grow" the array by if growth is
246       *     necessary
247       * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
248       *     negative
249       * @return an array containing the values of {@code array}, with guaranteed
250       *     minimum length {@code minLength}
251       */
252      public static double[] ensureCapacity(
253          double[] array, int minLength, int padding) {
254        checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
255        checkArgument(padding >= 0, "Invalid padding: %s", padding);
256        return (array.length < minLength)
257            ? copyOf(array, minLength + padding)
258            : array;
259      }
260    
261      // Arrays.copyOf() requires Java 6
262      private static double[] copyOf(double[] original, int length) {
263        double[] copy = new double[length];
264        System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
265        return copy;
266      }
267    
268      /**
269       * Returns a string containing the supplied {@code double} values, converted
270       * to strings as specified by {@link Double#toString(double)}, and separated
271       * by {@code separator}. For example, {@code join("-", 1.0, 2.0, 3.0)} returns
272       * the string {@code "1.0-2.0-3.0"}.
273       *
274       * @param separator the text that should appear between consecutive values in
275       *     the resulting string (but not at the start or end)
276       * @param array an array of {@code double} values, possibly empty
277       */
278      public static String join(String separator, double... array) {
279        checkNotNull(separator);
280        if (array.length == 0) {
281          return "";
282        }
283    
284        // For pre-sizing a builder, just get the right order of magnitude
285        StringBuilder builder = new StringBuilder(array.length * 12);
286        builder.append(array[0]);
287        for (int i = 1; i < array.length; i++) {
288          builder.append(separator).append(array[i]);
289        }
290        return builder.toString();
291      }
292    
293      /**
294       * Returns a comparator that compares two {@code double} arrays
295       * lexicographically. That is, it compares, using {@link
296       * #compare(double, double)}), the first pair of values that follow any
297       * common prefix, or when one array is a prefix of the other, treats the
298       * shorter array as the lesser. For example,
299       * {@code [] < [1.0] < [1.0, 2.0] < [2.0]}.
300       *
301       * <p>The returned comparator is inconsistent with {@link
302       * Object#equals(Object)} (since arrays support only identity equality), but
303       * it is consistent with {@link Arrays#equals(double[], double[])}.
304       *
305       * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
306       *     Lexicographical order article at Wikipedia</a>
307       * @since 2
308       */
309      public static Comparator<double[]> lexicographicalComparator() {
310        return LexicographicalComparator.INSTANCE;
311      }
312    
313      private enum LexicographicalComparator implements Comparator<double[]> {
314        INSTANCE;
315    
316        @Override
317        public int compare(double[] left, double[] right) {
318          int minLength = Math.min(left.length, right.length);
319          for (int i = 0; i < minLength; i++) {
320            int result = Doubles.compare(left[i], right[i]);
321            if (result != 0) {
322              return result;
323            }
324          }
325          return left.length - right.length;
326        }
327      }
328    
329      /**
330       * Copies a collection of {@code Double} instances into a new array of
331       * primitive {@code double} values.
332       *
333       * <p>Elements are copied from the argument collection as if by {@code
334       * collection.toArray()}.  Calling this method is as thread-safe as calling
335       * that method.
336       *
337       * @param collection a collection of {@code Double} objects
338       * @return an array containing the same values as {@code collection}, in the
339       *     same order, converted to primitives
340       * @throws NullPointerException if {@code collection} or any of its elements
341       *     is null
342       */
343      public static double[] toArray(Collection<Double> collection) {
344        if (collection instanceof DoubleArrayAsList) {
345          return ((DoubleArrayAsList) collection).toDoubleArray();
346        }
347    
348        Object[] boxedArray = collection.toArray();
349        int len = boxedArray.length;
350        double[] array = new double[len];
351        for (int i = 0; i < len; i++) {
352          array[i] = (Double) boxedArray[i];
353        }
354        return array;
355      }
356    
357      /**
358       * Returns a fixed-size list backed by the specified array, similar to {@link
359       * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
360       * but any attempt to set a value to {@code null} will result in a {@link
361       * NullPointerException}.
362       *
363       * <p>The returned list maintains the values, but not the identities, of
364       * {@code Double} objects written to or read from it.  For example, whether
365       * {@code list.get(0) == list.get(0)} is true for the returned list is
366       * unspecified.
367       *
368       * <p>The returned list may have unexpected behavior if it contains {@code
369       * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
370       *
371       * @param backingArray the array to back the list
372       * @return a list view of the array
373       */
374      public static List<Double> asList(double... backingArray) {
375        if (backingArray.length == 0) {
376          return Collections.emptyList();
377        }
378        return new DoubleArrayAsList(backingArray);
379      }
380    
381      @GwtCompatible
382      private static class DoubleArrayAsList extends AbstractList<Double>
383          implements RandomAccess, Serializable {
384        final double[] array;
385        final int start;
386        final int end;
387    
388        DoubleArrayAsList(double[] array) {
389          this(array, 0, array.length);
390        }
391    
392        DoubleArrayAsList(double[] array, int start, int end) {
393          this.array = array;
394          this.start = start;
395          this.end = end;
396        }
397    
398        @Override public int size() {
399          return end - start;
400        }
401    
402        @Override public boolean isEmpty() {
403          return false;
404        }
405    
406        @Override public Double get(int index) {
407          checkElementIndex(index, size());
408          return array[start + index];
409        }
410    
411        @Override public boolean contains(Object target) {
412          // Overridden to prevent a ton of boxing
413          return (target instanceof Double)
414              && Doubles.indexOf(array, (Double) target, start, end) != -1;
415        }
416    
417        @Override public int indexOf(Object target) {
418          // Overridden to prevent a ton of boxing
419          if (target instanceof Double) {
420            int i = Doubles.indexOf(array, (Double) target, start, end);
421            if (i >= 0) {
422              return i - start;
423            }
424          }
425          return -1;
426        }
427    
428        @Override public int lastIndexOf(Object target) {
429          // Overridden to prevent a ton of boxing
430          if (target instanceof Double) {
431            int i = Doubles.lastIndexOf(array, (Double) target, start, end);
432            if (i >= 0) {
433              return i - start;
434            }
435          }
436          return -1;
437        }
438    
439        @Override public Double set(int index, Double element) {
440          checkElementIndex(index, size());
441          double oldValue = array[start + index];
442          array[start + index] = element;
443          return oldValue;
444        }
445    
446        @Override public List<Double> subList(int fromIndex, int toIndex) {
447          int size = size();
448          checkPositionIndexes(fromIndex, toIndex, size);
449          if (fromIndex == toIndex) {
450            return Collections.emptyList();
451          }
452          return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
453        }
454    
455        @Override public boolean equals(Object object) {
456          if (object == this) {
457            return true;
458          }
459          if (object instanceof DoubleArrayAsList) {
460            DoubleArrayAsList that = (DoubleArrayAsList) object;
461            int size = size();
462            if (that.size() != size) {
463              return false;
464            }
465            for (int i = 0; i < size; i++) {
466              if (array[start + i] != that.array[that.start + i]) {
467                return false;
468              }
469            }
470            return true;
471          }
472          return super.equals(object);
473        }
474    
475        @Override public int hashCode() {
476          int result = 1;
477          for (int i = start; i < end; i++) {
478            result = 31 * result + Doubles.hashCode(array[i]);
479          }
480          return result;
481        }
482    
483        @Override public String toString() {
484          StringBuilder builder = new StringBuilder(size() * 12);
485          builder.append('[').append(array[start]);
486          for (int i = start + 1; i < end; i++) {
487            builder.append(", ").append(array[i]);
488          }
489          return builder.append(']').toString();
490        }
491    
492        double[] toDoubleArray() {
493          // Arrays.copyOfRange() requires Java 6
494          int size = size();
495          double[] result = new double[size];
496          System.arraycopy(array, start, result, 0, size);
497          return result;
498        }
499    
500        private static final long serialVersionUID = 0;
501      }
502    }