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 static final int SPQUIET = 1 << 22; 27 private static final long DPQUIET = 1L << 51; 28 29 public static boolean doThrow = false; 30 31 /// CHECK-START: float Main.$opt$noinline$absSP(float) intrinsics_recognition (after) 32 /// CHECK-DAG: <<Result:f\d+>> InvokeStaticOrDirect intrinsic:MathAbsFloat 33 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absSP(float f)34 private static float $opt$noinline$absSP(float f) { 35 if (doThrow) { 36 throw new Error("Something to prevent inlining"); 37 } 38 return Math.abs(f); 39 } 40 41 /// CHECK-START: double Main.$opt$noinline$absDP(double) intrinsics_recognition (after) 42 /// CHECK-DAG: <<Result:d\d+>> InvokeStaticOrDirect intrinsic:MathAbsDouble 43 /// CHECK-DAG: Return [<<Result>>] $opt$noinline$absDP(double d)44 private static double $opt$noinline$absDP(double d) { 45 if (doThrow) { 46 throw new Error("Something to prevent inlining"); 47 } 48 return Math.abs(d); 49 } 50 main(String args[])51 public static void main(String args[]) { 52 // A few obvious numbers. 53 for (float f = -100.0f; f < 0.0f; f += 0.5f) { 54 expectEqualsSP(-f, $opt$noinline$absSP(f)); 55 } 56 for (float f = 0.0f; f <= 100.0f; f += 0.5f) { 57 expectEqualsSP(f, $opt$noinline$absSP(f)); 58 } 59 for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 60 expectEqualsSP(-f, $opt$noinline$absSP(f)); 61 } 62 for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { 63 expectEqualsSP(f, $opt$noinline$absSP(f)); 64 } 65 66 // Zero 67 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f))); 68 expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f))); 69 70 // Inf. 71 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY)); 72 expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY)); 73 74 // A few NaN numbers. 75 int[] spnans = { 76 0x7f800001, 77 0x7fa00000, 78 0x7fc00000, 79 0x7fffffff, 80 0xff800001, 81 0xffa00000, 82 0xffc00000, 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("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 throw new Error("Expected: 0x" + Integer.toHexString(expected) 146 + ", found: 0x" + Integer.toHexString(result)); 147 } 148 } 149 expectEquals64(long expected, long result)150 private static void expectEquals64(long expected, long result) { 151 if (expected != result) { 152 throw new Error("Expected: 0x" + Long.toHexString(expected) 153 + ", found: 0x" + Long.toHexString(result)); 154 } 155 } 156 157 // We allow that an expected NaN result has become quiet. expectEqualsNaN64(long expected, long result)158 private static void expectEqualsNaN64(long expected, long result) { 159 if (expected != result && (expected | DPQUIET) != result) { 160 throw new Error("Expected: 0x" + Long.toHexString(expected) 161 + ", found: 0x" + Long.toHexString(result)); 162 } 163 } 164 expectEqualsSP(float expected, float result)165 private static void expectEqualsSP(float expected, float result) { 166 if (expected != result) { 167 throw new Error("Expected: " + expected + ", found: " + result); 168 } 169 } 170 expectEqualsDP(double expected, double result)171 private static void expectEqualsDP(double expected, double result) { 172 if (expected != result) { 173 throw new Error("Expected: " + expected + ", found: " + result); 174 } 175 } 176 } 177