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