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 public static boolean doThrow = false; 33 34 /// CHECK-START: float TestFpAbs.$opt$noinline$absSP(float) builder (after) 35 /// CHECK-DAG: <<Result:f\d+>> Abs 36 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absSP(float f)37 private static float $opt$noinline$absSP(float f) { 38 return Math.abs(f); 39 } 40 41 /// CHECK-START: double TestFpAbs.$opt$noinline$absDP(double) builder (after) 42 /// CHECK-DAG: <<Result:d\d+>> Abs 43 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absDP(double d)44 private static double $opt$noinline$absDP(double d) { 45 return Math.abs(d); 46 } 47 main()48 public static void main() { 49 // A few obvious numbers. 50 for (float f = -100.0f; f < 0.0f; f += 0.5f) { 51 expectEqualsSP(-f, $opt$noinline$absSP(f)); 52 } 53 for (float f = 0.0f; f <= 100.0f; f += 0.5f) { 54 expectEqualsSP(f, $opt$noinline$absSP(f)); 55 } 56 for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 57 expectEqualsSP(-f, $opt$noinline$absSP(f)); 58 } 59 for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 60 expectEqualsSP(f, $opt$noinline$absSP(f)); 61 } 62 63 // Zero 64 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f))); 65 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f))); 66 67 // Inf. 68 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY)); 69 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY)); 70 71 // A few NaN numbers. 72 int[] spnans = { 73 0x7f800001, // signaling 74 0x7fa00000, 75 0x7fbfffff, 76 0x7fc00000, // quiet 77 0x7fc00001, 78 0x7fffffff, 79 0xff800001, // signaling 80 0xffa00000, 81 0xffbfffff, 82 0xffc00000, // quiet 83 0xffffffff 84 }; 85 for (int i = 0; i < spnans.length; i++) { 86 float f = Float.intBitsToFloat(spnans[i]); 87 expectEqualsNaN32( 88 spnans[i] & Integer.MAX_VALUE, 89 Float.floatToRawIntBits($opt$noinline$absSP(f))); 90 } 91 92 // A few obvious numbers. 93 for (double d = -100.0; d < 0.0; d += 0.5) { 94 expectEqualsDP(-d, $opt$noinline$absDP(d)); 95 } 96 for (double d = 0.0; d <= 100.0; d += 0.5) { 97 expectEqualsDP(d, $opt$noinline$absDP(d)); 98 } 99 for (double d = -1.5d; d <= -1.49999999999d; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { 100 expectEqualsDP(-d, $opt$noinline$absDP(d)); 101 } 102 for (double d = 1.49999999999d; d <= 1.5; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { 103 expectEqualsDP(d, $opt$noinline$absDP(d)); 104 } 105 106 // Zero 107 expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(+0.0f))); 108 expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(-0.0f))); 109 110 // Inf. 111 expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.NEGATIVE_INFINITY)); 112 expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.POSITIVE_INFINITY)); 113 114 // A few NaN numbers. 115 long[] dpnans = { 116 0x7ff0000000000001L, 117 0x7ff4000000000000L, 118 0x7ff8000000000000L, 119 0x7fffffffffffffffL, 120 0xfff0000000000001L, 121 0xfff4000000000000L, 122 0xfff8000000000000L, 123 0xffffffffffffffffL 124 }; 125 for (int i = 0; i < dpnans.length; i++) { 126 double d = Double.longBitsToDouble(dpnans[i]); 127 expectEqualsNaN64( 128 dpnans[i] & Long.MAX_VALUE, 129 Double.doubleToRawLongBits($opt$noinline$absDP(d))); 130 } 131 132 System.out.println("TestFpAbs passed"); 133 } 134 expectEquals32(int expected, int result)135 private static void expectEquals32(int expected, int result) { 136 if (expected != result) { 137 throw new Error("Expected: 0x" + Integer.toHexString(expected) 138 + ", found: 0x" + Integer.toHexString(result)); 139 } 140 } 141 142 // We allow that an expected NaN result has become quiet. expectEqualsNaN32(int expected, int result)143 private static void expectEqualsNaN32(int expected, int result) { 144 if (expected != result && (expected | SPQUIET) != result) { 145 if (!isDalvik) { 146 // If not on ART, relax the expected value more towards just 147 // "spec compliance" and allow sign bit to remain set for NaN. 148 if (expected == (result & Integer.MAX_VALUE)) { 149 return; 150 } 151 } 152 throw new Error("Expected: 0x" + Integer.toHexString(expected) 153 + ", found: 0x" + Integer.toHexString(result)); 154 } 155 } 156 expectEquals64(long expected, long result)157 private static void expectEquals64(long expected, long result) { 158 if (expected != result) { 159 throw new Error("Expected: 0x" + Long.toHexString(expected) 160 + ", found: 0x" + Long.toHexString(result)); 161 } 162 } 163 164 // We allow that an expected NaN result has become quiet. expectEqualsNaN64(long expected, long result)165 private static void expectEqualsNaN64(long expected, long result) { 166 if (expected != result && (expected | DPQUIET) != result) { 167 if (!isDalvik) { 168 // If not on ART, relax the expected value more towards just 169 // "spec compliance" and allow sign bit to remain set for NaN. 170 if (expected == (result & Long.MAX_VALUE)) { 171 return; 172 } 173 } 174 throw new Error("Expected: 0x" + Long.toHexString(expected) 175 + ", found: 0x" + Long.toHexString(result)); 176 } 177 } 178 expectEqualsSP(float expected, float result)179 private static void expectEqualsSP(float expected, float result) { 180 if (expected != result) { 181 throw new Error("Expected: " + expected + ", found: " + result); 182 } 183 } 184 expectEqualsDP(double expected, double result)185 private static void expectEqualsDP(double expected, double result) { 186 if (expected != result) { 187 throw new Error("Expected: " + expected + ", found: " + result); 188 } 189 } 190 } 191