• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &frasl; 16,777,216</td></tr>
61  *     <tr><td>1 &frasl; 16,384</td><td>1 &frasl; 16,777,216</td></tr>
62  *     <tr><td>1 &frasl; 8,192</td><td>1 &frasl; 8,388,608</td></tr>
63  *     <tr><td>1 &frasl; 4,096</td><td>1 &frasl; 4,194,304</td></tr>
64  *     <tr><td>1 &frasl; 2,048</td><td>1 &frasl; 2,097,152</td></tr>
65  *     <tr><td>1 &frasl; 1,024</td><td>1 &frasl; 1,048,576</td></tr>
66  *     <tr><td>1 &frasl; 512</td><td>1 &frasl; 524,288</td></tr>
67  *     <tr><td>1 &frasl; 256</td><td>1 &frasl; 262,144</td></tr>
68  *     <tr><td>1 &frasl; 128</td><td>1 &frasl; 131,072</td></tr>
69  *     <tr><td>1 &frasl; 64</td><td>1 &frasl; 65,536</td></tr>
70  *     <tr><td>1 &frasl; 32</td><td>1 &frasl; 32,768</td></tr>
71  *     <tr><td>1 &frasl; 16</td><td>1 &frasl; 16,384</td></tr>
72  *     <tr><td>1 &frasl; 8</td><td>1 &frasl; 8,192</td></tr>
73  *     <tr><td>1 &frasl; 4</td><td>1 &frasl; 4,096</td></tr>
74  *     <tr><td>1 &frasl; 2</td><td>1 &frasl; 2,048</td></tr>
75  *     <tr><td>1</td><td>1 &frasl; 1,024</td></tr>
76  *     <tr><td>2</td><td>1 &frasl; 512</td></tr>
77  *     <tr><td>4</td><td>1 &frasl; 256</td></tr>
78  *     <tr><td>8</td><td>1 &frasl; 128</td></tr>
79  *     <tr><td>16</td><td>1 &frasl; 64</td></tr>
80  *     <tr><td>32</td><td>1 &frasl; 32</td></tr>
81  *     <tr><td>64</td><td>1 &frasl; 16</td></tr>
82  *     <tr><td>128</td><td>1 &frasl; 8</td></tr>
83  *     <tr><td>256</td><td>1 &frasl; 4</td></tr>
84  *     <tr><td>512</td><td>1 &frasl; 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