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