1/*
2 * Copyright (C) 2008 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.primitives;
18
19import com.google.common.annotations.GwtCompatible;
20
21import java.io.Serializable;
22import java.util.AbstractList;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.Collections;
26import java.util.Comparator;
27import java.util.List;
28import java.util.RandomAccess;
29
30import static com.google.common.base.Preconditions.checkArgument;
31import static com.google.common.base.Preconditions.checkElementIndex;
32import static com.google.common.base.Preconditions.checkNotNull;
33import static com.google.common.base.Preconditions.checkPositionIndexes;
34
35/**
36 * Static utility methods pertaining to {@code double} primitives, that are not
37 * already found in either {@link Double} or {@link Arrays}.
38 *
39 * @author Kevin Bourrillion
40 * @since 2009.09.15 <b>tentative</b>
41 */
42@GwtCompatible
43public final class Doubles {
44  private Doubles() {}
45
46  /**
47   * Returns a hash code for {@code value}; equal to the result of invoking
48   * {@code ((Double) value).hashCode()}.
49   *
50   * @param value a primitive {@code double} value
51   * @return a hash code for the value
52   */
53  public static int hashCode(double value) {
54    return ((Double) value).hashCode();
55    // TODO: do it this way when we can (GWT problem):
56    // long bits = Double.doubleToLongBits(value);
57    // return (int)(bits ^ (bits >>> 32));
58  }
59
60  /**
61   * Compares the two specified {@code double} values. The sign of the value
62   * returned is the same as that of <code>((Double) a).{@linkplain
63   * Double#compareTo compareTo}(b)</code>. As with that method, {@code NaN} is
64   * treated as greater than all other values, and {@code 0.0 > -0.0}.
65   *
66   * @param a the first {@code double} to compare
67   * @param b the second {@code double} to compare
68   * @return a negative value if {@code a} is less than {@code b}; a positive
69   *     value if {@code a} is greater than {@code b}; or zero if they are equal
70   */
71  public static int compare(double a, double b) {
72    return Double.compare(a, b);
73  }
74
75  /**
76   * Returns {@code true} if {@code target} is present as an element anywhere in
77   * {@code array}. Note that this always returns {@code false} when {@code
78   * target} is {@code NaN}.
79   *
80   * @param array an array of {@code double} values, possibly empty
81   * @param target a primitive {@code double} value
82   * @return {@code true} if {@code array[i] == target} for some value of {@code
83   *     i}
84   */
85  public static boolean contains(double[] array, double target) {
86    for (double value : array) {
87      if (value == target) {
88        return true;
89      }
90    }
91    return false;
92  }
93
94  /**
95   * Returns the index of the first appearance of the value {@code target} in
96   * {@code array}. Note that this always returns {@code -1} when {@code target}
97   * is {@code NaN}.
98   *
99   * @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: 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: 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</a> article at Wikipedia
307   * @since 2010.01.04 <b>tentative</b>
308   */
309  public static Comparator<double[]> lexicographicalComparator() {
310    return LexicographicalComparator.INSTANCE;
311  }
312
313  private enum LexicographicalComparator implements Comparator<double[]> {
314    INSTANCE;
315
316    public int compare(double[] left, double[] right) {
317      int minLength = Math.min(left.length, right.length);
318      for (int i = 0; i < minLength; i++) {
319        int result = Doubles.compare(left[i], right[i]);
320        if (result != 0) {
321          return result;
322        }
323      }
324      return left.length - right.length;
325    }
326  }
327
328  /**
329   * Copies a collection of {@code Double} instances into a new array of
330   * primitive {@code double} values.
331   *
332   * <p>Elements are copied from the argument collection as if by {@code
333   * collection.toArray()}.  Calling this method is as thread-safe as calling
334   * that method.
335   *
336   * @param collection a collection of {@code Double} objects
337   * @return an array containing the same values as {@code collection}, in the
338   *     same order, converted to primitives
339   * @throws NullPointerException if {@code collection} or any of its elements
340   *     is null
341   */
342  public static double[] toArray(Collection<Double> collection) {
343    if (collection instanceof DoubleArrayAsList) {
344      return ((DoubleArrayAsList) collection).toDoubleArray();
345    }
346
347    Object[] boxedArray = collection.toArray();
348    int len = boxedArray.length;
349    double[] array = new double[len];
350    for (int i = 0; i < len; i++) {
351      array[i] = (Double) boxedArray[i];
352    }
353    return array;
354  }
355
356  /**
357   * Returns a fixed-size list backed by the specified array, similar to {@link
358   * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
359   * but any attempt to set a value to {@code null} will result in a {@link
360   * NullPointerException}.
361   *
362   * <p>The returned list maintains the values, but not the identities, of
363   * {@code Double} objects written to or read from it.  For example, whether
364   * {@code list.get(0) == list.get(0)} is true for the returned list is
365   * unspecified.
366   *
367   * <p>The returned list may have unexpected behavior if it contains {@code
368   * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
369   *
370   * @param backingArray the array to back the list
371   * @return a list view of the array
372   */
373  public static List<Double> asList(double... backingArray) {
374    if (backingArray.length == 0) {
375      return Collections.emptyList();
376    }
377    return new DoubleArrayAsList(backingArray);
378  }
379
380  @GwtCompatible
381  private static class DoubleArrayAsList extends AbstractList<Double>
382      implements RandomAccess, Serializable {
383    final double[] array;
384    final int start;
385    final int end;
386
387    DoubleArrayAsList(double[] array) {
388      this(array, 0, array.length);
389    }
390
391    DoubleArrayAsList(double[] array, int start, int end) {
392      this.array = array;
393      this.start = start;
394      this.end = end;
395    }
396
397    @Override public int size() {
398      return end - start;
399    }
400
401    @Override public boolean isEmpty() {
402      return false;
403    }
404
405    @Override public Double get(int index) {
406      checkElementIndex(index, size());
407      return array[start + index];
408    }
409
410    @Override public boolean contains(Object target) {
411      // Overridden to prevent a ton of boxing
412      return (target instanceof Double)
413          && Doubles.indexOf(array, (Double) target, start, end) != -1;
414    }
415
416    @Override public int indexOf(Object target) {
417      // Overridden to prevent a ton of boxing
418      if (target instanceof Double) {
419        int i = Doubles.indexOf(array, (Double) target, start, end);
420        if (i >= 0) {
421          return i - start;
422        }
423      }
424      return -1;
425    }
426
427    @Override public int lastIndexOf(Object target) {
428      // Overridden to prevent a ton of boxing
429      if (target instanceof Double) {
430        int i = Doubles.lastIndexOf(array, (Double) target, start, end);
431        if (i >= 0) {
432          return i - start;
433        }
434      }
435      return -1;
436    }
437
438    @Override public Double set(int index, Double element) {
439      checkElementIndex(index, size());
440      double oldValue = array[start + index];
441      array[start + index] = element;
442      return oldValue;
443    }
444
445    /** In GWT, List and AbstractList do not have the subList method. */
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}
503