xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 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 | import libcore.util.FP16; |
| 18 | |
| 19 | public class Main { |
| 20 | public Main() { |
| 21 | } |
| 22 | |
| 23 | public static int TestFP16ToFloatRawIntBits(short half) { |
| 24 | float f = FP16.toFloat(half); |
| 25 | // Since in this test class we need to check the integer representing of |
| 26 | // the actual float NaN values, the floatToRawIntBits() is used instead of |
| 27 | // floatToIntBits(). |
| 28 | return Float.floatToRawIntBits(f); |
| 29 | } |
| 30 | |
Vladimir Marko | 7f958e3 | 2019-10-24 09:03:58 +0000 | [diff] [blame] | 31 | public static void assertEquals(short expected, short calculated) { |
| 32 | if (expected != calculated) { |
| 33 | throw new Error("Expected: " + expected + ", Calculated: " + calculated); |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 34 | } |
| 35 | } |
Vladimir Marko | 7f958e3 | 2019-10-24 09:03:58 +0000 | [diff] [blame] | 36 | public static void assertEquals(float expected, float calculated) { |
| 37 | if (expected != calculated) { |
| 38 | throw new Error("Expected: " + expected + ", Calculated: " + calculated); |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 39 | } |
| 40 | } |
| 41 | |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 42 | public static void testHalfToFloatToHalfConversions(){ |
| 43 | // Test FP16 to float and back to Half for all possible Short values |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 44 | for (short h = Short.MIN_VALUE; h < Short.MAX_VALUE; h++) { |
| 45 | if (FP16.isNaN(h)) { |
| 46 | // NaN inputs are tested below. |
| 47 | continue; |
| 48 | } |
Vladimir Marko | 7f958e3 | 2019-10-24 09:03:58 +0000 | [diff] [blame] | 49 | assertEquals(h, FP16.toHalf(FP16.toFloat(h))); |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 50 | } |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 51 | } |
Vladimir Marko | 7f958e3 | 2019-10-24 09:03:58 +0000 | [diff] [blame] | 52 | |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 53 | public static void testToHalf(){ |
Vladimir Marko | 7f958e3 | 2019-10-24 09:03:58 +0000 | [diff] [blame] | 54 | // These asserts check some known values and edge cases for FP16.toHalf |
| 55 | // and have been inspired by the cts HalfTest. |
| 56 | // Zeroes, NaN and infinities |
| 57 | assertEquals(FP16.POSITIVE_ZERO, FP16.toHalf(0.0f)); |
| 58 | assertEquals(FP16.NEGATIVE_ZERO, FP16.toHalf(-0.0f)); |
| 59 | assertEquals(FP16.NaN, FP16.toHalf(Float.NaN)); |
| 60 | assertEquals(FP16.POSITIVE_INFINITY, FP16.toHalf(Float.POSITIVE_INFINITY)); |
| 61 | assertEquals(FP16.NEGATIVE_INFINITY, FP16.toHalf(Float.NEGATIVE_INFINITY)); |
| 62 | // Known values |
| 63 | assertEquals((short) 0x3c01, FP16.toHalf(1.0009765625f)); |
| 64 | assertEquals((short) 0xc000, FP16.toHalf(-2.0f)); |
| 65 | assertEquals((short) 0x0400, FP16.toHalf(6.10352e-5f)); |
| 66 | assertEquals((short) 0x7bff, FP16.toHalf(65504.0f)); |
| 67 | assertEquals((short) 0x3555, FP16.toHalf(1.0f / 3.0f)); |
| 68 | // Subnormals |
| 69 | assertEquals((short) 0x03ff, FP16.toHalf(6.09756e-5f)); |
| 70 | assertEquals(FP16.MIN_VALUE, FP16.toHalf(5.96046e-8f)); |
| 71 | assertEquals((short) 0x83ff, FP16.toHalf(-6.09756e-5f)); |
| 72 | assertEquals((short) 0x8001, FP16.toHalf(-5.96046e-8f)); |
| 73 | // Subnormals (flushed to +/-0) |
| 74 | assertEquals(FP16.POSITIVE_ZERO, FP16.toHalf(5.96046e-9f)); |
| 75 | assertEquals(FP16.NEGATIVE_ZERO, FP16.toHalf(-5.96046e-9f)); |
| 76 | // Test for values that overflow the mantissa bits into exp bits |
| 77 | assertEquals(0x1000, FP16.toHalf(Float.intBitsToFloat(0x39fff000))); |
| 78 | assertEquals(0x0400, FP16.toHalf(Float.intBitsToFloat(0x387fe000))); |
| 79 | // Floats with absolute value above +/-65519 are rounded to +/-inf |
| 80 | // when using round-to-even |
| 81 | assertEquals(0x7bff, FP16.toHalf(65519.0f)); |
| 82 | assertEquals(0x7bff, FP16.toHalf(65519.9f)); |
| 83 | assertEquals(FP16.POSITIVE_INFINITY, FP16.toHalf(65520.0f)); |
| 84 | assertEquals(FP16.NEGATIVE_INFINITY, FP16.toHalf(-65520.0f)); |
| 85 | // Check if numbers are rounded to nearest even when they |
| 86 | // cannot be accurately represented by Half |
| 87 | assertEquals(0x6800, FP16.toHalf(2049.0f)); |
| 88 | assertEquals(0x6c00, FP16.toHalf(4098.0f)); |
| 89 | assertEquals(0x7000, FP16.toHalf(8196.0f)); |
| 90 | assertEquals(0x7400, FP16.toHalf(16392.0f)); |
| 91 | assertEquals(0x7800, FP16.toHalf(32784.0f)); |
| 92 | |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | public static void testToFloat(){ |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 96 | // FP16 SNaN/QNaN inputs to float |
| 97 | // The most significant bit of mantissa: |
| 98 | // V |
| 99 | // 0xfc01: 1 11111 0000000001 (signaling NaN) |
| 100 | // 0xfdff: 1 11111 0111111111 (signaling NaN) |
| 101 | // 0xfe00: 1 11111 1000000000 (quiet NaN) |
| 102 | // 0xffff: 1 11111 1111111111 (quiet NaN) |
| 103 | // This test is inspired by Java implementation of android.util.Half.toFloat(), |
| 104 | // where the implementation performs SNaN->QNaN conversion. |
| 105 | assert(Float.isNaN(FP16.toFloat((short)0xfc01))); |
| 106 | assert(Float.isNaN(FP16.toFloat((short)0xfdff))); |
| 107 | assert(Float.isNaN(FP16.toFloat((short)0xfe00))); |
| 108 | assert(Float.isNaN(FP16.toFloat((short)0xffff))); |
| 109 | assertEquals(0xffc02000, TestFP16ToFloatRawIntBits((short)(0xfc01))); // SNaN->QNaN |
| 110 | assertEquals(0xffffe000, TestFP16ToFloatRawIntBits((short)(0xfdff))); // SNaN->QNaN |
| 111 | assertEquals(0xffc00000, TestFP16ToFloatRawIntBits((short)(0xfe00))); // QNaN->QNaN |
| 112 | assertEquals(0xffffe000, TestFP16ToFloatRawIntBits((short)(0xffff))); // QNaN->QNaN |
| 113 | } |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 114 | |
Usama Arif | b9f02c2 | 2019-10-25 17:37:33 +0100 | [diff] [blame^] | 115 | public static void testFloor() { |
| 116 | // These tests have been taken from the cts HalfTest |
| 117 | assertEquals(FP16.POSITIVE_INFINITY, FP16.floor(FP16.POSITIVE_INFINITY)); |
| 118 | assertEquals(FP16.NEGATIVE_INFINITY, FP16.floor(FP16.NEGATIVE_INFINITY)); |
| 119 | assertEquals(FP16.POSITIVE_ZERO, FP16.floor(FP16.POSITIVE_ZERO)); |
| 120 | assertEquals(FP16.NEGATIVE_ZERO, FP16.floor(FP16.NEGATIVE_ZERO)); |
| 121 | assertEquals(FP16.NaN, FP16.floor(FP16.NaN)); |
| 122 | assertEquals(FP16.LOWEST_VALUE, FP16.floor(FP16.LOWEST_VALUE)); |
| 123 | assertEquals(FP16.POSITIVE_ZERO, FP16.floor(FP16.MIN_NORMAL)); |
| 124 | assertEquals(FP16.POSITIVE_ZERO, FP16.floor((short) 0x3ff)); |
| 125 | assertEquals(FP16.POSITIVE_ZERO, FP16.floor(FP16.toHalf(0.2f))); |
| 126 | assertEquals(-1.0f, FP16.toFloat(FP16.floor(FP16.toHalf(-0.2f)))); |
| 127 | assertEquals(-1.0f, FP16.toFloat(FP16.floor(FP16.toHalf(-0.7f)))); |
| 128 | assertEquals(FP16.POSITIVE_ZERO, FP16.floor(FP16.toHalf(0.7f))); |
| 129 | assertEquals(124.0f, FP16.toFloat(FP16.floor(FP16.toHalf(124.7f)))); |
| 130 | assertEquals(-125.0f, FP16.toFloat(FP16.floor(FP16.toHalf(-124.7f)))); |
| 131 | assertEquals(124.0f, FP16.toFloat(FP16.floor(FP16.toHalf(124.2f)))); |
| 132 | assertEquals(-125.0f, FP16.toFloat(FP16.floor(FP16.toHalf(-124.2f)))); |
| 133 | // floor for NaN values |
| 134 | assertEquals((short) 0x7e01, FP16.floor((short) 0x7c01)); |
| 135 | assertEquals((short) 0x7f00, FP16.floor((short) 0x7d00)); |
| 136 | assertEquals((short) 0xfe01, FP16.floor((short) 0xfc01)); |
| 137 | assertEquals((short) 0xff00, FP16.floor((short) 0xfd00)); |
| 138 | } |
| 139 | |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 140 | public static void main(String args[]) { |
| 141 | testHalfToFloatToHalfConversions(); |
| 142 | testToHalf(); |
| 143 | testToFloat(); |
Usama Arif | b9f02c2 | 2019-10-25 17:37:33 +0100 | [diff] [blame^] | 144 | testFloor(); |
Usama Arif | 64bac15 | 2019-10-28 12:11:21 +0000 | [diff] [blame] | 145 | } |
xueliang.zhong | 9ce340f | 2019-01-22 17:46:09 +0000 | [diff] [blame] | 146 | } |