blob: fe536a6e4e68b18a6ef34765d3a94dc13eb10528 [file] [log] [blame]
Romain Guyde0a3a82016-10-20 12:37:21 -07001/*
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
17package android.util;
18
Romain Guy5d7e2352016-11-14 09:20:39 -080019import android.annotation.HalfFloat;
Romain Guy95b52fd2017-02-24 18:44:12 -080020import android.annotation.NonNull;
21import android.annotation.Nullable;
22
xueliang.zhonge008d962019-01-22 18:01:45 +000023import libcore.util.FP16;
24
Romain Guyde0a3a82016-10-20 12:37:21 -070025/**
Romain Guy95b52fd2017-02-24 18:44:12 -080026 * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
Romain Guyde0a3a82016-10-20 12:37:21 -070027 * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
Romain Guy5d7e2352016-11-14 09:20:39 -080028 * 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>
Romain Guyde0a3a82016-10-20 12:37:21 -070032 *
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>
Romain Guy12ae9a02016-11-04 18:29:58 -070037 * <li>Significand: 10 bits</li>
Romain Guyde0a3a82016-10-20 12:37:21 -070038 * </ul>
39 *
Romain Guy12ae9a02016-11-04 18:29:58 -070040 * <p>The format is laid out as follows:</p>
Romain Guyde0a3a82016-10-20 12:37:21 -070041 * <pre>
42 * 1 11111 1111111111
43 * ^ --^-- -----^----
Romain Guy12ae9a02016-11-04 18:29:58 -070044 * sign | |_______ significand
Romain Guyde0a3a82016-10-20 12:37:21 -070045 * |
46 * -- exponent
47 * </pre>
48 *
Romain Guy12ae9a02016-11-04 18:29:58 -070049 * <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>
Romain Guyde0a3a82016-10-20 12:37:21 -070093 */
Romain Guy12ae9a02016-11-04 18:29:58 -070094@SuppressWarnings("SimplifiableIfStatement")
Romain Guy95b52fd2017-02-24 18:44:12 -080095public final class Half extends Number implements Comparable<Half> {
Romain Guyde0a3a82016-10-20 12:37:21 -070096 /**
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800105 public static final @HalfFloat short EPSILON = (short) 0x1400;
106
Romain Guyde0a3a82016-10-20 12:37:21 -0700107 /**
108 * Maximum exponent a finite half-precision float may have.
109 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800110 public static final int MAX_EXPONENT = 15;
Romain Guyde0a3a82016-10-20 12:37:21 -0700111 /**
112 * Minimum exponent a normalized half-precision float may have.
113 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800114 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;
Romain Guyde0a3a82016-10-20 12:37:21 -0700124 /**
125 * Smallest positive normal value a half-precision float may have.
126 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800127 public static final @HalfFloat short MIN_NORMAL = (short) 0x0400;
Romain Guyde0a3a82016-10-20 12:37:21 -0700128 /**
129 * Smallest positive non-zero value a half-precision float may have.
130 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800131 public static final @HalfFloat short MIN_VALUE = (short) 0x0001;
Romain Guyde0a3a82016-10-20 12:37:21 -0700132 /**
133 * A Not-a-Number representation of a half-precision float.
134 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800135 public static final @HalfFloat short NaN = (short) 0x7e00;
Romain Guyde0a3a82016-10-20 12:37:21 -0700136 /**
137 * Negative infinity of type half-precision float.
138 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800139 public static final @HalfFloat short NEGATIVE_INFINITY = (short) 0xfc00;
Romain Guyde0a3a82016-10-20 12:37:21 -0700140 /**
141 * Negative 0 of type half-precision float.
142 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800143 public static final @HalfFloat short NEGATIVE_ZERO = (short) 0x8000;
Romain Guyde0a3a82016-10-20 12:37:21 -0700144 /**
145 * Positive infinity of type half-precision float.
146 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800147 public static final @HalfFloat short POSITIVE_INFINITY = (short) 0x7c00;
Romain Guyde0a3a82016-10-20 12:37:21 -0700148 /**
149 * Positive 0 of type half-precision float.
150 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800151 public static final @HalfFloat short POSITIVE_ZERO = (short) 0x0000;
Romain Guyde0a3a82016-10-20 12:37:21 -0700152
Romain Guy95b52fd2017-02-24 18:44:12 -0800153 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 */
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 */
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 */
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 */
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 */
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
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
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
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
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
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
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 */
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
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
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
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
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 */
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 */
399 public static int compare(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000400 return FP16.compare(x, y);
Romain Guy95b52fd2017-02-24 18:44:12 -0800401 }
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 */
416 public static @HalfFloat short halfToShortBits(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000417 return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h;
Romain Guy95b52fd2017-02-24 18:44:12 -0800418 }
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 */
435 public static int halfToIntBits(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000436 return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h & 0xffff;
Romain Guy95b52fd2017-02-24 18:44:12 -0800437 }
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 */
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 */
468 public static @HalfFloat short intBitsToHalf(int bits) {
469 return (short) (bits & 0xffff);
Romain Guyde0a3a82016-10-20 12:37:21 -0700470 }
471
472 /**
Romain Guy12ae9a02016-11-04 18:29:58 -0700473 * 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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800481 public static @HalfFloat short copySign(@HalfFloat short magnitude, @HalfFloat short sign) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000482 return (short) ((sign & FP16.SIGN_MASK) | (magnitude & FP16.EXPONENT_SIGNIFICAND_MASK));
Romain Guy12ae9a02016-11-04 18:29:58 -0700483 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800499 public static @HalfFloat short abs(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000500 return (short) (h & FP16.EXPONENT_SIGNIFICAND_MASK);
Romain Guy12ae9a02016-11-04 18:29:58 -0700501 }
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 *
xueliang.zhonge008d962019-01-22 18:01:45 +0000515 * <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 *
Romain Guy12ae9a02016-11-04 18:29:58 -0700521 * @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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800525 public static @HalfFloat short round(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000526 return FP16.rint(h);
Romain Guy12ae9a02016-11-04 18:29:58 -0700527 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800545 public static @HalfFloat short ceil(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000546 return FP16.ceil(h);
Romain Guy12ae9a02016-11-04 18:29:58 -0700547 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800565 public static @HalfFloat short floor(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000566 return FP16.floor(h);
Romain Guy12ae9a02016-11-04 18:29:58 -0700567 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800584 public static @HalfFloat short trunc(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000585 return FP16.trunc(h);
Romain Guy12ae9a02016-11-04 18:29:58 -0700586 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800600 public static @HalfFloat short min(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000601 return FP16.min(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700602 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800617 public static @HalfFloat short max(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000618 return FP16.max(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700619 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800631 public static boolean less(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000632 return FP16.less(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700633 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800645 public static boolean lessEquals(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000646 return FP16.lessEquals(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700647 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800659 public static boolean greater(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000660 return FP16.greater(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700661 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800673 public static boolean greaterEquals(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000674 return FP16.greaterEquals(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700675 }
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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800687 public static boolean equals(@HalfFloat short x, @HalfFloat short y) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000688 return FP16.equals(x, y);
Romain Guy12ae9a02016-11-04 18:29:58 -0700689 }
690
691 /**
Romain Guyde0a3a82016-10-20 12:37:21 -0700692 * 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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800697 public static int getSign(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000698 return (h & FP16.SIGN_MASK) == 0 ? 1 : -1;
Romain Guyde0a3a82016-10-20 12:37:21 -0700699 }
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.
Romain Guy12ae9a02016-11-04 18:29:58 -0700705 * If the argument is 0 or a subnormal representation, this method
706 * returns {@link #MIN_EXPONENT} - 1.
Romain Guyde0a3a82016-10-20 12:37:21 -0700707 *
708 * @param h A half-precision float value
709 * @return The unbiased exponent of the specified value
710 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800711 public static int getExponent(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000712 return ((h >>> FP16.EXPONENT_SHIFT) & FP16.SHIFTED_EXPONENT_MASK) - FP16.EXPONENT_BIAS;
Romain Guyde0a3a82016-10-20 12:37:21 -0700713 }
714
715 /**
Romain Guy12ae9a02016-11-04 18:29:58 -0700716 * Returns the significand, or mantissa, used in the representation
Romain Guyde0a3a82016-10-20 12:37:21 -0700717 * of the specified half-precision float value.
718 *
719 * @param h A half-precision float value
Romain Guy12ae9a02016-11-04 18:29:58 -0700720 * @return The significand, or significand, of the specified vlaue
Romain Guyde0a3a82016-10-20 12:37:21 -0700721 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800722 public static int getSignificand(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000723 return h & FP16.SIGNIFICAND_MASK;
Romain Guyde0a3a82016-10-20 12:37:21 -0700724 }
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
Romain Guy95b52fd2017-02-24 18:44:12 -0800731 * @return True if the value is positive infinity or negative infinity,
Romain Guyde0a3a82016-10-20 12:37:21 -0700732 * false otherwise
733 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800734 public static boolean isInfinite(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000735 return FP16.isInfinite(h);
Romain Guyde0a3a82016-10-20 12:37:21 -0700736 }
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
Romain Guy95b52fd2017-02-24 18:44:12 -0800743 * @return True if the value is a NaN, false otherwise
Romain Guyde0a3a82016-10-20 12:37:21 -0700744 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800745 public static boolean isNaN(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000746 return FP16.isNaN(h);
Romain Guy12ae9a02016-11-04 18:29:58 -0700747 }
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
Romain Guy95b52fd2017-02-24 18:44:12 -0800757 * @return True if the value is normalized, false otherwise
Romain Guy12ae9a02016-11-04 18:29:58 -0700758 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800759 public static boolean isNormalized(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000760 return FP16.isNormalized(h);
Romain Guyde0a3a82016-10-20 12:37:21 -0700761 }
762
763 /**
764 * <p>Converts the specified half-precision float value into a
Romain Guy68bd5fd2016-11-14 18:53:40 -0800765 * single-precision float value. The following special cases are handled:</p>
Romain Guyde0a3a82016-10-20 12:37:21 -0700766 * <ul>
Romain Guy68bd5fd2016-11-14 18:53:40 -0800767 * <li>If the input is {@link #NaN}, the returned value is {@link Float#NaN}</li>
Romain Guyde0a3a82016-10-20 12:37:21 -0700768 * <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 */
Romain Guy5d7e2352016-11-14 09:20:39 -0800778 public static float toFloat(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000779 return FP16.toFloat(h);
Romain Guyde0a3a82016-10-20 12:37:21 -0700780 }
781
782 /**
783 * <p>Converts the specified single-precision float value into a
Romain Guy68bd5fd2016-11-14 18:53:40 -0800784 * half-precision float value. The following special cases are handled:</p>
Romain Guyde0a3a82016-10-20 12:37:21 -0700785 * <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")
Romain Guy95b52fd2017-02-24 18:44:12 -0800805 public static @HalfFloat short toHalf(float f) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000806 return FP16.toHalf(f);
Romain Guyde0a3a82016-10-20 12:37:21 -0700807 }
808
809 /**
Romain Guy95b52fd2017-02-24 18:44:12 -0800810 * 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 */
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 */
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 */
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 */
856 public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
Neil Fullerf9d88df2018-07-02 12:04:39 +0100857 return toHalf(Float.parseFloat(s));
Romain Guy95b52fd2017-02-24 18:44:12 -0800858 }
859
860 /**
Romain Guyde0a3a82016-10-20 12:37:21 -0700861 * 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 */
Romain Guy95b52fd2017-02-24 18:44:12 -0800869 @NonNull
Romain Guy5d7e2352016-11-14 09:20:39 -0800870 public static String toString(@HalfFloat short h) {
Romain Guyde0a3a82016-10-20 12:37:21 -0700871 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
Romain Guy12ae9a02016-11-04 18:29:58 -0700884 * significand are represented in the string in two fields. The significand
885 * starts with <code>"0x1."</code> followed by its lowercase hexadecimal
Romain Guyde0a3a82016-10-20 12:37:21 -0700886 * representation. Trailing zeroes are removed unless all digits are 0, then
Romain Guy12ae9a02016-11-04 18:29:58 -0700887 * a single zero is used. The significand representation is followed by the
Romain Guyde0a3a82016-10-20 12:37:21 -0700888 * exponent, represented by <code>"p"</code>, itself followed by a decimal
889 * string of the unbiased exponent</li>
Romain Guy12ae9a02016-11-04 18:29:58 -0700890 * <li>If the value has a subnormal representation, the significand starts
Romain Guyde0a3a82016-10-20 12:37:21 -0700891 * with <code>"0x0."</code> followed by its lowercase hexadecimal
892 * representation. Trailing zeroes are removed unless all digits are 0, then
Romain Guy12ae9a02016-11-04 18:29:58 -0700893 * a single zero is used. The significand representation is followed by the
Romain Guyde0a3a82016-10-20 12:37:21 -0700894 * 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 */
Romain Guy95b52fd2017-02-24 18:44:12 -0800900 @NonNull
Romain Guy5d7e2352016-11-14 09:20:39 -0800901 public static String toHexString(@HalfFloat short h) {
xueliang.zhonge008d962019-01-22 18:01:45 +0000902 return FP16.toHexString(h);
Romain Guyde0a3a82016-10-20 12:37:21 -0700903 }
904}