1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * A few tests of Math.abs for floating-point data. 19 * 20 * Note, as a "quality of implementation", rather than pure "spec compliance", 21 * we require that Math.abs() clears the sign bit (but changes nothing else) 22 * for all numbers, including NaN (signaling NaN may become quiet though). 23 */ 24 public class TestFpAbs { 25 26 private final static boolean isDalvik = 27 System.getProperty("java.vm.name").equals("Dalvik"); 28 29 private static final int SPQUIET = 1 << 22; 30 private static final long DPQUIET = 1L << 51; 31 32 /// CHECK-START: float TestFpAbs.$opt$noinline$absSP(float) builder (after) 33 /// CHECK-DAG: <<Result:f\d+>> Abs 34 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absSP(float f)35 private static float $opt$noinline$absSP(float f) { 36 return Math.abs(f); 37 } 38 39 /// CHECK-START: double TestFpAbs.$opt$noinline$absDP(double) builder (after) 40 /// CHECK-DAG: <<Result:d\d+>> Abs 41 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absDP(double d)42 private static double $opt$noinline$absDP(double d) { 43 return Math.abs(d); 44 } 45 main()46 public static void main() { 47 // A few obvious numbers. 48 for (float f = -100.0f; f < 0.0f; f += 0.5f) { 49 expectEqualsSP(-f, $opt$noinline$absSP(f)); 50 } 51 for (float f = 0.0f; f <= 100.0f; f += 0.5f) { 52 expectEqualsSP(f, $opt$noinline$absSP(f)); 53 } 54 for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 55 expectEqualsSP(-f, $opt$noinline$absSP(f)); 56 } 57 for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 58 expectEqualsSP(f, $opt$noinline$absSP(f)); 59 } 60 61 // Zero 62 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f))); 63 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f))); 64 65 // Inf. 66 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY)); 67 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY)); 68 69 // A few NaN numbers. 70 int[] spnans = { 71 0x7f800001, // signaling 72 0x7fa00000, 73 0x7fbfffff, 74 0x7fc00000, // quiet 75 0x7fc00001, 76 0x7fffffff, 77 0xff800001, // signaling 78 0xffa00000, 79 0xffbfffff, 80 0xffc00000, // quiet 81 0xffffffff 82 }; 83 for (int i = 0; i < spnans.length; i++) { 84 float f = Float.intBitsToFloat(spnans[i]); 85 expectEqualsNaN32( 86 spnans[i] & Integer.MAX_VALUE, 87 Float.floatToRawIntBits($opt$noinline$absSP(f))); 88 } 89 90 // A few obvious numbers. 91 for (double d = -100.0; d < 0.0; d += 0.5) { 92 expectEqualsDP(-d, $opt$noinline$absDP(d)); 93 } 94 for (double d = 0.0; d <= 100.0; d += 0.5) { 95 expectEqualsDP(d, $opt$noinline$absDP(d)); 96 } 97 for (double d = -1.5d; d <= -1.49999999999d; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { 98 expectEqualsDP(-d, $opt$noinline$absDP(d)); 99 } 100 for (double d = 1.49999999999d; d <= 1.5; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { 101 expectEqualsDP(d, $opt$noinline$absDP(d)); 102 } 103 104 // Zero 105 expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(+0.0f))); 106 expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(-0.0f))); 107 108 // Inf. 109 expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.NEGATIVE_INFINITY)); 110 expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.POSITIVE_INFINITY)); 111 112 // A few NaN numbers. 113 long[] dpnans = { 114 0x7ff0000000000001L, 115 0x7ff4000000000000L, 116 0x7ff8000000000000L, 117 0x7fffffffffffffffL, 118 0xfff0000000000001L, 119 0xfff4000000000000L, 120 0xfff8000000000000L, 121 0xffffffffffffffffL 122 }; 123 for (int i = 0; i < dpnans.length; i++) { 124 double d = Double.longBitsToDouble(dpnans[i]); 125 expectEqualsNaN64( 126 dpnans[i] & Long.MAX_VALUE, 127 Double.doubleToRawLongBits($opt$noinline$absDP(d))); 128 } 129 130 System.out.println("TestFpAbs passed"); 131 } 132 expectEquals32(int expected, int result)133 private static void expectEquals32(int expected, int result) { 134 if (expected != result) { 135 throw new Error("Expected: 0x" + Integer.toHexString(expected) 136 + ", found: 0x" + Integer.toHexString(result)); 137 } 138 } 139 140 // We allow that an expected NaN result has become quiet. expectEqualsNaN32(int expected, int result)141 private static void expectEqualsNaN32(int expected, int result) { 142 if (expected != result && (expected | SPQUIET) != result) { 143 if (!isDalvik) { 144 // If not on ART, relax the expected value more towards just 145 // "spec compliance" and allow sign bit to remain set for NaN. 146 if (expected == (result & Integer.MAX_VALUE)) { 147 return; 148 } 149 } 150 throw new Error("Expected: 0x" + Integer.toHexString(expected) 151 + ", found: 0x" + Integer.toHexString(result)); 152 } 153 } 154 expectEquals64(long expected, long result)155 private static void expectEquals64(long expected, long result) { 156 if (expected != result) { 157 throw new Error("Expected: 0x" + Long.toHexString(expected) 158 + ", found: 0x" + Long.toHexString(result)); 159 } 160 } 161 162 // We allow that an expected NaN result has become quiet. expectEqualsNaN64(long expected, long result)163 private static void expectEqualsNaN64(long expected, long result) { 164 if (expected != result && (expected | DPQUIET) != result) { 165 if (!isDalvik) { 166 // If not on ART, relax the expected value more towards just 167 // "spec compliance" and allow sign bit to remain set for NaN. 168 if (expected == (result & Long.MAX_VALUE)) { 169 return; 170 } 171 } 172 throw new Error("Expected: 0x" + Long.toHexString(expected) 173 + ", found: 0x" + Long.toHexString(result)); 174 } 175 } 176 expectEqualsSP(float expected, float result)177 private static void expectEqualsSP(float expected, float result) { 178 if (expected != result) { 179 throw new Error("Expected: " + expected + ", found: " + result); 180 } 181 } 182 expectEqualsDP(double expected, double result)183 private static void expectEqualsDP(double expected, double result) { 184 if (expected != result) { 185 throw new Error("Expected: " + expected + ", found: " + result); 186 } 187 } 188 } 189