1 /* 2 * Copyright (C) 2016 The Android Open Source Project 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 android.util; 18 19 import android.annotation.HalfFloat; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 23 import libcore.util.FP16; 24 25 /** 26 * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit 27 * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a> 28 * floating point data types (also called fp16 or binary16). A half-precision float can be 29 * created from or converted to single-precision floats, and is stored in a short data type. 30 * To distinguish short values holding half-precision floats from regular short values, 31 * it is recommended to use the <code>@HalfFloat</code> annotation.</p> 32 * 33 * <p>The IEEE 754 standard specifies an fp16 as having the following format:</p> 34 * <ul> 35 * <li>Sign bit: 1 bit</li> 36 * <li>Exponent width: 5 bits</li> 37 * <li>Significand: 10 bits</li> 38 * </ul> 39 * 40 * <p>The format is laid out as follows:</p> 41 * <pre> 42 * 1 11111 1111111111 43 * ^ --^-- -----^---- 44 * sign | |_______ significand 45 * | 46 * -- exponent 47 * </pre> 48 * 49 * <p>Half-precision floating points can be useful to save memory and/or 50 * bandwidth at the expense of range and precision when compared to single-precision 51 * floating points (fp32).</p> 52 * <p>To help you decide whether fp16 is the right storage type for you need, please 53 * refer to the table below that shows the available precision throughout the range of 54 * possible values. The <em>precision</em> column indicates the step size between two 55 * consecutive numbers in a specific part of the range.</p> 56 * 57 * <table summary="Precision of fp16 across the range"> 58 * <tr><th>Range start</th><th>Precision</th></tr> 59 * <tr><td>0</td><td>1 ⁄ 16,777,216</td></tr> 60 * <tr><td>1 ⁄ 16,384</td><td>1 ⁄ 16,777,216</td></tr> 61 * <tr><td>1 ⁄ 8,192</td><td>1 ⁄ 8,388,608</td></tr> 62 * <tr><td>1 ⁄ 4,096</td><td>1 ⁄ 4,194,304</td></tr> 63 * <tr><td>1 ⁄ 2,048</td><td>1 ⁄ 2,097,152</td></tr> 64 * <tr><td>1 ⁄ 1,024</td><td>1 ⁄ 1,048,576</td></tr> 65 * <tr><td>1 ⁄ 512</td><td>1 ⁄ 524,288</td></tr> 66 * <tr><td>1 ⁄ 256</td><td>1 ⁄ 262,144</td></tr> 67 * <tr><td>1 ⁄ 128</td><td>1 ⁄ 131,072</td></tr> 68 * <tr><td>1 ⁄ 64</td><td>1 ⁄ 65,536</td></tr> 69 * <tr><td>1 ⁄ 32</td><td>1 ⁄ 32,768</td></tr> 70 * <tr><td>1 ⁄ 16</td><td>1 ⁄ 16,384</td></tr> 71 * <tr><td>1 ⁄ 8</td><td>1 ⁄ 8,192</td></tr> 72 * <tr><td>1 ⁄ 4</td><td>1 ⁄ 4,096</td></tr> 73 * <tr><td>1 ⁄ 2</td><td>1 ⁄ 2,048</td></tr> 74 * <tr><td>1</td><td>1 ⁄ 1,024</td></tr> 75 * <tr><td>2</td><td>1 ⁄ 512</td></tr> 76 * <tr><td>4</td><td>1 ⁄ 256</td></tr> 77 * <tr><td>8</td><td>1 ⁄ 128</td></tr> 78 * <tr><td>16</td><td>1 ⁄ 64</td></tr> 79 * <tr><td>32</td><td>1 ⁄ 32</td></tr> 80 * <tr><td>64</td><td>1 ⁄ 16</td></tr> 81 * <tr><td>128</td><td>1 ⁄ 8</td></tr> 82 * <tr><td>256</td><td>1 ⁄ 4</td></tr> 83 * <tr><td>512</td><td>1 ⁄ 2</td></tr> 84 * <tr><td>1,024</td><td>1</td></tr> 85 * <tr><td>2,048</td><td>2</td></tr> 86 * <tr><td>4,096</td><td>4</td></tr> 87 * <tr><td>8,192</td><td>8</td></tr> 88 * <tr><td>16,384</td><td>16</td></tr> 89 * <tr><td>32,768</td><td>32</td></tr> 90 * </table> 91 * 92 * <p>This table shows that numbers higher than 1024 lose all fractional precision.</p> 93 */ 94 @SuppressWarnings("SimplifiableIfStatement") 95 public final class Half extends Number implements Comparable<Half> { 96 /** 97 * The number of bits used to represent a half-precision float value. 98 */ 99 public static final int SIZE = 16; 100 101 /** 102 * Epsilon is the difference between 1.0 and the next value representable 103 * by a half-precision floating-point. 104 */ 105 public static final @HalfFloat short EPSILON = (short) 0x1400; 106 107 /** 108 * Maximum exponent a finite half-precision float may have. 109 */ 110 public static final int MAX_EXPONENT = 15; 111 /** 112 * Minimum exponent a normalized half-precision float may have. 113 */ 114 public static final int MIN_EXPONENT = -14; 115 116 /** 117 * Smallest negative value a half-precision float may have. 118 */ 119 public static final @HalfFloat short LOWEST_VALUE = (short) 0xfbff; 120 /** 121 * Maximum positive finite value a half-precision float may have. 122 */ 123 public static final @HalfFloat short MAX_VALUE = (short) 0x7bff; 124 /** 125 * Smallest positive normal value a half-precision float may have. 126 */ 127 public static final @HalfFloat short MIN_NORMAL = (short) 0x0400; 128 /** 129 * Smallest positive non-zero value a half-precision float may have. 130 */ 131 public static final @HalfFloat short MIN_VALUE = (short) 0x0001; 132 /** 133 * A Not-a-Number representation of a half-precision float. 134 */ 135 public static final @HalfFloat short NaN = (short) 0x7e00; 136 /** 137 * Negative infinity of type half-precision float. 138 */ 139 public static final @HalfFloat short NEGATIVE_INFINITY = (short) 0xfc00; 140 /** 141 * Negative 0 of type half-precision float. 142 */ 143 public static final @HalfFloat short NEGATIVE_ZERO = (short) 0x8000; 144 /** 145 * Positive infinity of type half-precision float. 146 */ 147 public static final @HalfFloat short POSITIVE_INFINITY = (short) 0x7c00; 148 /** 149 * Positive 0 of type half-precision float. 150 */ 151 public static final @HalfFloat short POSITIVE_ZERO = (short) 0x0000; 152 153 private final @HalfFloat short mValue; 154 155 /** 156 * Constructs a newly allocated {@code Half} object that represents the 157 * half-precision float type argument. 158 * 159 * @param value The value to be represented by the {@code Half} 160 */ Half(@alfFloat short value)161 public Half(@HalfFloat short value) { 162 mValue = value; 163 } 164 165 /** 166 * Constructs a newly allocated {@code Half} object that represents the 167 * argument converted to a half-precision float. 168 * 169 * @param value The value to be represented by the {@code Half} 170 * 171 * @see #toHalf(float) 172 */ Half(float value)173 public Half(float value) { 174 mValue = toHalf(value); 175 } 176 177 /** 178 * Constructs a newly allocated {@code Half} object that 179 * represents the argument converted to a half-precision float. 180 * 181 * @param value The value to be represented by the {@code Half} 182 * 183 * @see #toHalf(float) 184 */ Half(double value)185 public Half(double value) { 186 mValue = toHalf((float) value); 187 } 188 189 /** 190 * <p>Constructs a newly allocated {@code Half} object that represents the 191 * half-precision float value represented by the string. 192 * The string is converted to a half-precision float value as if by the 193 * {@link #valueOf(String)} method.</p> 194 * 195 * <p>Calling this constructor is equivalent to calling:</p> 196 * <pre> 197 * new Half(Float.parseFloat(value)) 198 * </pre> 199 * 200 * @param value A string to be converted to a {@code Half} 201 * @throws NumberFormatException if the string does not contain a parsable number 202 * 203 * @see Float#valueOf(java.lang.String) 204 * @see #toHalf(float) 205 */ Half(@onNull String value)206 public Half(@NonNull String value) throws NumberFormatException { 207 mValue = toHalf(Float.parseFloat(value)); 208 } 209 210 /** 211 * Returns the half-precision value of this {@code Half} as a {@code short} 212 * containing the bit representation described in {@link Half}. 213 * 214 * @return The half-precision float value represented by this object 215 */ halfValue()216 public @HalfFloat short halfValue() { 217 return mValue; 218 } 219 220 /** 221 * Returns the value of this {@code Half} as a {@code byte} after 222 * a narrowing primitive conversion. 223 * 224 * @return The half-precision float value represented by this object 225 * converted to type {@code byte} 226 */ 227 @Override byteValue()228 public byte byteValue() { 229 return (byte) toFloat(mValue); 230 } 231 232 /** 233 * Returns the value of this {@code Half} as a {@code short} after 234 * a narrowing primitive conversion. 235 * 236 * @return The half-precision float value represented by this object 237 * converted to type {@code short} 238 */ 239 @Override shortValue()240 public short shortValue() { 241 return (short) toFloat(mValue); 242 } 243 244 /** 245 * Returns the value of this {@code Half} as a {@code int} after 246 * a narrowing primitive conversion. 247 * 248 * @return The half-precision float value represented by this object 249 * converted to type {@code int} 250 */ 251 @Override intValue()252 public int intValue() { 253 return (int) toFloat(mValue); 254 } 255 256 /** 257 * Returns the value of this {@code Half} as a {@code long} after 258 * a narrowing primitive conversion. 259 * 260 * @return The half-precision float value represented by this object 261 * converted to type {@code long} 262 */ 263 @Override longValue()264 public long longValue() { 265 return (long) toFloat(mValue); 266 } 267 268 /** 269 * Returns the value of this {@code Half} as a {@code float} after 270 * a widening primitive conversion. 271 * 272 * @return The half-precision float value represented by this object 273 * converted to type {@code float} 274 */ 275 @Override floatValue()276 public float floatValue() { 277 return toFloat(mValue); 278 } 279 280 /** 281 * Returns the value of this {@code Half} as a {@code double} after 282 * a widening primitive conversion. 283 * 284 * @return The half-precision float value represented by this object 285 * converted to type {@code double} 286 */ 287 @Override doubleValue()288 public double doubleValue() { 289 return toFloat(mValue); 290 } 291 292 /** 293 * Returns true if this {@code Half} value represents a Not-a-Number, 294 * false otherwise. 295 * 296 * @return True if the value is a NaN, false otherwise 297 */ isNaN()298 public boolean isNaN() { 299 return isNaN(mValue); 300 } 301 302 /** 303 * Compares this object against the specified object. The result is {@code true} 304 * if and only if the argument is not {@code null} and is a {@code Half} object 305 * that represents the same half-precision value as the this object. Two 306 * half-precision values are considered to be the same if and only if the method 307 * {@link #halfToIntBits(short)} returns an identical {@code int} value for both. 308 * 309 * @param o The object to compare 310 * @return True if the objects are the same, false otherwise 311 * 312 * @see #halfToIntBits(short) 313 */ 314 @Override equals(@ullable Object o)315 public boolean equals(@Nullable Object o) { 316 return (o instanceof Half) && 317 (halfToIntBits(((Half) o).mValue) == halfToIntBits(mValue)); 318 } 319 320 /** 321 * Returns a hash code for this {@code Half} object. The result is the 322 * integer bit representation, exactly as produced by the method 323 * {@link #halfToIntBits(short)}, of the primitive half-precision float 324 * value represented by this {@code Half} object. 325 * 326 * @return A hash code value for this object 327 */ 328 @Override hashCode()329 public int hashCode() { 330 return hashCode(mValue); 331 } 332 333 /** 334 * Returns a string representation of the specified half-precision 335 * float value. See {@link #toString(short)} for more information. 336 * 337 * @return A string representation of this {@code Half} object 338 */ 339 @NonNull 340 @Override toString()341 public String toString() { 342 return toString(mValue); 343 } 344 345 /** 346 * <p>Compares the two specified half-precision float values. The following 347 * conditions apply during the comparison:</p> 348 * 349 * <ul> 350 * <li>{@link #NaN} is considered by this method to be equal to itself and greater 351 * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li> 352 * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than 353 * {@link #NEGATIVE_ZERO}.</li> 354 * </ul> 355 * 356 * @param h The half-precision float value to compare to the half-precision value 357 * represented by this {@code Half} object 358 * 359 * @return The value {@code 0} if {@code x} is numerically equal to {@code y}; a 360 * value less than {@code 0} if {@code x} is numerically less than {@code y}; 361 * and a value greater than {@code 0} if {@code x} is numerically greater 362 * than {@code y} 363 */ 364 @Override compareTo(@onNull Half h)365 public int compareTo(@NonNull Half h) { 366 return compare(mValue, h.mValue); 367 } 368 369 /** 370 * Returns a hash code for a half-precision float value. 371 * 372 * @param h The value to hash 373 * 374 * @return A hash code value for a half-precision float value 375 */ hashCode(@alfFloat short h)376 public static int hashCode(@HalfFloat short h) { 377 return halfToIntBits(h); 378 } 379 380 /** 381 * <p>Compares the two specified half-precision float values. The following 382 * conditions apply during the comparison:</p> 383 * 384 * <ul> 385 * <li>{@link #NaN} is considered by this method to be equal to itself and greater 386 * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li> 387 * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than 388 * {@link #NEGATIVE_ZERO}.</li> 389 * </ul> 390 * 391 * @param x The first half-precision float value to compare. 392 * @param y The second half-precision float value to compare 393 * 394 * @return The value {@code 0} if {@code x} is numerically equal to {@code y}, a 395 * value less than {@code 0} if {@code x} is numerically less than {@code y}, 396 * and a value greater than {@code 0} if {@code x} is numerically greater 397 * than {@code y} 398 */ compare(@alfFloat short x, @HalfFloat short y)399 public static int compare(@HalfFloat short x, @HalfFloat short y) { 400 return FP16.compare(x, y); 401 } 402 403 /** 404 * <p>Returns a representation of the specified half-precision float value 405 * according to the bit layout described in {@link Half}.</p> 406 * 407 * <p>Similar to {@link #halfToIntBits(short)}, this method collapses all 408 * possible Not-a-Number values to a single canonical Not-a-Number value 409 * defined by {@link #NaN}.</p> 410 * 411 * @param h A half-precision float value 412 * @return The bits that represent the half-precision float value 413 * 414 * @see #halfToIntBits(short) 415 */ halfToShortBits(@alfFloat short h)416 public static @HalfFloat short halfToShortBits(@HalfFloat short h) { 417 return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h; 418 } 419 420 /** 421 * <p>Returns a representation of the specified half-precision float value 422 * according to the bit layout described in {@link Half}.</p> 423 * 424 * <p>Unlike {@link #halfToRawIntBits(short)}, this method collapses all 425 * possible Not-a-Number values to a single canonical Not-a-Number value 426 * defined by {@link #NaN}.</p> 427 * 428 * @param h A half-precision float value 429 * @return The bits that represent the half-precision float value 430 * 431 * @see #halfToRawIntBits(short) 432 * @see #halfToShortBits(short) 433 * @see #intBitsToHalf(int) 434 */ halfToIntBits(@alfFloat short h)435 public static int halfToIntBits(@HalfFloat short h) { 436 return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h & 0xffff; 437 } 438 439 /** 440 * <p>Returns a representation of the specified half-precision float value 441 * according to the bit layout described in {@link Half}.</p> 442 * 443 * <p>The argument is considered to be a representation of a half-precision 444 * float value according to the bit layout described in {@link Half}. The 16 445 * most significant bits of the returned value are set to 0.</p> 446 * 447 * @param h A half-precision float value 448 * @return The bits that represent the half-precision float value 449 * 450 * @see #halfToIntBits(short) 451 * @see #intBitsToHalf(int) 452 */ halfToRawIntBits(@alfFloat short h)453 public static int halfToRawIntBits(@HalfFloat short h) { 454 return h & 0xffff; 455 } 456 457 /** 458 * <p>Returns the half-precision float value corresponding to a given 459 * bit representation.</p> 460 * 461 * <p>The argument is considered to be a representation of a half-precision 462 * float value according to the bit layout described in {@link Half}. The 16 463 * most significant bits of the argument are ignored.</p> 464 * 465 * @param bits An integer 466 * @return The half-precision float value with the same bit pattern 467 */ intBitsToHalf(int bits)468 public static @HalfFloat short intBitsToHalf(int bits) { 469 return (short) (bits & 0xffff); 470 } 471 472 /** 473 * Returns the first parameter with the sign of the second parameter. 474 * This method treats NaNs as having a sign. 475 * 476 * @param magnitude A half-precision float value providing the magnitude of the result 477 * @param sign A half-precision float value providing the sign of the result 478 * @return A value with the magnitude of the first parameter and the sign 479 * of the second parameter 480 */ copySign(@alfFloat short magnitude, @HalfFloat short sign)481 public static @HalfFloat short copySign(@HalfFloat short magnitude, @HalfFloat short sign) { 482 return (short) ((sign & FP16.SIGN_MASK) | (magnitude & FP16.EXPONENT_SIGNIFICAND_MASK)); 483 } 484 485 /** 486 * Returns the absolute value of the specified half-precision float. 487 * Special values are handled in the following ways: 488 * <ul> 489 * <li>If the specified half-precision float is NaN, the result is NaN</li> 490 * <li>If the specified half-precision float is zero (negative or positive), 491 * the result is positive zero (see {@link #POSITIVE_ZERO})</li> 492 * <li>If the specified half-precision float is infinity (negative or positive), 493 * the result is positive infinity (see {@link #POSITIVE_INFINITY})</li> 494 * </ul> 495 * 496 * @param h A half-precision float value 497 * @return The absolute value of the specified half-precision float 498 */ abs(@alfFloat short h)499 public static @HalfFloat short abs(@HalfFloat short h) { 500 return (short) (h & FP16.EXPONENT_SIGNIFICAND_MASK); 501 } 502 503 /** 504 * Returns the closest integral half-precision float value to the specified 505 * half-precision float value. Special values are handled in the 506 * following ways: 507 * <ul> 508 * <li>If the specified half-precision float is NaN, the result is NaN</li> 509 * <li>If the specified half-precision float is infinity (negative or positive), 510 * the result is infinity (with the same sign)</li> 511 * <li>If the specified half-precision float is zero (negative or positive), 512 * the result is zero (with the same sign)</li> 513 * </ul> 514 * 515 * <p class=note> 516 * <strong>Note:</strong> Unlike the identically named 517 * <code class=prettyprint>int java.lang.Math.round(float)</code> method, 518 * this returns a Half value stored in a short, <strong>not</strong> an 519 * actual short integer result. 520 * 521 * @param h A half-precision float value 522 * @return The value of the specified half-precision float rounded to the nearest 523 * half-precision float value 524 */ round(@alfFloat short h)525 public static @HalfFloat short round(@HalfFloat short h) { 526 return FP16.rint(h); 527 } 528 529 /** 530 * Returns the smallest half-precision float value toward negative infinity 531 * greater than or equal to the specified half-precision float value. 532 * Special values are handled in the following ways: 533 * <ul> 534 * <li>If the specified half-precision float is NaN, the result is NaN</li> 535 * <li>If the specified half-precision float is infinity (negative or positive), 536 * the result is infinity (with the same sign)</li> 537 * <li>If the specified half-precision float is zero (negative or positive), 538 * the result is zero (with the same sign)</li> 539 * </ul> 540 * 541 * @param h A half-precision float value 542 * @return The smallest half-precision float value toward negative infinity 543 * greater than or equal to the specified half-precision float value 544 */ ceil(@alfFloat short h)545 public static @HalfFloat short ceil(@HalfFloat short h) { 546 return FP16.ceil(h); 547 } 548 549 /** 550 * Returns the largest half-precision float value toward positive infinity 551 * less than or equal to the specified half-precision float value. 552 * Special values are handled in the following ways: 553 * <ul> 554 * <li>If the specified half-precision float is NaN, the result is NaN</li> 555 * <li>If the specified half-precision float is infinity (negative or positive), 556 * the result is infinity (with the same sign)</li> 557 * <li>If the specified half-precision float is zero (negative or positive), 558 * the result is zero (with the same sign)</li> 559 * </ul> 560 * 561 * @param h A half-precision float value 562 * @return The largest half-precision float value toward positive infinity 563 * less than or equal to the specified half-precision float value 564 */ floor(@alfFloat short h)565 public static @HalfFloat short floor(@HalfFloat short h) { 566 return FP16.floor(h); 567 } 568 569 /** 570 * Returns the truncated half-precision float value of the specified 571 * half-precision float value. Special values are handled in the following ways: 572 * <ul> 573 * <li>If the specified half-precision float is NaN, the result is NaN</li> 574 * <li>If the specified half-precision float is infinity (negative or positive), 575 * the result is infinity (with the same sign)</li> 576 * <li>If the specified half-precision float is zero (negative or positive), 577 * the result is zero (with the same sign)</li> 578 * </ul> 579 * 580 * @param h A half-precision float value 581 * @return The truncated half-precision float value of the specified 582 * half-precision float value 583 */ trunc(@alfFloat short h)584 public static @HalfFloat short trunc(@HalfFloat short h) { 585 return FP16.trunc(h); 586 } 587 588 /** 589 * Returns the smaller of two half-precision float values (the value closest 590 * to negative infinity). Special values are handled in the following ways: 591 * <ul> 592 * <li>If either value is NaN, the result is NaN</li> 593 * <li>{@link #NEGATIVE_ZERO} is smaller than {@link #POSITIVE_ZERO}</li> 594 * </ul> 595 * 596 * @param x The first half-precision value 597 * @param y The second half-precision value 598 * @return The smaller of the two specified half-precision values 599 */ min(@alfFloat short x, @HalfFloat short y)600 public static @HalfFloat short min(@HalfFloat short x, @HalfFloat short y) { 601 return FP16.min(x, y); 602 } 603 604 /** 605 * Returns the larger of two half-precision float values (the value closest 606 * to positive infinity). Special values are handled in the following ways: 607 * <ul> 608 * <li>If either value is NaN, the result is NaN</li> 609 * <li>{@link #POSITIVE_ZERO} is greater than {@link #NEGATIVE_ZERO}</li> 610 * </ul> 611 * 612 * @param x The first half-precision value 613 * @param y The second half-precision value 614 * 615 * @return The larger of the two specified half-precision values 616 */ max(@alfFloat short x, @HalfFloat short y)617 public static @HalfFloat short max(@HalfFloat short x, @HalfFloat short y) { 618 return FP16.max(x, y); 619 } 620 621 /** 622 * Returns true if the first half-precision float value is less (smaller 623 * toward negative infinity) than the second half-precision float value. 624 * If either of the values is NaN, the result is false. 625 * 626 * @param x The first half-precision value 627 * @param y The second half-precision value 628 * 629 * @return True if x is less than y, false otherwise 630 */ less(@alfFloat short x, @HalfFloat short y)631 public static boolean less(@HalfFloat short x, @HalfFloat short y) { 632 return FP16.less(x, y); 633 } 634 635 /** 636 * Returns true if the first half-precision float value is less (smaller 637 * toward negative infinity) than or equal to the second half-precision 638 * float value. If either of the values is NaN, the result is false. 639 * 640 * @param x The first half-precision value 641 * @param y The second half-precision value 642 * 643 * @return True if x is less than or equal to y, false otherwise 644 */ lessEquals(@alfFloat short x, @HalfFloat short y)645 public static boolean lessEquals(@HalfFloat short x, @HalfFloat short y) { 646 return FP16.lessEquals(x, y); 647 } 648 649 /** 650 * Returns true if the first half-precision float value is greater (larger 651 * toward positive infinity) than the second half-precision float value. 652 * If either of the values is NaN, the result is false. 653 * 654 * @param x The first half-precision value 655 * @param y The second half-precision value 656 * 657 * @return True if x is greater than y, false otherwise 658 */ greater(@alfFloat short x, @HalfFloat short y)659 public static boolean greater(@HalfFloat short x, @HalfFloat short y) { 660 return FP16.greater(x, y); 661 } 662 663 /** 664 * Returns true if the first half-precision float value is greater (larger 665 * toward positive infinity) than or equal to the second half-precision float 666 * value. If either of the values is NaN, the result is false. 667 * 668 * @param x The first half-precision value 669 * @param y The second half-precision value 670 * 671 * @return True if x is greater than y, false otherwise 672 */ greaterEquals(@alfFloat short x, @HalfFloat short y)673 public static boolean greaterEquals(@HalfFloat short x, @HalfFloat short y) { 674 return FP16.greaterEquals(x, y); 675 } 676 677 /** 678 * Returns true if the two half-precision float values are equal. 679 * If either of the values is NaN, the result is false. {@link #POSITIVE_ZERO} 680 * and {@link #NEGATIVE_ZERO} are considered equal. 681 * 682 * @param x The first half-precision value 683 * @param y The second half-precision value 684 * 685 * @return True if x is equal to y, false otherwise 686 */ equals(@alfFloat short x, @HalfFloat short y)687 public static boolean equals(@HalfFloat short x, @HalfFloat short y) { 688 return FP16.equals(x, y); 689 } 690 691 /** 692 * Returns the sign of the specified half-precision float. 693 * 694 * @param h A half-precision float value 695 * @return 1 if the value is positive, -1 if the value is negative 696 */ getSign(@alfFloat short h)697 public static int getSign(@HalfFloat short h) { 698 return (h & FP16.SIGN_MASK) == 0 ? 1 : -1; 699 } 700 701 /** 702 * Returns the unbiased exponent used in the representation of 703 * the specified half-precision float value. if the value is NaN 704 * or infinite, this* method returns {@link #MAX_EXPONENT} + 1. 705 * If the argument is 0 or a subnormal representation, this method 706 * returns {@link #MIN_EXPONENT} - 1. 707 * 708 * @param h A half-precision float value 709 * @return The unbiased exponent of the specified value 710 */ getExponent(@alfFloat short h)711 public static int getExponent(@HalfFloat short h) { 712 return ((h >>> FP16.EXPONENT_SHIFT) & FP16.SHIFTED_EXPONENT_MASK) - FP16.EXPONENT_BIAS; 713 } 714 715 /** 716 * Returns the significand, or mantissa, used in the representation 717 * of the specified half-precision float value. 718 * 719 * @param h A half-precision float value 720 * @return The significand, or significand, of the specified vlaue 721 */ getSignificand(@alfFloat short h)722 public static int getSignificand(@HalfFloat short h) { 723 return h & FP16.SIGNIFICAND_MASK; 724 } 725 726 /** 727 * Returns true if the specified half-precision float value represents 728 * infinity, false otherwise. 729 * 730 * @param h A half-precision float value 731 * @return True if the value is positive infinity or negative infinity, 732 * false otherwise 733 */ isInfinite(@alfFloat short h)734 public static boolean isInfinite(@HalfFloat short h) { 735 return FP16.isInfinite(h); 736 } 737 738 /** 739 * Returns true if the specified half-precision float value represents 740 * a Not-a-Number, false otherwise. 741 * 742 * @param h A half-precision float value 743 * @return True if the value is a NaN, false otherwise 744 */ isNaN(@alfFloat short h)745 public static boolean isNaN(@HalfFloat short h) { 746 return FP16.isNaN(h); 747 } 748 749 /** 750 * Returns true if the specified half-precision float value is normalized 751 * (does not have a subnormal representation). If the specified value is 752 * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, 753 * {@link #POSITIVE_ZERO}, {@link #NEGATIVE_ZERO}, NaN or any subnormal 754 * number, this method returns false. 755 * 756 * @param h A half-precision float value 757 * @return True if the value is normalized, false otherwise 758 */ isNormalized(@alfFloat short h)759 public static boolean isNormalized(@HalfFloat short h) { 760 return FP16.isNormalized(h); 761 } 762 763 /** 764 * <p>Converts the specified half-precision float value into a 765 * single-precision float value. The following special cases are handled:</p> 766 * <ul> 767 * <li>If the input is {@link #NaN}, the returned value is {@link Float#NaN}</li> 768 * <li>If the input is {@link #POSITIVE_INFINITY} or 769 * {@link #NEGATIVE_INFINITY}, the returned value is respectively 770 * {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY}</li> 771 * <li>If the input is 0 (positive or negative), the returned value is +/-0.0f</li> 772 * <li>Otherwise, the returned value is a normalized single-precision float value</li> 773 * </ul> 774 * 775 * @param h The half-precision float value to convert to single-precision 776 * @return A normalized single-precision float value 777 */ toFloat(@alfFloat short h)778 public static float toFloat(@HalfFloat short h) { 779 return FP16.toFloat(h); 780 } 781 782 /** 783 * <p>Converts the specified single-precision float value into a 784 * half-precision float value. The following special cases are handled:</p> 785 * <ul> 786 * <li>If the input is NaN (see {@link Float#isNaN(float)}), the returned 787 * value is {@link #NaN}</li> 788 * <li>If the input is {@link Float#POSITIVE_INFINITY} or 789 * {@link Float#NEGATIVE_INFINITY}, the returned value is respectively 790 * {@link #POSITIVE_INFINITY} or {@link #NEGATIVE_INFINITY}</li> 791 * <li>If the input is 0 (positive or negative), the returned value is 792 * {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li> 793 * <li>If the input is a less than {@link #MIN_VALUE}, the returned value 794 * is flushed to {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li> 795 * <li>If the input is a less than {@link #MIN_NORMAL}, the returned value 796 * is a denorm half-precision float</li> 797 * <li>Otherwise, the returned value is rounded to the nearest 798 * representable half-precision float value</li> 799 * </ul> 800 * 801 * @param f The single-precision float value to convert to half-precision 802 * @return A half-precision float value 803 */ 804 @SuppressWarnings("StatementWithEmptyBody") toHalf(float f)805 public static @HalfFloat short toHalf(float f) { 806 return FP16.toHalf(f); 807 } 808 809 /** 810 * Returns a {@code Half} instance representing the specified 811 * half-precision float value. 812 * 813 * @param h A half-precision float value 814 * @return a {@code Half} instance representing {@code h} 815 */ valueOf(@alfFloat short h)816 public static @NonNull Half valueOf(@HalfFloat short h) { 817 return new Half(h); 818 } 819 820 /** 821 * Returns a {@code Half} instance representing the specified float value. 822 * 823 * @param f A float value 824 * @return a {@code Half} instance representing {@code f} 825 */ valueOf(float f)826 public static @NonNull Half valueOf(float f) { 827 return new Half(f); 828 } 829 830 /** 831 * Returns a {@code Half} instance representing the specified string value. 832 * Calling this method is equivalent to calling 833 * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)} 834 * for more information on the format of the string representation. 835 * 836 * @param s The string to be parsed 837 * @return a {@code Half} instance representing {@code h} 838 * @throws NumberFormatException if the string does not contain a parsable 839 * half-precision float value 840 */ valueOf(@onNull String s)841 public static @NonNull Half valueOf(@NonNull String s) { 842 return new Half(s); 843 } 844 845 /** 846 * Returns the half-precision float value represented by the specified string. 847 * Calling this method is equivalent to calling 848 * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)} 849 * for more information on the format of the string representation. 850 * 851 * @param s The string to be parsed 852 * @return A half-precision float value represented by the string 853 * @throws NumberFormatException if the string does not contain a parsable 854 * half-precision float value 855 */ parseHalf(@onNull String s)856 public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException { 857 return toHalf(Float.parseFloat(s)); 858 } 859 860 /** 861 * Returns a string representation of the specified half-precision 862 * float value. Calling this method is equivalent to calling 863 * <code>Float.toString(toFloat(h))</code>. See {@link Float#toString(float)} 864 * for more information on the format of the string representation. 865 * 866 * @param h A half-precision float value 867 * @return A string representation of the specified value 868 */ 869 @NonNull toString(@alfFloat short h)870 public static String toString(@HalfFloat short h) { 871 return Float.toString(toFloat(h)); 872 } 873 874 /** 875 * <p>Returns a hexadecimal string representation of the specified half-precision 876 * float value. If the value is a NaN, the result is <code>"NaN"</code>, 877 * otherwise the result follows this format:</p> 878 * <ul> 879 * <li>If the sign is positive, no sign character appears in the result</li> 880 * <li>If the sign is negative, the first character is <code>'-'</code></li> 881 * <li>If the value is inifinity, the string is <code>"Infinity"</code></li> 882 * <li>If the value is 0, the string is <code>"0x0.0p0"</code></li> 883 * <li>If the value has a normalized representation, the exponent and 884 * significand are represented in the string in two fields. The significand 885 * starts with <code>"0x1."</code> followed by its lowercase hexadecimal 886 * representation. Trailing zeroes are removed unless all digits are 0, then 887 * a single zero is used. The significand representation is followed by the 888 * exponent, represented by <code>"p"</code>, itself followed by a decimal 889 * string of the unbiased exponent</li> 890 * <li>If the value has a subnormal representation, the significand starts 891 * with <code>"0x0."</code> followed by its lowercase hexadecimal 892 * representation. Trailing zeroes are removed unless all digits are 0, then 893 * a single zero is used. The significand representation is followed by the 894 * exponent, represented by <code>"p-14"</code></li> 895 * </ul> 896 * 897 * @param h A half-precision float value 898 * @return A hexadecimal string representation of the specified value 899 */ 900 @NonNull toHexString(@alfFloat short h)901 public static String toHexString(@HalfFloat short h) { 902 return FP16.toHexString(h); 903 } 904 } 905