1 /*
2  * Copyright (C) 2008 The Guava Authors
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 
17 package com.google.common.primitives;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndexes;
23 import static java.lang.Float.NEGATIVE_INFINITY;
24 import static java.lang.Float.POSITIVE_INFINITY;
25 
26 import com.google.common.annotations.Beta;
27 import com.google.common.annotations.GwtCompatible;
28 import com.google.common.annotations.GwtIncompatible;
29 import com.google.common.base.Converter;
30 
31 import java.io.Serializable;
32 import java.util.AbstractList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.List;
38 import java.util.RandomAccess;
39 
40 import javax.annotation.Nullable;
41 
42 /**
43  * Static utility methods pertaining to {@code float} primitives, that are not
44  * already found in either {@link Float} or {@link Arrays}.
45  *
46  * <p>See the Guava User Guide article on <a href=
47  * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
48  * primitive utilities</a>.
49  *
50  * @author Kevin Bourrillion
51  * @since 1.0
52  */
53 @GwtCompatible(emulated = true)
54 public final class Floats {
Floats()55   private Floats() {}
56 
57   /**
58    * The number of bytes required to represent a primitive {@code float}
59    * value.
60    *
61    * @since 10.0
62    */
63   public static final int BYTES = Float.SIZE / Byte.SIZE;
64 
65   /**
66    * Returns a hash code for {@code value}; equal to the result of invoking
67    * {@code ((Float) value).hashCode()}.
68    *
69    * @param value a primitive {@code float} value
70    * @return a hash code for the value
71    */
hashCode(float value)72   public static int hashCode(float value) {
73     // TODO(kevinb): is there a better way, that's still gwt-safe?
74     return ((Float) value).hashCode();
75   }
76 
77   /**
78    * Compares the two specified {@code float} values using {@link
79    * Float#compare(float, float)}. You may prefer to invoke that method
80    * directly; this method exists only for consistency with the other utilities
81    * in this package.
82    *
83    * <p><b>Note:</b> this method simply delegates to the JDK method {@link
84    * Float#compare}. It is provided for consistency with the other primitive
85    * types, whose compare methods were not added to the JDK until JDK 7.
86    *
87    * @param a the first {@code float} to compare
88    * @param b the second {@code float} to compare
89    * @return the result of invoking {@link Float#compare(float, float)}
90    */
compare(float a, float b)91   public static int compare(float a, float b) {
92     return Float.compare(a, b);
93   }
94 
95   /**
96    * Returns {@code true} if {@code value} represents a real number. This is
97    * equivalent to, but not necessarily implemented as,
98    * {@code !(Float.isInfinite(value) || Float.isNaN(value))}.
99    *
100    * @since 10.0
101    */
isFinite(float value)102   public static boolean isFinite(float value) {
103     return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
104   }
105 
106   /**
107    * Returns {@code true} if {@code target} is present as an element anywhere in
108    * {@code array}. Note that this always returns {@code false} when {@code
109    * target} is {@code NaN}.
110    *
111    * @param array an array of {@code float} values, possibly empty
112    * @param target a primitive {@code float} value
113    * @return {@code true} if {@code array[i] == target} for some value of {@code
114    *     i}
115    */
contains(float[] array, float target)116   public static boolean contains(float[] array, float target) {
117     for (float value : array) {
118       if (value == target) {
119         return true;
120       }
121     }
122     return false;
123   }
124 
125   /**
126    * Returns the index of the first appearance of the value {@code target} in
127    * {@code array}. Note that this always returns {@code -1} when {@code target}
128    * is {@code NaN}.
129    *
130    * @param array an array of {@code float} values, possibly empty
131    * @param target a primitive {@code float} value
132    * @return the least index {@code i} for which {@code array[i] == target}, or
133    *     {@code -1} if no such index exists.
134    */
indexOf(float[] array, float target)135   public static int indexOf(float[] array, float target) {
136     return indexOf(array, target, 0, array.length);
137   }
138 
139   // TODO(kevinb): consider making this public
indexOf( float[] array, float target, int start, int end)140   private static int indexOf(
141       float[] array, float target, int start, int end) {
142     for (int i = start; i < end; i++) {
143       if (array[i] == target) {
144         return i;
145       }
146     }
147     return -1;
148   }
149 
150   /**
151    * Returns the start position of the first occurrence of the specified {@code
152    * target} within {@code array}, or {@code -1} if there is no such occurrence.
153    *
154    * <p>More formally, returns the lowest index {@code i} such that {@code
155    * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
156    * the same elements as {@code target}.
157    *
158    * <p>Note that this always returns {@code -1} when {@code target} contains
159    * {@code NaN}.
160    *
161    * @param array the array to search for the sequence {@code target}
162    * @param target the array to search for as a sub-sequence of {@code array}
163    */
indexOf(float[] array, float[] target)164   public static int indexOf(float[] array, float[] target) {
165     checkNotNull(array, "array");
166     checkNotNull(target, "target");
167     if (target.length == 0) {
168       return 0;
169     }
170 
171     outer:
172     for (int i = 0; i < array.length - target.length + 1; i++) {
173       for (int j = 0; j < target.length; j++) {
174         if (array[i + j] != target[j]) {
175           continue outer;
176         }
177       }
178       return i;
179     }
180     return -1;
181   }
182 
183   /**
184    * Returns the index of the last appearance of the value {@code target} in
185    * {@code array}. Note that this always returns {@code -1} when {@code target}
186    * is {@code NaN}.
187    *
188    * @param array an array of {@code float} values, possibly empty
189    * @param target a primitive {@code float} value
190    * @return the greatest index {@code i} for which {@code array[i] == target},
191    *     or {@code -1} if no such index exists.
192    */
lastIndexOf(float[] array, float target)193   public static int lastIndexOf(float[] array, float target) {
194     return lastIndexOf(array, target, 0, array.length);
195   }
196 
197   // TODO(kevinb): consider making this public
lastIndexOf( float[] array, float target, int start, int end)198   private static int lastIndexOf(
199       float[] array, float target, int start, int end) {
200     for (int i = end - 1; i >= start; i--) {
201       if (array[i] == target) {
202         return i;
203       }
204     }
205     return -1;
206   }
207 
208   /**
209    * Returns the least value present in {@code array}, using the same rules of
210    * comparison as {@link Math#min(float, float)}.
211    *
212    * @param array a <i>nonempty</i> array of {@code float} values
213    * @return the value present in {@code array} that is less than or equal to
214    *     every other value in the array
215    * @throws IllegalArgumentException if {@code array} is empty
216    */
min(float... array)217   public static float min(float... array) {
218     checkArgument(array.length > 0);
219     float min = array[0];
220     for (int i = 1; i < array.length; i++) {
221       min = Math.min(min, array[i]);
222     }
223     return min;
224   }
225 
226   /**
227    * Returns the greatest value present in {@code array}, using the same rules
228    * of comparison as {@link Math#min(float, float)}.
229    *
230    * @param array a <i>nonempty</i> array of {@code float} values
231    * @return the value present in {@code array} that is greater than or equal to
232    *     every other value in the array
233    * @throws IllegalArgumentException if {@code array} is empty
234    */
max(float... array)235   public static float max(float... array) {
236     checkArgument(array.length > 0);
237     float max = array[0];
238     for (int i = 1; i < array.length; i++) {
239       max = Math.max(max, array[i]);
240     }
241     return max;
242   }
243 
244   /**
245    * Returns the values from each provided array combined into a single array.
246    * For example, {@code concat(new float[] {a, b}, new float[] {}, new
247    * float[] {c}} returns the array {@code {a, b, c}}.
248    *
249    * @param arrays zero or more {@code float} arrays
250    * @return a single array containing all the values from the source arrays, in
251    *     order
252    */
concat(float[]... arrays)253   public static float[] concat(float[]... arrays) {
254     int length = 0;
255     for (float[] array : arrays) {
256       length += array.length;
257     }
258     float[] result = new float[length];
259     int pos = 0;
260     for (float[] array : arrays) {
261       System.arraycopy(array, 0, result, pos, array.length);
262       pos += array.length;
263     }
264     return result;
265   }
266 
267   private static final class FloatConverter
268       extends Converter<String, Float> implements Serializable {
269     static final FloatConverter INSTANCE = new FloatConverter();
270 
271     @Override
doForward(String value)272     protected Float doForward(String value) {
273       return Float.valueOf(value);
274     }
275 
276     @Override
doBackward(Float value)277     protected String doBackward(Float value) {
278       return value.toString();
279     }
280 
281     @Override
toString()282     public String toString() {
283       return "Floats.stringConverter()";
284     }
285 
readResolve()286     private Object readResolve() {
287       return INSTANCE;
288     }
289     private static final long serialVersionUID = 1;
290   }
291 
292   /**
293    * Returns a serializable converter object that converts between strings and
294    * floats using {@link Float#valueOf} and {@link Float#toString()}.
295    *
296    * @since 16.0
297    */
298   @Beta
stringConverter()299   public static Converter<String, Float> stringConverter() {
300     return FloatConverter.INSTANCE;
301   }
302 
303   /**
304    * Returns an array containing the same values as {@code array}, but
305    * guaranteed to be of a specified minimum length. If {@code array} already
306    * has a length of at least {@code minLength}, it is returned directly.
307    * Otherwise, a new array of size {@code minLength + padding} is returned,
308    * containing the values of {@code array}, and zeroes in the remaining places.
309    *
310    * @param array the source array
311    * @param minLength the minimum length the returned array must guarantee
312    * @param padding an extra amount to "grow" the array by if growth is
313    *     necessary
314    * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
315    *     negative
316    * @return an array containing the values of {@code array}, with guaranteed
317    *     minimum length {@code minLength}
318    */
ensureCapacity( float[] array, int minLength, int padding)319   public static float[] ensureCapacity(
320       float[] array, int minLength, int padding) {
321     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
322     checkArgument(padding >= 0, "Invalid padding: %s", padding);
323     return (array.length < minLength)
324         ? copyOf(array, minLength + padding)
325         : array;
326   }
327 
328   // Arrays.copyOf() requires Java 6
copyOf(float[] original, int length)329   private static float[] copyOf(float[] original, int length) {
330     float[] copy = new float[length];
331     System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
332     return copy;
333   }
334 
335   /**
336    * Returns a string containing the supplied {@code float} values, converted
337    * to strings as specified by {@link Float#toString(float)}, and separated by
338    * {@code separator}. For example, {@code join("-", 1.0f, 2.0f, 3.0f)}
339    * returns the string {@code "1.0-2.0-3.0"}.
340    *
341    * <p>Note that {@link Float#toString(float)} formats {@code float}
342    * differently in GWT.  In the previous example, it returns the string {@code
343    * "1-2-3"}.
344    *
345    * @param separator the text that should appear between consecutive values in
346    *     the resulting string (but not at the start or end)
347    * @param array an array of {@code float} values, possibly empty
348    */
join(String separator, float... array)349   public static String join(String separator, float... array) {
350     checkNotNull(separator);
351     if (array.length == 0) {
352       return "";
353     }
354 
355     // For pre-sizing a builder, just get the right order of magnitude
356     StringBuilder builder = new StringBuilder(array.length * 12);
357     builder.append(array[0]);
358     for (int i = 1; i < array.length; i++) {
359       builder.append(separator).append(array[i]);
360     }
361     return builder.toString();
362   }
363 
364   /**
365    * Returns a comparator that compares two {@code float} arrays
366    * lexicographically. That is, it compares, using {@link
367    * #compare(float, float)}), the first pair of values that follow any
368    * common prefix, or when one array is a prefix of the other, treats the
369    * shorter array as the lesser. For example, {@code [] < [1.0f] < [1.0f, 2.0f]
370    * < [2.0f]}.
371    *
372    * <p>The returned comparator is inconsistent with {@link
373    * Object#equals(Object)} (since arrays support only identity equality), but
374    * it is consistent with {@link Arrays#equals(float[], float[])}.
375    *
376    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
377    *     Lexicographical order article at Wikipedia</a>
378    * @since 2.0
379    */
lexicographicalComparator()380   public static Comparator<float[]> lexicographicalComparator() {
381     return LexicographicalComparator.INSTANCE;
382   }
383 
384   private enum LexicographicalComparator implements Comparator<float[]> {
385     INSTANCE;
386 
387     @Override
compare(float[] left, float[] right)388     public int compare(float[] left, float[] right) {
389       int minLength = Math.min(left.length, right.length);
390       for (int i = 0; i < minLength; i++) {
391         int result = Float.compare(left[i], right[i]);
392         if (result != 0) {
393           return result;
394         }
395       }
396       return left.length - right.length;
397     }
398   }
399 
400   /**
401    * Returns an array containing each value of {@code collection}, converted to
402    * a {@code float} value in the manner of {@link Number#floatValue}.
403    *
404    * <p>Elements are copied from the argument collection as if by {@code
405    * collection.toArray()}.  Calling this method is as thread-safe as calling
406    * that method.
407    *
408    * @param collection a collection of {@code Number} instances
409    * @return an array containing the same values as {@code collection}, in the
410    *     same order, converted to primitives
411    * @throws NullPointerException if {@code collection} or any of its elements
412    *     is null
413    * @since 1.0 (parameter was {@code Collection<Float>} before 12.0)
414    */
toArray(Collection<? extends Number> collection)415   public static float[] toArray(Collection<? extends Number> collection) {
416     if (collection instanceof FloatArrayAsList) {
417       return ((FloatArrayAsList) collection).toFloatArray();
418     }
419 
420     Object[] boxedArray = collection.toArray();
421     int len = boxedArray.length;
422     float[] array = new float[len];
423     for (int i = 0; i < len; i++) {
424       // checkNotNull for GWT (do not optimize)
425       array[i] = ((Number) checkNotNull(boxedArray[i])).floatValue();
426     }
427     return array;
428   }
429 
430   /**
431    * Returns a fixed-size list backed by the specified array, similar to {@link
432    * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
433    * but any attempt to set a value to {@code null} will result in a {@link
434    * NullPointerException}.
435    *
436    * <p>The returned list maintains the values, but not the identities, of
437    * {@code Float} objects written to or read from it.  For example, whether
438    * {@code list.get(0) == list.get(0)} is true for the returned list is
439    * unspecified.
440    *
441    * <p>The returned list may have unexpected behavior if it contains {@code
442    * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
443    *
444    * @param backingArray the array to back the list
445    * @return a list view of the array
446    */
asList(float... backingArray)447   public static List<Float> asList(float... backingArray) {
448     if (backingArray.length == 0) {
449       return Collections.emptyList();
450     }
451     return new FloatArrayAsList(backingArray);
452   }
453 
454   @GwtCompatible
455   private static class FloatArrayAsList extends AbstractList<Float>
456       implements RandomAccess, Serializable {
457     final float[] array;
458     final int start;
459     final int end;
460 
FloatArrayAsList(float[] array)461     FloatArrayAsList(float[] array) {
462       this(array, 0, array.length);
463     }
464 
FloatArrayAsList(float[] array, int start, int end)465     FloatArrayAsList(float[] array, int start, int end) {
466       this.array = array;
467       this.start = start;
468       this.end = end;
469     }
470 
size()471     @Override public int size() {
472       return end - start;
473     }
474 
isEmpty()475     @Override public boolean isEmpty() {
476       return false;
477     }
478 
get(int index)479     @Override public Float get(int index) {
480       checkElementIndex(index, size());
481       return array[start + index];
482     }
483 
contains(Object target)484     @Override public boolean contains(Object target) {
485       // Overridden to prevent a ton of boxing
486       return (target instanceof Float)
487           && Floats.indexOf(array, (Float) target, start, end) != -1;
488     }
489 
indexOf(Object target)490     @Override public int indexOf(Object target) {
491       // Overridden to prevent a ton of boxing
492       if (target instanceof Float) {
493         int i = Floats.indexOf(array, (Float) target, start, end);
494         if (i >= 0) {
495           return i - start;
496         }
497       }
498       return -1;
499     }
500 
lastIndexOf(Object target)501     @Override public int lastIndexOf(Object target) {
502       // Overridden to prevent a ton of boxing
503       if (target instanceof Float) {
504         int i = Floats.lastIndexOf(array, (Float) target, start, end);
505         if (i >= 0) {
506           return i - start;
507         }
508       }
509       return -1;
510     }
511 
set(int index, Float element)512     @Override public Float set(int index, Float element) {
513       checkElementIndex(index, size());
514       float oldValue = array[start + index];
515       // checkNotNull for GWT (do not optimize)
516       array[start + index] = checkNotNull(element);
517       return oldValue;
518     }
519 
subList(int fromIndex, int toIndex)520     @Override public List<Float> subList(int fromIndex, int toIndex) {
521       int size = size();
522       checkPositionIndexes(fromIndex, toIndex, size);
523       if (fromIndex == toIndex) {
524         return Collections.emptyList();
525       }
526       return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
527     }
528 
equals(Object object)529     @Override public boolean equals(Object object) {
530       if (object == this) {
531         return true;
532       }
533       if (object instanceof FloatArrayAsList) {
534         FloatArrayAsList that = (FloatArrayAsList) object;
535         int size = size();
536         if (that.size() != size) {
537           return false;
538         }
539         for (int i = 0; i < size; i++) {
540           if (array[start + i] != that.array[that.start + i]) {
541             return false;
542           }
543         }
544         return true;
545       }
546       return super.equals(object);
547     }
548 
hashCode()549     @Override public int hashCode() {
550       int result = 1;
551       for (int i = start; i < end; i++) {
552         result = 31 * result + Floats.hashCode(array[i]);
553       }
554       return result;
555     }
556 
toString()557     @Override public String toString() {
558       StringBuilder builder = new StringBuilder(size() * 12);
559       builder.append('[').append(array[start]);
560       for (int i = start + 1; i < end; i++) {
561         builder.append(", ").append(array[i]);
562       }
563       return builder.append(']').toString();
564     }
565 
toFloatArray()566     float[] toFloatArray() {
567       // Arrays.copyOfRange() is not available under GWT
568       int size = size();
569       float[] result = new float[size];
570       System.arraycopy(array, start, result, 0, size);
571       return result;
572     }
573 
574     private static final long serialVersionUID = 0;
575   }
576 
577   /**
578    * Parses the specified string as a single-precision floating point value.
579    * The ASCII character {@code '-'} (<code>'&#92;u002D'</code>) is recognized
580    * as the minus sign.
581    *
582    * <p>Unlike {@link Float#parseFloat(String)}, this method returns
583    * {@code null} instead of throwing an exception if parsing fails.
584    * Valid inputs are exactly those accepted by {@link Float#valueOf(String)},
585    * except that leading and trailing whitespace is not permitted.
586    *
587    * <p>This implementation is likely to be faster than {@code
588    * Float.parseFloat} if many failures are expected.
589    *
590    * @param string the string representation of a {@code float} value
591    * @return the floating point value represented by {@code string}, or
592    *     {@code null} if {@code string} has a length of zero or cannot be
593    *     parsed as a {@code float} value
594    * @since 14.0
595    */
596   @GwtIncompatible("regular expressions")
597   @Nullable
598   @Beta
tryParse(String string)599   public static Float tryParse(String string) {
600     if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) {
601       // TODO(user): could be potentially optimized, but only with
602       // extensive testing
603       try {
604         return Float.parseFloat(string);
605       } catch (NumberFormatException e) {
606         // Float.parseFloat has changed specs several times, so fall through
607         // gracefully
608       }
609     }
610     return null;
611   }
612 }
613