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