001 /*
002 * Copyright (C) 2008 Google Inc.
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: 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: 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 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 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 }