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>'\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