Home | History | Annotate | Download | only in src
      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>>]
     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>>]
     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 
     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 
    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.
    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 
    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.
    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 
    165   private static void expectEqualsSP(float expected, float result) {
    166     if (expected != result) {
    167       throw new Error("Expected: " + expected + ", found: " + result);
    168     }
    169   }
    170 
    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