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