From b67877704edf8a32e71ce825d7ab4703be39f8ce Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Mon, 19 Dec 2016 13:57:31 -0800 Subject: [PATCH] Tests on FP Math.abs() Rationale: As a "quality of implementation" rather than pure "spec compliance" we require that Math.abs() clears the sign bit (but changes nothing else) for all numbers, including NaN. These tests ensure that remains the case. **NOTE** This CL depends on the pending libcore change (https://android-review.googlesource.com/#/c/316368/). Test: test-art-host Bug: 30758343 Change-Id: I01044a73992b2e89d97060ed8bbb76abea0933b9 --- test/631-checker-fp-abs/expected.txt | 1 + test/631-checker-fp-abs/info.txt | 1 + test/631-checker-fp-abs/src/Main.java | 163 ++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 test/631-checker-fp-abs/expected.txt create mode 100644 test/631-checker-fp-abs/info.txt create mode 100644 test/631-checker-fp-abs/src/Main.java diff --git a/test/631-checker-fp-abs/expected.txt b/test/631-checker-fp-abs/expected.txt new file mode 100644 index 000000000..b0aad4deb --- /dev/null +++ b/test/631-checker-fp-abs/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/631-checker-fp-abs/info.txt b/test/631-checker-fp-abs/info.txt new file mode 100644 index 000000000..0a1499e72 --- /dev/null +++ b/test/631-checker-fp-abs/info.txt @@ -0,0 +1 @@ +Tests on floating-point Math.abs. diff --git a/test/631-checker-fp-abs/src/Main.java b/test/631-checker-fp-abs/src/Main.java new file mode 100644 index 000000000..eef52965c --- /dev/null +++ b/test/631-checker-fp-abs/src/Main.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A few tests of Math.abs for floating-point data. + */ +public class Main { + + public static boolean doThrow = false; + + /// CHECK-START: float Main.$opt$noinline$absSP(float) intrinsics_recognition (after) + /// CHECK-DAG: <> InvokeStaticOrDirect intrinsic:MathAbsFloat + /// CHECK-DAG: Return [<>] + private static float $opt$noinline$absSP(float f) { + if (doThrow) { + throw new Error("Something to prevent inlining"); + } + return Math.abs(f); + } + + /// CHECK-START: double Main.$opt$noinline$absDP(double) intrinsics_recognition (after) + /// CHECK-DAG: <> InvokeStaticOrDirect intrinsic:MathAbsDouble + /// CHECK-DAG: Return [<>] + private static double $opt$noinline$absDP(double d) { + if (doThrow) { + throw new Error("Something to prevent inlining"); + } + return Math.abs(d); + } + + public static void main(String args[]) { + // A few obvious numbers. + for (float f = -100.0f; f < 0.0f; f += 0.5f) { + expectEqualsSP(-f, $opt$noinline$absSP(f)); + } + for (float f = 0.0f; f <= 100.0f; f += 0.5f) { + expectEqualsSP(f, $opt$noinline$absSP(f)); + } + for (float f = -1.5f; f <= -1.499f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { + expectEqualsSP(-f, $opt$noinline$absSP(f)); + } + for (float f = 1.499f; f <= 1.5f; f = Math.nextAfter(f, Float.POSITIVE_INFINITY)) { + expectEqualsSP(f, $opt$noinline$absSP(f)); + } + + // Zero + expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(+0.0f))); + expectEquals32(0, Float.floatToRawIntBits($opt$noinline$absSP(-0.0f))); + + // Inf. + expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.NEGATIVE_INFINITY)); + expectEqualsSP(Float.POSITIVE_INFINITY, $opt$noinline$absSP(Float.POSITIVE_INFINITY)); + + // A few NaN numbers. + // + // Note, as a "quality of implementation" rather than pure "spec compliance" we require that + // Math.abs() clears the sign bit (but nothing else) for all NaN numbers. This requirement + // should hold regardless of whether Art uses the interpreter, library, or compiler. + // + int[] spnans = { + 0x7f800001, + 0x7fa00000, + 0x7fc00000, + 0x7fffffff, + 0xff800001, + 0xffa00000, + 0xffc00000, + 0xffffffff + }; + for (int i = 0; i < spnans.length; i++) { + float f = Float.intBitsToFloat(spnans[i]); + expectEquals32( + spnans[i] & Integer.MAX_VALUE, + Float.floatToRawIntBits($opt$noinline$absSP(f))); + } + + // A few obvious numbers. + for (double d = -100.0; d < 0.0; d += 0.5) { + expectEqualsDP(-d, $opt$noinline$absDP(d)); + } + for (double d = 0.0; d <= 100.0; d += 0.5) { + expectEqualsDP(d, $opt$noinline$absDP(d)); + } + for (double d = -1.5d; d <= -1.49999999999d; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { + expectEqualsDP(-d, $opt$noinline$absDP(d)); + } + for (double d = 1.49999999999d; d <= 1.5; d = Math.nextAfter(d, Double.POSITIVE_INFINITY)) { + expectEqualsDP(d, $opt$noinline$absDP(d)); + } + + // Zero + expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(+0.0f))); + expectEquals64(0L, Double.doubleToRawLongBits($opt$noinline$absDP(-0.0f))); + + // Inf. + expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.NEGATIVE_INFINITY)); + expectEqualsDP(Double.POSITIVE_INFINITY, $opt$noinline$absDP(Double.POSITIVE_INFINITY)); + + // A few NaN numbers. + // + // Note, as a "quality of implementation" rather than pure "spec compliance" we require that + // Math.abs() clears the sign bit (but nothing else) for all NaN numbers. This requirement + // should hold regardless of whether Art uses the interpreter, library, or compiler. + // + long[] dpnans = { + 0x7ff0000000000001L, + 0x7ff4000000000000L, + 0x7ff8000000000000L, + 0x7fffffffffffffffL, + 0xfff0000000000001L, + 0xfff4000000000000L, + 0xfff8000000000000L, + 0xffffffffffffffffL + }; + for (int i = 0; i < dpnans.length; i++) { + double d = Double.longBitsToDouble(dpnans[i]); + expectEquals64( + dpnans[i] & Long.MAX_VALUE, + Double.doubleToRawLongBits($opt$noinline$absDP(d))); + } + + System.out.println("passed"); + } + + private static void expectEquals32(int expected, int result) { + if (expected != result) { + throw new Error("Expected: 0x" + Integer.toHexString(expected) + + ", found: 0x" + Integer.toHexString(result)); + } + } + + private static void expectEquals64(long expected, long result) { + if (expected != result) { + throw new Error("Expected: 0x" + Long.toHexString(expected) + + ", found: 0x" + Long.toHexString(result)); + } + } + + private static void expectEqualsSP(float expected, float result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEqualsDP(double expected, double result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} -- 2.11.0