905 lines
34 KiB
Java
905 lines
34 KiB
Java
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.util;
|
|
|
|
import android.annotation.HalfFloat;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
|
|
import libcore.util.FP16;
|
|
|
|
/**
|
|
* <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
|
|
* <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
|
|
* floating point data types (also called fp16 or binary16). A half-precision float can be
|
|
* created from or converted to single-precision floats, and is stored in a short data type.
|
|
* To distinguish short values holding half-precision floats from regular short values,
|
|
* it is recommended to use the <code>@HalfFloat</code> annotation.</p>
|
|
*
|
|
* <p>The IEEE 754 standard specifies an fp16 as having the following format:</p>
|
|
* <ul>
|
|
* <li>Sign bit: 1 bit</li>
|
|
* <li>Exponent width: 5 bits</li>
|
|
* <li>Significand: 10 bits</li>
|
|
* </ul>
|
|
*
|
|
* <p>The format is laid out as follows:</p>
|
|
* <pre>
|
|
* 1 11111 1111111111
|
|
* ^ --^-- -----^----
|
|
* sign | |_______ significand
|
|
* |
|
|
* -- exponent
|
|
* </pre>
|
|
*
|
|
* <p>Half-precision floating points can be useful to save memory and/or
|
|
* bandwidth at the expense of range and precision when compared to single-precision
|
|
* floating points (fp32).</p>
|
|
* <p>To help you decide whether fp16 is the right storage type for you need, please
|
|
* refer to the table below that shows the available precision throughout the range of
|
|
* possible values. The <em>precision</em> column indicates the step size between two
|
|
* consecutive numbers in a specific part of the range.</p>
|
|
*
|
|
* <table summary="Precision of fp16 across the range">
|
|
* <tr><th>Range start</th><th>Precision</th></tr>
|
|
* <tr><td>0</td><td>1 ⁄ 16,777,216</td></tr>
|
|
* <tr><td>1 ⁄ 16,384</td><td>1 ⁄ 16,777,216</td></tr>
|
|
* <tr><td>1 ⁄ 8,192</td><td>1 ⁄ 8,388,608</td></tr>
|
|
* <tr><td>1 ⁄ 4,096</td><td>1 ⁄ 4,194,304</td></tr>
|
|
* <tr><td>1 ⁄ 2,048</td><td>1 ⁄ 2,097,152</td></tr>
|
|
* <tr><td>1 ⁄ 1,024</td><td>1 ⁄ 1,048,576</td></tr>
|
|
* <tr><td>1 ⁄ 512</td><td>1 ⁄ 524,288</td></tr>
|
|
* <tr><td>1 ⁄ 256</td><td>1 ⁄ 262,144</td></tr>
|
|
* <tr><td>1 ⁄ 128</td><td>1 ⁄ 131,072</td></tr>
|
|
* <tr><td>1 ⁄ 64</td><td>1 ⁄ 65,536</td></tr>
|
|
* <tr><td>1 ⁄ 32</td><td>1 ⁄ 32,768</td></tr>
|
|
* <tr><td>1 ⁄ 16</td><td>1 ⁄ 16,384</td></tr>
|
|
* <tr><td>1 ⁄ 8</td><td>1 ⁄ 8,192</td></tr>
|
|
* <tr><td>1 ⁄ 4</td><td>1 ⁄ 4,096</td></tr>
|
|
* <tr><td>1 ⁄ 2</td><td>1 ⁄ 2,048</td></tr>
|
|
* <tr><td>1</td><td>1 ⁄ 1,024</td></tr>
|
|
* <tr><td>2</td><td>1 ⁄ 512</td></tr>
|
|
* <tr><td>4</td><td>1 ⁄ 256</td></tr>
|
|
* <tr><td>8</td><td>1 ⁄ 128</td></tr>
|
|
* <tr><td>16</td><td>1 ⁄ 64</td></tr>
|
|
* <tr><td>32</td><td>1 ⁄ 32</td></tr>
|
|
* <tr><td>64</td><td>1 ⁄ 16</td></tr>
|
|
* <tr><td>128</td><td>1 ⁄ 8</td></tr>
|
|
* <tr><td>256</td><td>1 ⁄ 4</td></tr>
|
|
* <tr><td>512</td><td>1 ⁄ 2</td></tr>
|
|
* <tr><td>1,024</td><td>1</td></tr>
|
|
* <tr><td>2,048</td><td>2</td></tr>
|
|
* <tr><td>4,096</td><td>4</td></tr>
|
|
* <tr><td>8,192</td><td>8</td></tr>
|
|
* <tr><td>16,384</td><td>16</td></tr>
|
|
* <tr><td>32,768</td><td>32</td></tr>
|
|
* </table>
|
|
*
|
|
* <p>This table shows that numbers higher than 1024 lose all fractional precision.</p>
|
|
*/
|
|
@SuppressWarnings("SimplifiableIfStatement")
|
|
public final class Half extends Number implements Comparable<Half> {
|
|
/**
|
|
* The number of bits used to represent a half-precision float value.
|
|
*/
|
|
public static final int SIZE = 16;
|
|
|
|
/**
|
|
* Epsilon is the difference between 1.0 and the next value representable
|
|
* by a half-precision floating-point.
|
|
*/
|
|
public static final @HalfFloat short EPSILON = (short) 0x1400;
|
|
|
|
/**
|
|
* Maximum exponent a finite half-precision float may have.
|
|
*/
|
|
public static final int MAX_EXPONENT = 15;
|
|
/**
|
|
* Minimum exponent a normalized half-precision float may have.
|
|
*/
|
|
public static final int MIN_EXPONENT = -14;
|
|
|
|
/**
|
|
* Smallest negative value a half-precision float may have.
|
|
*/
|
|
public static final @HalfFloat short LOWEST_VALUE = (short) 0xfbff;
|
|
/**
|
|
* Maximum positive finite value a half-precision float may have.
|
|
*/
|
|
public static final @HalfFloat short MAX_VALUE = (short) 0x7bff;
|
|
/**
|
|
* Smallest positive normal value a half-precision float may have.
|
|
*/
|
|
public static final @HalfFloat short MIN_NORMAL = (short) 0x0400;
|
|
/**
|
|
* Smallest positive non-zero value a half-precision float may have.
|
|
*/
|
|
public static final @HalfFloat short MIN_VALUE = (short) 0x0001;
|
|
/**
|
|
* A Not-a-Number representation of a half-precision float.
|
|
*/
|
|
public static final @HalfFloat short NaN = (short) 0x7e00;
|
|
/**
|
|
* Negative infinity of type half-precision float.
|
|
*/
|
|
public static final @HalfFloat short NEGATIVE_INFINITY = (short) 0xfc00;
|
|
/**
|
|
* Negative 0 of type half-precision float.
|
|
*/
|
|
public static final @HalfFloat short NEGATIVE_ZERO = (short) 0x8000;
|
|
/**
|
|
* Positive infinity of type half-precision float.
|
|
*/
|
|
public static final @HalfFloat short POSITIVE_INFINITY = (short) 0x7c00;
|
|
/**
|
|
* Positive 0 of type half-precision float.
|
|
*/
|
|
public static final @HalfFloat short POSITIVE_ZERO = (short) 0x0000;
|
|
|
|
private final @HalfFloat short mValue;
|
|
|
|
/**
|
|
* Constructs a newly allocated {@code Half} object that represents the
|
|
* half-precision float type argument.
|
|
*
|
|
* @param value The value to be represented by the {@code Half}
|
|
*/
|
|
public Half(@HalfFloat short value) {
|
|
mValue = value;
|
|
}
|
|
|
|
/**
|
|
* Constructs a newly allocated {@code Half} object that represents the
|
|
* argument converted to a half-precision float.
|
|
*
|
|
* @param value The value to be represented by the {@code Half}
|
|
*
|
|
* @see #toHalf(float)
|
|
*/
|
|
public Half(float value) {
|
|
mValue = toHalf(value);
|
|
}
|
|
|
|
/**
|
|
* Constructs a newly allocated {@code Half} object that
|
|
* represents the argument converted to a half-precision float.
|
|
*
|
|
* @param value The value to be represented by the {@code Half}
|
|
*
|
|
* @see #toHalf(float)
|
|
*/
|
|
public Half(double value) {
|
|
mValue = toHalf((float) value);
|
|
}
|
|
|
|
/**
|
|
* <p>Constructs a newly allocated {@code Half} object that represents the
|
|
* half-precision float value represented by the string.
|
|
* The string is converted to a half-precision float value as if by the
|
|
* {@link #valueOf(String)} method.</p>
|
|
*
|
|
* <p>Calling this constructor is equivalent to calling:</p>
|
|
* <pre>
|
|
* new Half(Float.parseFloat(value))
|
|
* </pre>
|
|
*
|
|
* @param value A string to be converted to a {@code Half}
|
|
* @throws NumberFormatException if the string does not contain a parsable number
|
|
*
|
|
* @see Float#valueOf(java.lang.String)
|
|
* @see #toHalf(float)
|
|
*/
|
|
public Half(@NonNull String value) throws NumberFormatException {
|
|
mValue = toHalf(Float.parseFloat(value));
|
|
}
|
|
|
|
/**
|
|
* Returns the half-precision value of this {@code Half} as a {@code short}
|
|
* containing the bit representation described in {@link Half}.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
*/
|
|
public @HalfFloat short halfValue() {
|
|
return mValue;
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code byte} after
|
|
* a narrowing primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code byte}
|
|
*/
|
|
@Override
|
|
public byte byteValue() {
|
|
return (byte) toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code short} after
|
|
* a narrowing primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code short}
|
|
*/
|
|
@Override
|
|
public short shortValue() {
|
|
return (short) toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code int} after
|
|
* a narrowing primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code int}
|
|
*/
|
|
@Override
|
|
public int intValue() {
|
|
return (int) toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code long} after
|
|
* a narrowing primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code long}
|
|
*/
|
|
@Override
|
|
public long longValue() {
|
|
return (long) toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code float} after
|
|
* a widening primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code float}
|
|
*/
|
|
@Override
|
|
public float floatValue() {
|
|
return toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns the value of this {@code Half} as a {@code double} after
|
|
* a widening primitive conversion.
|
|
*
|
|
* @return The half-precision float value represented by this object
|
|
* converted to type {@code double}
|
|
*/
|
|
@Override
|
|
public double doubleValue() {
|
|
return toFloat(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns true if this {@code Half} value represents a Not-a-Number,
|
|
* false otherwise.
|
|
*
|
|
* @return True if the value is a NaN, false otherwise
|
|
*/
|
|
public boolean isNaN() {
|
|
return isNaN(mValue);
|
|
}
|
|
|
|
/**
|
|
* Compares this object against the specified object. The result is {@code true}
|
|
* if and only if the argument is not {@code null} and is a {@code Half} object
|
|
* that represents the same half-precision value as the this object. Two
|
|
* half-precision values are considered to be the same if and only if the method
|
|
* {@link #halfToIntBits(short)} returns an identical {@code int} value for both.
|
|
*
|
|
* @param o The object to compare
|
|
* @return True if the objects are the same, false otherwise
|
|
*
|
|
* @see #halfToIntBits(short)
|
|
*/
|
|
@Override
|
|
public boolean equals(@Nullable Object o) {
|
|
return (o instanceof Half) &&
|
|
(halfToIntBits(((Half) o).mValue) == halfToIntBits(mValue));
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code for this {@code Half} object. The result is the
|
|
* integer bit representation, exactly as produced by the method
|
|
* {@link #halfToIntBits(short)}, of the primitive half-precision float
|
|
* value represented by this {@code Half} object.
|
|
*
|
|
* @return A hash code value for this object
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
return hashCode(mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of the specified half-precision
|
|
* float value. See {@link #toString(short)} for more information.
|
|
*
|
|
* @return A string representation of this {@code Half} object
|
|
*/
|
|
@NonNull
|
|
@Override
|
|
public String toString() {
|
|
return toString(mValue);
|
|
}
|
|
|
|
/**
|
|
* <p>Compares the two specified half-precision float values. The following
|
|
* conditions apply during the comparison:</p>
|
|
*
|
|
* <ul>
|
|
* <li>{@link #NaN} is considered by this method to be equal to itself and greater
|
|
* than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
|
|
* <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
|
|
* {@link #NEGATIVE_ZERO}.</li>
|
|
* </ul>
|
|
*
|
|
* @param h The half-precision float value to compare to the half-precision value
|
|
* represented by this {@code Half} object
|
|
*
|
|
* @return The value {@code 0} if {@code x} is numerically equal to {@code y}; a
|
|
* value less than {@code 0} if {@code x} is numerically less than {@code y};
|
|
* and a value greater than {@code 0} if {@code x} is numerically greater
|
|
* than {@code y}
|
|
*/
|
|
@Override
|
|
public int compareTo(@NonNull Half h) {
|
|
return compare(mValue, h.mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code for a half-precision float value.
|
|
*
|
|
* @param h The value to hash
|
|
*
|
|
* @return A hash code value for a half-precision float value
|
|
*/
|
|
public static int hashCode(@HalfFloat short h) {
|
|
return halfToIntBits(h);
|
|
}
|
|
|
|
/**
|
|
* <p>Compares the two specified half-precision float values. The following
|
|
* conditions apply during the comparison:</p>
|
|
*
|
|
* <ul>
|
|
* <li>{@link #NaN} is considered by this method to be equal to itself and greater
|
|
* than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
|
|
* <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
|
|
* {@link #NEGATIVE_ZERO}.</li>
|
|
* </ul>
|
|
*
|
|
* @param x The first half-precision float value to compare.
|
|
* @param y The second half-precision float value to compare
|
|
*
|
|
* @return The value {@code 0} if {@code x} is numerically equal to {@code y}, a
|
|
* value less than {@code 0} if {@code x} is numerically less than {@code y},
|
|
* and a value greater than {@code 0} if {@code x} is numerically greater
|
|
* than {@code y}
|
|
*/
|
|
public static int compare(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.compare(x, y);
|
|
}
|
|
|
|
/**
|
|
* <p>Returns a representation of the specified half-precision float value
|
|
* according to the bit layout described in {@link Half}.</p>
|
|
*
|
|
* <p>Similar to {@link #halfToIntBits(short)}, this method collapses all
|
|
* possible Not-a-Number values to a single canonical Not-a-Number value
|
|
* defined by {@link #NaN}.</p>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The bits that represent the half-precision float value
|
|
*
|
|
* @see #halfToIntBits(short)
|
|
*/
|
|
public static @HalfFloat short halfToShortBits(@HalfFloat short h) {
|
|
return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h;
|
|
}
|
|
|
|
/**
|
|
* <p>Returns a representation of the specified half-precision float value
|
|
* according to the bit layout described in {@link Half}.</p>
|
|
*
|
|
* <p>Unlike {@link #halfToRawIntBits(short)}, this method collapses all
|
|
* possible Not-a-Number values to a single canonical Not-a-Number value
|
|
* defined by {@link #NaN}.</p>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The bits that represent the half-precision float value
|
|
*
|
|
* @see #halfToRawIntBits(short)
|
|
* @see #halfToShortBits(short)
|
|
* @see #intBitsToHalf(int)
|
|
*/
|
|
public static int halfToIntBits(@HalfFloat short h) {
|
|
return (h & FP16.EXPONENT_SIGNIFICAND_MASK) > FP16.POSITIVE_INFINITY ? NaN : h & 0xffff;
|
|
}
|
|
|
|
/**
|
|
* <p>Returns a representation of the specified half-precision float value
|
|
* according to the bit layout described in {@link Half}.</p>
|
|
*
|
|
* <p>The argument is considered to be a representation of a half-precision
|
|
* float value according to the bit layout described in {@link Half}. The 16
|
|
* most significant bits of the returned value are set to 0.</p>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The bits that represent the half-precision float value
|
|
*
|
|
* @see #halfToIntBits(short)
|
|
* @see #intBitsToHalf(int)
|
|
*/
|
|
public static int halfToRawIntBits(@HalfFloat short h) {
|
|
return h & 0xffff;
|
|
}
|
|
|
|
/**
|
|
* <p>Returns the half-precision float value corresponding to a given
|
|
* bit representation.</p>
|
|
*
|
|
* <p>The argument is considered to be a representation of a half-precision
|
|
* float value according to the bit layout described in {@link Half}. The 16
|
|
* most significant bits of the argument are ignored.</p>
|
|
*
|
|
* @param bits An integer
|
|
* @return The half-precision float value with the same bit pattern
|
|
*/
|
|
public static @HalfFloat short intBitsToHalf(int bits) {
|
|
return (short) (bits & 0xffff);
|
|
}
|
|
|
|
/**
|
|
* Returns the first parameter with the sign of the second parameter.
|
|
* This method treats NaNs as having a sign.
|
|
*
|
|
* @param magnitude A half-precision float value providing the magnitude of the result
|
|
* @param sign A half-precision float value providing the sign of the result
|
|
* @return A value with the magnitude of the first parameter and the sign
|
|
* of the second parameter
|
|
*/
|
|
public static @HalfFloat short copySign(@HalfFloat short magnitude, @HalfFloat short sign) {
|
|
return (short) ((sign & FP16.SIGN_MASK) | (magnitude & FP16.EXPONENT_SIGNIFICAND_MASK));
|
|
}
|
|
|
|
/**
|
|
* Returns the absolute value of the specified half-precision float.
|
|
* Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If the specified half-precision float is NaN, the result is NaN</li>
|
|
* <li>If the specified half-precision float is zero (negative or positive),
|
|
* the result is positive zero (see {@link #POSITIVE_ZERO})</li>
|
|
* <li>If the specified half-precision float is infinity (negative or positive),
|
|
* the result is positive infinity (see {@link #POSITIVE_INFINITY})</li>
|
|
* </ul>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The absolute value of the specified half-precision float
|
|
*/
|
|
public static @HalfFloat short abs(@HalfFloat short h) {
|
|
return (short) (h & FP16.EXPONENT_SIGNIFICAND_MASK);
|
|
}
|
|
|
|
/**
|
|
* Returns the closest integral half-precision float value to the specified
|
|
* half-precision float value. Special values are handled in the
|
|
* following ways:
|
|
* <ul>
|
|
* <li>If the specified half-precision float is NaN, the result is NaN</li>
|
|
* <li>If the specified half-precision float is infinity (negative or positive),
|
|
* the result is infinity (with the same sign)</li>
|
|
* <li>If the specified half-precision float is zero (negative or positive),
|
|
* the result is zero (with the same sign)</li>
|
|
* </ul>
|
|
*
|
|
* <p class=note>
|
|
* <strong>Note:</strong> Unlike the identically named
|
|
* <code class=prettyprint>int java.lang.Math.round(float)</code> method,
|
|
* this returns a Half value stored in a short, <strong>not</strong> an
|
|
* actual short integer result.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The value of the specified half-precision float rounded to the nearest
|
|
* half-precision float value
|
|
*/
|
|
public static @HalfFloat short round(@HalfFloat short h) {
|
|
return FP16.rint(h);
|
|
}
|
|
|
|
/**
|
|
* Returns the smallest half-precision float value toward negative infinity
|
|
* greater than or equal to the specified half-precision float value.
|
|
* Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If the specified half-precision float is NaN, the result is NaN</li>
|
|
* <li>If the specified half-precision float is infinity (negative or positive),
|
|
* the result is infinity (with the same sign)</li>
|
|
* <li>If the specified half-precision float is zero (negative or positive),
|
|
* the result is zero (with the same sign)</li>
|
|
* </ul>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The smallest half-precision float value toward negative infinity
|
|
* greater than or equal to the specified half-precision float value
|
|
*/
|
|
public static @HalfFloat short ceil(@HalfFloat short h) {
|
|
return FP16.ceil(h);
|
|
}
|
|
|
|
/**
|
|
* Returns the largest half-precision float value toward positive infinity
|
|
* less than or equal to the specified half-precision float value.
|
|
* Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If the specified half-precision float is NaN, the result is NaN</li>
|
|
* <li>If the specified half-precision float is infinity (negative or positive),
|
|
* the result is infinity (with the same sign)</li>
|
|
* <li>If the specified half-precision float is zero (negative or positive),
|
|
* the result is zero (with the same sign)</li>
|
|
* </ul>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The largest half-precision float value toward positive infinity
|
|
* less than or equal to the specified half-precision float value
|
|
*/
|
|
public static @HalfFloat short floor(@HalfFloat short h) {
|
|
return FP16.floor(h);
|
|
}
|
|
|
|
/**
|
|
* Returns the truncated half-precision float value of the specified
|
|
* half-precision float value. Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If the specified half-precision float is NaN, the result is NaN</li>
|
|
* <li>If the specified half-precision float is infinity (negative or positive),
|
|
* the result is infinity (with the same sign)</li>
|
|
* <li>If the specified half-precision float is zero (negative or positive),
|
|
* the result is zero (with the same sign)</li>
|
|
* </ul>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The truncated half-precision float value of the specified
|
|
* half-precision float value
|
|
*/
|
|
public static @HalfFloat short trunc(@HalfFloat short h) {
|
|
return FP16.trunc(h);
|
|
}
|
|
|
|
/**
|
|
* Returns the smaller of two half-precision float values (the value closest
|
|
* to negative infinity). Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If either value is NaN, the result is NaN</li>
|
|
* <li>{@link #NEGATIVE_ZERO} is smaller than {@link #POSITIVE_ZERO}</li>
|
|
* </ul>
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
* @return The smaller of the two specified half-precision values
|
|
*/
|
|
public static @HalfFloat short min(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.min(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns the larger of two half-precision float values (the value closest
|
|
* to positive infinity). Special values are handled in the following ways:
|
|
* <ul>
|
|
* <li>If either value is NaN, the result is NaN</li>
|
|
* <li>{@link #POSITIVE_ZERO} is greater than {@link #NEGATIVE_ZERO}</li>
|
|
* </ul>
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return The larger of the two specified half-precision values
|
|
*/
|
|
public static @HalfFloat short max(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.max(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the first half-precision float value is less (smaller
|
|
* toward negative infinity) than the second half-precision float value.
|
|
* If either of the values is NaN, the result is false.
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return True if x is less than y, false otherwise
|
|
*/
|
|
public static boolean less(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.less(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the first half-precision float value is less (smaller
|
|
* toward negative infinity) than or equal to the second half-precision
|
|
* float value. If either of the values is NaN, the result is false.
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return True if x is less than or equal to y, false otherwise
|
|
*/
|
|
public static boolean lessEquals(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.lessEquals(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the first half-precision float value is greater (larger
|
|
* toward positive infinity) than the second half-precision float value.
|
|
* If either of the values is NaN, the result is false.
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return True if x is greater than y, false otherwise
|
|
*/
|
|
public static boolean greater(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.greater(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the first half-precision float value is greater (larger
|
|
* toward positive infinity) than or equal to the second half-precision float
|
|
* value. If either of the values is NaN, the result is false.
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return True if x is greater than y, false otherwise
|
|
*/
|
|
public static boolean greaterEquals(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.greaterEquals(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the two half-precision float values are equal.
|
|
* If either of the values is NaN, the result is false. {@link #POSITIVE_ZERO}
|
|
* and {@link #NEGATIVE_ZERO} are considered equal.
|
|
*
|
|
* @param x The first half-precision value
|
|
* @param y The second half-precision value
|
|
*
|
|
* @return True if x is equal to y, false otherwise
|
|
*/
|
|
public static boolean equals(@HalfFloat short x, @HalfFloat short y) {
|
|
return FP16.equals(x, y);
|
|
}
|
|
|
|
/**
|
|
* Returns the sign of the specified half-precision float.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return 1 if the value is positive, -1 if the value is negative
|
|
*/
|
|
public static int getSign(@HalfFloat short h) {
|
|
return (h & FP16.SIGN_MASK) == 0 ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Returns the unbiased exponent used in the representation of
|
|
* the specified half-precision float value. if the value is NaN
|
|
* or infinite, this* method returns {@link #MAX_EXPONENT} + 1.
|
|
* If the argument is 0 or a subnormal representation, this method
|
|
* returns {@link #MIN_EXPONENT} - 1.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The unbiased exponent of the specified value
|
|
*/
|
|
public static int getExponent(@HalfFloat short h) {
|
|
return ((h >>> FP16.EXPONENT_SHIFT) & FP16.SHIFTED_EXPONENT_MASK) - FP16.EXPONENT_BIAS;
|
|
}
|
|
|
|
/**
|
|
* Returns the significand, or mantissa, used in the representation
|
|
* of the specified half-precision float value.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return The significand, or significand, of the specified vlaue
|
|
*/
|
|
public static int getSignificand(@HalfFloat short h) {
|
|
return h & FP16.SIGNIFICAND_MASK;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the specified half-precision float value represents
|
|
* infinity, false otherwise.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return True if the value is positive infinity or negative infinity,
|
|
* false otherwise
|
|
*/
|
|
public static boolean isInfinite(@HalfFloat short h) {
|
|
return FP16.isInfinite(h);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the specified half-precision float value represents
|
|
* a Not-a-Number, false otherwise.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return True if the value is a NaN, false otherwise
|
|
*/
|
|
public static boolean isNaN(@HalfFloat short h) {
|
|
return FP16.isNaN(h);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the specified half-precision float value is normalized
|
|
* (does not have a subnormal representation). If the specified value is
|
|
* {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY},
|
|
* {@link #POSITIVE_ZERO}, {@link #NEGATIVE_ZERO}, NaN or any subnormal
|
|
* number, this method returns false.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return True if the value is normalized, false otherwise
|
|
*/
|
|
public static boolean isNormalized(@HalfFloat short h) {
|
|
return FP16.isNormalized(h);
|
|
}
|
|
|
|
/**
|
|
* <p>Converts the specified half-precision float value into a
|
|
* single-precision float value. The following special cases are handled:</p>
|
|
* <ul>
|
|
* <li>If the input is {@link #NaN}, the returned value is {@link Float#NaN}</li>
|
|
* <li>If the input is {@link #POSITIVE_INFINITY} or
|
|
* {@link #NEGATIVE_INFINITY}, the returned value is respectively
|
|
* {@link Float#POSITIVE_INFINITY} or {@link Float#NEGATIVE_INFINITY}</li>
|
|
* <li>If the input is 0 (positive or negative), the returned value is +/-0.0f</li>
|
|
* <li>Otherwise, the returned value is a normalized single-precision float value</li>
|
|
* </ul>
|
|
*
|
|
* @param h The half-precision float value to convert to single-precision
|
|
* @return A normalized single-precision float value
|
|
*/
|
|
public static float toFloat(@HalfFloat short h) {
|
|
return FP16.toFloat(h);
|
|
}
|
|
|
|
/**
|
|
* <p>Converts the specified single-precision float value into a
|
|
* half-precision float value. The following special cases are handled:</p>
|
|
* <ul>
|
|
* <li>If the input is NaN (see {@link Float#isNaN(float)}), the returned
|
|
* value is {@link #NaN}</li>
|
|
* <li>If the input is {@link Float#POSITIVE_INFINITY} or
|
|
* {@link Float#NEGATIVE_INFINITY}, the returned value is respectively
|
|
* {@link #POSITIVE_INFINITY} or {@link #NEGATIVE_INFINITY}</li>
|
|
* <li>If the input is 0 (positive or negative), the returned value is
|
|
* {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li>
|
|
* <li>If the input is a less than {@link #MIN_VALUE}, the returned value
|
|
* is flushed to {@link #POSITIVE_ZERO} or {@link #NEGATIVE_ZERO}</li>
|
|
* <li>If the input is a less than {@link #MIN_NORMAL}, the returned value
|
|
* is a denorm half-precision float</li>
|
|
* <li>Otherwise, the returned value is rounded to the nearest
|
|
* representable half-precision float value</li>
|
|
* </ul>
|
|
*
|
|
* @param f The single-precision float value to convert to half-precision
|
|
* @return A half-precision float value
|
|
*/
|
|
@SuppressWarnings("StatementWithEmptyBody")
|
|
public static @HalfFloat short toHalf(float f) {
|
|
return FP16.toHalf(f);
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code Half} instance representing the specified
|
|
* half-precision float value.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return a {@code Half} instance representing {@code h}
|
|
*/
|
|
public static @NonNull Half valueOf(@HalfFloat short h) {
|
|
return new Half(h);
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code Half} instance representing the specified float value.
|
|
*
|
|
* @param f A float value
|
|
* @return a {@code Half} instance representing {@code f}
|
|
*/
|
|
public static @NonNull Half valueOf(float f) {
|
|
return new Half(f);
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code Half} instance representing the specified string value.
|
|
* Calling this method is equivalent to calling
|
|
* <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
|
|
* for more information on the format of the string representation.
|
|
*
|
|
* @param s The string to be parsed
|
|
* @return a {@code Half} instance representing {@code h}
|
|
* @throws NumberFormatException if the string does not contain a parsable
|
|
* half-precision float value
|
|
*/
|
|
public static @NonNull Half valueOf(@NonNull String s) {
|
|
return new Half(s);
|
|
}
|
|
|
|
/**
|
|
* Returns the half-precision float value represented by the specified string.
|
|
* Calling this method is equivalent to calling
|
|
* <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
|
|
* for more information on the format of the string representation.
|
|
*
|
|
* @param s The string to be parsed
|
|
* @return A half-precision float value represented by the string
|
|
* @throws NumberFormatException if the string does not contain a parsable
|
|
* half-precision float value
|
|
*/
|
|
public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
|
|
return toHalf(Float.parseFloat(s));
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of the specified half-precision
|
|
* float value. Calling this method is equivalent to calling
|
|
* <code>Float.toString(toFloat(h))</code>. See {@link Float#toString(float)}
|
|
* for more information on the format of the string representation.
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return A string representation of the specified value
|
|
*/
|
|
@NonNull
|
|
public static String toString(@HalfFloat short h) {
|
|
return Float.toString(toFloat(h));
|
|
}
|
|
|
|
/**
|
|
* <p>Returns a hexadecimal string representation of the specified half-precision
|
|
* float value. If the value is a NaN, the result is <code>"NaN"</code>,
|
|
* otherwise the result follows this format:</p>
|
|
* <ul>
|
|
* <li>If the sign is positive, no sign character appears in the result</li>
|
|
* <li>If the sign is negative, the first character is <code>'-'</code></li>
|
|
* <li>If the value is inifinity, the string is <code>"Infinity"</code></li>
|
|
* <li>If the value is 0, the string is <code>"0x0.0p0"</code></li>
|
|
* <li>If the value has a normalized representation, the exponent and
|
|
* significand are represented in the string in two fields. The significand
|
|
* starts with <code>"0x1."</code> followed by its lowercase hexadecimal
|
|
* representation. Trailing zeroes are removed unless all digits are 0, then
|
|
* a single zero is used. The significand representation is followed by the
|
|
* exponent, represented by <code>"p"</code>, itself followed by a decimal
|
|
* string of the unbiased exponent</li>
|
|
* <li>If the value has a subnormal representation, the significand starts
|
|
* with <code>"0x0."</code> followed by its lowercase hexadecimal
|
|
* representation. Trailing zeroes are removed unless all digits are 0, then
|
|
* a single zero is used. The significand representation is followed by the
|
|
* exponent, represented by <code>"p-14"</code></li>
|
|
* </ul>
|
|
*
|
|
* @param h A half-precision float value
|
|
* @return A hexadecimal string representation of the specified value
|
|
*/
|
|
@NonNull
|
|
public static String toHexString(@HalfFloat short h) {
|
|
return FP16.toHexString(h);
|
|
}
|
|
}
|