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;
029import com.google.common.base.Converter;
030
031import java.io.Serializable;
032import java.util.AbstractList;
033import java.util.Arrays;
034import java.util.Collection;
035import java.util.Collections;
036import java.util.Comparator;
037import java.util.List;
038import java.util.RandomAccess;
039
040import javax.annotation.Nullable;
041
042/**
043 * Static utility methods pertaining to {@code float} primitives, that are not
044 * already found in either {@link Float} or {@link Arrays}.
045 *
046 * <p>See the Guava User Guide article on <a href=
047 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
048 * primitive utilities</a>.
049 *
050 * @author Kevin Bourrillion
051 * @since 1.0
052 */
053@GwtCompatible(emulated = true)
054public final class Floats {
055  private Floats() {}
056
057  /**
058   * The number of bytes required to represent a primitive {@code float}
059   * value.
060   *
061   * @since 10.0
062   */
063  public static final int BYTES = Float.SIZE / Byte.SIZE;
064
065  /**
066   * Returns a hash code for {@code value}; equal to the result of invoking
067   * {@code ((Float) value).hashCode()}.
068   *
069   * @param value a primitive {@code float} value
070   * @return a hash code for the value
071   */
072  public static int hashCode(float value) {
073    // TODO(kevinb): is there a better way, that's still gwt-safe?
074    return ((Float) value).hashCode();
075  }
076
077  /**
078   * Compares the two specified {@code float} values using {@link
079   * Float#compare(float, float)}. You may prefer to invoke that method
080   * directly; this method exists only for consistency with the other utilities
081   * in this package.
082   *
083   * <p><b>Note:</b> this method simply delegates to the JDK method {@link
084   * Float#compare}. It is provided for consistency with the other primitive
085   * types, whose compare methods were not added to the JDK until JDK 7.
086   *
087   * @param a the first {@code float} to compare
088   * @param b the second {@code float} to compare
089   * @return the result of invoking {@link Float#compare(float, float)}
090   */
091  public static int compare(float a, float b) {
092    return Float.compare(a, b);
093  }
094
095  /**
096   * Returns {@code true} if {@code value} represents a real number. This is
097   * equivalent to, but not necessarily implemented as,
098   * {@code !(Float.isInfinite(value) || Float.isNaN(value))}.
099   *
100   * @since 10.0
101   */
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   */
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   */
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
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   */
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   */
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
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   */
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   */
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   */
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
272    protected Float doForward(String value) {
273      return Float.valueOf(value);
274    }
275
276    @Override
277    protected String doBackward(Float value) {
278      return value.toString();
279    }
280
281    @Override
282    public String toString() {
283      return "Floats.stringConverter()";
284    }
285
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
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   */
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
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   */
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   */
380  public static Comparator<float[]> lexicographicalComparator() {
381    return LexicographicalComparator.INSTANCE;
382  }
383
384  private enum LexicographicalComparator implements Comparator<float[]> {
385    INSTANCE;
386
387    @Override
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   */
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   */
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
461    FloatArrayAsList(float[] array) {
462      this(array, 0, array.length);
463    }
464
465    FloatArrayAsList(float[] array, int start, int end) {
466      this.array = array;
467      this.start = start;
468      this.end = end;
469    }
470
471    @Override public int size() {
472      return end - start;
473    }
474
475    @Override public boolean isEmpty() {
476      return false;
477    }
478
479    @Override public Float get(int index) {
480      checkElementIndex(index, size());
481      return array[start + index];
482    }
483
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
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
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
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
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
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
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
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
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
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}