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