1 /*
   2  * Copyright (c) 2003, 2011 Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * Shared static test methods for numerical tests.  Sharing these
  26  * helper test methods avoids repeated functions in the various test
  27  * programs.  The test methods return 1 for a test failure and 0 for
  28  * success.  The order of arguments to the test methods is generally
  29  * the test name, followed by the test arguments, the computed result,
  30  * and finally the expected result.
  31  */
  32 
  33 import sun.misc.FpUtils;
  34 
  35 public class Tests {
  36     private Tests(){}; // do not instantiate
  37 
  38     private static String toHexString(float f) {
  39         if (!Float.isNaN(f))
  40             return Float.toHexString(f);
  41         else
  42             return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")";
  43     }
  44 
  45     private static String toHexString(double d) {
  46         if (!Double.isNaN(d))
  47             return Double.toHexString(d);
  48         else
  49             return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")";
  50     }
  51 
  52     public static int test(String testName, float input,
  53                            boolean result, boolean expected) {
  54         if (expected != result) {
  55             System.err.println("Failure for " + testName + ":\n" +
  56                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
  57                                "\texpected  " + expected + "\n"  +
  58                                "\tgot       " + result   + ").");
  59             return 1;
  60         }
  61         else
  62             return 0;
  63     }
  64 
  65     public static int test(String testName, double input,
  66                            boolean result, boolean expected) {
  67         if (expected != result) {
  68             System.err.println("Failure for " + testName + ":\n" +
  69                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
  70                                "\texpected  " + expected + "\n"  +
  71                                "\tgot       " + result   + ").");
  72             return 1;
  73         }
  74         else
  75             return 0;
  76     }
  77 
  78     public static int test(String testName, float input1, float input2,
  79                            boolean result, boolean expected) {
  80         if (expected != result) {
  81             System.err.println("Failure for "  + testName + ":\n" +
  82                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
  83                                                + input2   + "\t(" + toHexString(input2) + ")\n" +
  84                                "\texpected  "  + expected + "\n"  +
  85                                "\tgot       "  + result   + ").");
  86             return 1;
  87         }
  88         return 0;
  89     }
  90 
  91     public static int test(String testName, double input1, double input2,
  92                            boolean result, boolean expected) {
  93         if (expected != result) {
  94             System.err.println("Failure for "  + testName + ":\n" +
  95                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
  96                                                + input2   + "\t(" + toHexString(input2) + ")\n" +
  97                                "\texpected  "  + expected + "\n"  +
  98                                "\tgot       "  + result   + ").");
  99             return 1;
 100         }
 101         return 0;
 102     }
 103 
 104     public static int test(String testName, float input,
 105                            int result, int expected) {
 106         if (expected != result) {
 107             System.err.println("Failure for " + testName + ":\n" +
 108                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 109                                "\texpected  " + expected + "\n" +
 110                                "\tgot       " + result    + ").");
 111             return 1;
 112         }
 113         return 0;
 114     }
 115 
 116     public  static int test(String testName, double input,
 117                             int result, int expected) {
 118         if (expected != result) {
 119             System.err.println("Failure for " + testName + ":\n" +
 120                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 121                                "\texpected  " + expected + "\n"  +
 122                                "\tgot       " + result   + ").");
 123             return 1;
 124         }
 125         else
 126             return 0;
 127     }
 128 
 129     public static int test(String testName, float input,
 130                            float result, float expected) {
 131         if (Float.compare(expected, result) != 0 ) {
 132             System.err.println("Failure for " + testName + ":\n" +
 133                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 134                                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
 135                                "\tgot       " + result   + "\t(" + toHexString(result) + ").");
 136             return 1;
 137         }
 138         else
 139             return 0;
 140     }
 141 
 142 
 143     public static int test(String testName, double input,
 144                            double result, double expected) {
 145         if (Double.compare(expected, result ) != 0) {
 146             System.err.println("Failure for " + testName + ":\n" +
 147                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 148                                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
 149                                "\tgot       " + result   + "\t(" + toHexString(result) + ").");
 150             return 1;
 151         }
 152         else
 153             return 0;
 154     }
 155 
 156     public static int test(String testName,
 157                            float input1, double input2,
 158                            float result, float expected) {
 159         if (Float.compare(expected, result ) != 0) {
 160             System.err.println("Failure for "  + testName + ":\n" +
 161                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
 162                                                + input2   + "\t(" + toHexString(input2) + ")\n" +
 163                                "\texpected  "  + expected + "\t(" + toHexString(expected) + ")\n" +
 164                                "\tgot       "  + result   + "\t(" + toHexString(result) + ").");
 165             return 1;
 166         }
 167         else
 168             return 0;
 169     }
 170 
 171     public static int test(String testName,
 172                            double input1, double input2,
 173                            double result, double expected) {
 174         if (Double.compare(expected, result ) != 0) {
 175             System.err.println("Failure for "  + testName + ":\n" +
 176                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
 177                                                + input2   + "\t(" + toHexString(input2) + ")\n" +
 178                                "\texpected  "  + expected + "\t(" + toHexString(expected) + ")\n" +
 179                                "\tgot       "  + result   + "\t(" + toHexString(result) + ").");
 180             return 1;
 181         }
 182         else
 183             return 0;
 184     }
 185 
 186     public static int test(String testName,
 187                            float input1, int input2,
 188                            float result, float expected) {
 189         if (Float.compare(expected, result ) != 0) {
 190             System.err.println("Failure for "  + testName + ":\n" +
 191                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
 192                                                + input2   + "\n"  +
 193                                "\texpected  "  + expected + "\t(" + toHexString(expected) + ")\n" +
 194                                "\tgot       "  + result   + "\t(" + toHexString(result) + ").");
 195             return 1;
 196         }
 197         else
 198             return 0;
 199     }
 200 
 201     public static int test(String testName,
 202                            double input1, int input2,
 203                            double result, double expected) {
 204         if (Double.compare(expected, result ) != 0) {
 205             System.err.println("Failure for "  + testName + ":\n" +
 206                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
 207                                                + input2   + "\n"  +
 208                                "\texpected  "  + expected + "\t(" + toHexString(expected) + ")\n" +
 209                                "\tgot       "  + result   + "\t(" + toHexString(result) + ").");
 210             return 1;
 211         }
 212         else
 213             return 0;
 214     }
 215 
 216     static int testUlpCore(double result, double expected, double ulps) {
 217         // We assume we won't be unlucky and have an inexact expected
 218         // be nextDown(2^i) when 2^i would be the correctly rounded
 219         // answer.  This would cause the ulp size to be half as large
 220         // as it should be, doubling the measured error).
 221 
 222         if (Double.compare(expected, result) == 0) {
 223             return 0;   // result and expected are equivalent
 224         } else {
 225             if( ulps == 0.0) {
 226                 // Equivalent results required but not found
 227                 return 1;
 228             } else {
 229                 double difference = expected - result;
 230                 if (FpUtils.isUnordered(expected, result) ||
 231                     Double.isNaN(difference) ||
 232                     // fail if greater than or unordered
 233                     !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) {
 234                     return 1;
 235                 }
 236                 else
 237                     return 0;
 238             }
 239         }
 240     }
 241 
 242     // One input argument.
 243     public static int testUlpDiff(String testName, double input,
 244                                   double result, double expected, double ulps) {
 245         int code = testUlpCore(result, expected, ulps);
 246         if (code == 1) {
 247             System.err.println("Failure for " + testName + ":\n" +
 248                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 249                                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
 250                                "\tgot       " + result   + "\t(" + toHexString(result) + ");\n" +
 251                                "\tdifference greater than ulp tolerance " + ulps);
 252         }
 253         return code;
 254     }
 255 
 256     // Two input arguments.
 257     public static int testUlpDiff(String testName, double input1, double input2,
 258                                   double result, double expected, double ulps) {
 259         int code = testUlpCore(result, expected, ulps);
 260         if (code == 1) {
 261             System.err.println("Failure for "  + testName + ":\n" +
 262                                "\tFor inputs " + input1   + "\t(" + toHexString(input1) + ") and "
 263                                                + input2   + "\t(" + toHexString(input2) + ")\n" +
 264                                "\texpected  "  + expected + "\t(" + toHexString(expected) + ")\n" +
 265                                "\tgot       "  + result   + "\t(" + toHexString(result) + ");\n" +
 266                                "\tdifference greater than ulp tolerance " + ulps);
 267         }
 268         return code;
 269     }
 270 
 271     // For a successful test, the result must be within the ulp bound of
 272     // expected AND the result must have absolute value less than or
 273     // equal to absBound.
 274     public static int testUlpDiffWithAbsBound(String testName, double input,
 275                                               double result, double expected,
 276                                               double ulps, double absBound) {
 277         int code = 0;   // return code value
 278 
 279         if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) &&
 280             !Double.isNaN(expected)) {
 281             code = 1;
 282         } else
 283             code = testUlpCore(result, expected, ulps);
 284 
 285         if (code == 1) {
 286             System.err.println("Failure for " + testName + ":\n" +
 287                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 288                                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
 289                                "\tgot       " + result   + "\t(" + toHexString(result) + ");\n" +
 290                                "\tdifference greater than ulp tolerance " + ulps +
 291                                " or the result has larger magnitude than " + absBound);
 292         }
 293         return code;
 294     }
 295 
 296     // For a successful test, the result must be within the ulp bound of
 297     // expected AND the result must have absolute value greater than
 298     // or equal to the lowerBound.
 299     public static int testUlpDiffWithLowerBound(String testName, double input,
 300                                                 double result, double expected,
 301                                                 double ulps, double lowerBound) {
 302         int code = 0;   // return code value
 303 
 304         if (!(result >= lowerBound) && !Double.isNaN(expected)) {
 305             code = 1;
 306         } else
 307             code = testUlpCore(result, expected, ulps);
 308 
 309         if (code == 1) {
 310             System.err.println("Failure for " + testName +
 311                                ":\n" +
 312                                "\tFor input "   + input    + "\t(" + toHexString(input) + ")" +
 313                                "\n\texpected  " + expected + "\t(" + toHexString(expected) + ")" +
 314                                "\n\tgot       " + result   + "\t(" + toHexString(result) + ");" +
 315                                "\ndifference greater than ulp tolerance " + ulps +
 316                                " or result not greater than or equal to the bound " + lowerBound);
 317         }
 318         return code;
 319     }
 320 
 321     public static int testTolerance(String testName, double input,
 322                                     double result, double expected, double tolerance) {
 323         if (Double.compare(expected, result ) != 0) {
 324             double difference = expected - result;
 325             if (FpUtils.isUnordered(expected, result) ||
 326                 Double.isNaN(difference) ||
 327                 // fail if greater than or unordered
 328                 !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) {
 329                 System.err.println("Failure for " + testName + ":\n" +
 330                                    "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 331                                    "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
 332                                    "\tgot       " + result   + "\t(" + toHexString(result) + ");\n" +
 333                                    "\tdifference greater than tolerance 10^-" + tolerance);
 334                 return 1;
 335             }
 336             return 0;
 337         }
 338         else
 339             return 0;
 340     }
 341 
 342     // For a successful test, the result must be within the upper and
 343     // lower bounds.
 344     public static int testBounds(String testName, double input, double result,
 345                                  double bound1, double bound2) {
 346         if ((result >= bound1 && result <= bound2) ||
 347             (result <= bound1 && result >= bound2))
 348             return 0;
 349         else {
 350             double lowerBound = Math.min(bound1, bound2);
 351             double upperBound = Math.max(bound1, bound2);
 352             System.err.println("Failure for " + testName + ":\n" +
 353                                "\tFor input " + input    + "\t(" + toHexString(input) + ")\n" +
 354                                "\tgot       " + result   + "\t(" + toHexString(result) + ");\n" +
 355                                "\toutside of range\n" +
 356                                "\t[" + lowerBound    + "\t(" + toHexString(lowerBound) + "), " +
 357                                upperBound    + "\t(" + toHexString(upperBound) + ")]");
 358             return 1;
 359         }
 360     }
 361 }