You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2011/01/24 18:33:33 UTC
svn commit: r1062893 -
/commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java
Author: sebb
Date: Mon Jan 24 17:33:33 2011
New Revision: 1062893
URL: http://svn.apache.org/viewvc?rev=1062893&view=rev
Log:
Check all FastMath methods against StrictMath results
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java (with props)
Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java?rev=1062893&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java Mon Jan 24 17:33:33 2011
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.commons.math.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Test to compare FastMath results against StrictMath results for boundary values.
+ */
+@RunWith(Parameterized.class)
+public class FastMathStrictComparisonTest {
+
+ // Values which often need special handling
+ private static final Double[] DOUBLE_SPECIAL_VALUES = {
+ -0.0, +0.0, // 1,2
+ Double.NaN, // 3
+ Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, // 4,5
+ -Double.MAX_VALUE, Double.MAX_VALUE, // 6,7
+ // decreasing order of absolute value to help catch first failure
+ -MathUtils.EPSILON, MathUtils.EPSILON, // 8,9
+ -MathUtils.SAFE_MIN, MathUtils.SAFE_MIN, // 10,11
+ -Double.MIN_VALUE, Double.MIN_VALUE, // 12,13
+ };
+
+ private static final Float [] FLOAT_SPECIAL_VALUES = {
+ -0.0f, +0.0f, // 1,2
+ Float.NaN, // 3
+ Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, // 4,5
+ Float.MIN_VALUE, Float.MAX_VALUE, // 6,7
+ -Float.MIN_VALUE, -Float.MAX_VALUE, // 8,9
+ };
+
+ private static final Object [] LONG_SPECIAL_VALUES = {
+ -1,0,1,
+ Long.MIN_VALUE, Long.MAX_VALUE,
+ };
+
+ private static final Object[] INT_SPECIAL_VALUES = {
+ -1,0,1,
+ Integer.MIN_VALUE, Integer.MAX_VALUE,
+ };
+
+ private final Method mathMethod;
+ private final Method fastMethod;
+ private final Type[] types;
+ private final Object[][] valueArrays;
+
+ public FastMathStrictComparisonTest(Method m, Method f, Type[] types, Object[][] data) throws Exception{
+ this.mathMethod=m;
+ this.fastMethod=f;
+ this.types=types;
+ this.valueArrays=data;
+ }
+
+ @Test
+ public void test1() throws Exception{
+ setupMethodCall(mathMethod, fastMethod, types, valueArrays);
+ }
+ private static boolean isNumber(Double d) {
+ return !(d.isInfinite() || d.isNaN());
+ }
+
+ private static boolean isNumber(Float f) {
+ return !(f.isInfinite() || f.isNaN());
+ }
+
+ private static void reportFailedResults(Method mathMethod, Object[] params, Object expected, Object actual, int[] entries){
+ String format = null;
+ long actL=0;
+ long expL=0;
+ if (expected instanceof Double) {
+ Double exp = (Double) expected;
+ Double act = (Double) actual;
+ if (isNumber(exp) && isNumber(act)) { // show difference as hex
+ actL = Double.doubleToLongBits(act);
+ expL = Double.doubleToLongBits(exp);
+ format = "%016x";
+ }
+ } else if (expected instanceof Float ){
+ Float exp = (Float) expected;
+ Float act = (Float) actual;
+ if (isNumber(exp) && isNumber(act)) { // show difference as hex
+ actL = Float.floatToIntBits(act);
+ expL = Float.floatToIntBits(exp);
+ format = "%08x";
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append(mathMethod.getReturnType().getSimpleName());
+ sb.append(" ");
+ sb.append(mathMethod.getName());
+ sb.append("(");
+ String sep = "";
+ for(Object o : params){
+ sb.append(sep);
+ sb.append(o);
+ sep=", ";
+ }
+ sb.append(") expected ");
+ if (format != null){
+ sb.append(String.format(format, expL));
+ } else {
+ sb.append(expected);
+ }
+ sb.append(" actual ");
+ if (format != null){
+ sb.append(String.format(format, actL));
+ } else {
+ sb.append(actual);
+ }
+ sb.append(" entries ");
+ sb.append(Arrays.toString(entries));
+ String message = sb.toString();
+ final boolean fatal = false;
+ if (fatal) {
+ Assert.fail(message);
+ } else {
+ System.out.println(message);
+ }
+ }
+
+ private static void callMethods(Method mathMethod, Method fastMethod,
+ Object[] params, int[] entries) throws IllegalAccessException,
+ InvocationTargetException {
+ try {
+ Object expected = mathMethod.invoke(mathMethod, params);
+ Object actual = fastMethod.invoke(mathMethod, params);
+ if (!expected.equals(actual)) {
+ reportFailedResults(mathMethod, params, expected, actual, entries);
+ }
+ } catch (IllegalArgumentException e) {
+ Assert.fail(mathMethod+" "+e);
+ }
+ }
+
+ private static void setupMethodCall(Method mathMethod, Method fastMethod,
+ Type[] types, Object[][] valueArrays) throws Exception {
+ Object[] params = new Object[types.length];
+ int entry1 = 0;
+ int[] entries = new int[types.length];
+ for(Object d : valueArrays[0]) {
+ entry1++;
+ params[0] = d;
+ entries[0] = entry1;
+ if (params.length > 1){
+ int entry2 = 0;
+ for(Object d1 : valueArrays[1]) {
+ entry2++;
+ params[1] = d1;
+ entries[1] = entry2;
+ callMethods(mathMethod, fastMethod, params, entries);
+ }
+ } else {
+ callMethods(mathMethod, fastMethod, params, entries);
+ }
+ }
+ }
+
+ @Parameters
+ public static List<Object[]> data() throws Exception {
+ List<Object[]> list = new ArrayList<Object[]>();
+ for(Method mathMethod : StrictMath.class.getDeclaredMethods()) {
+ method:
+ if (Modifier.isPublic(mathMethod.getModifiers())){// Only test public methods
+ Type []types = mathMethod.getGenericParameterTypes();
+ if (types.length >=1) { // Only check methods with at least one parameter
+ try {
+ // Get the corresponding FastMath method
+ Method fastMethod = FastMath.class.getDeclaredMethod(mathMethod.getName(), (Class[]) types);
+ if (Modifier.isPublic(fastMethod.getModifiers())) { // It must be public too
+ Object [][] values = new Object[types.length][];
+ int index = 0;
+ for(Type t : types) {
+ if (t.equals(double.class)){
+ values[index]=DOUBLE_SPECIAL_VALUES;
+ } else if (t.equals(float.class)) {
+ values[index]=FLOAT_SPECIAL_VALUES;
+ } else if (t.equals(long.class)) {
+ values[index]=LONG_SPECIAL_VALUES;
+ } else if (t.equals(int.class)) {
+ values[index]=INT_SPECIAL_VALUES;
+ } else {
+ System.out.println("Cannot handle class "+t+" for "+mathMethod);
+ break method;
+ }
+ index++;
+ }
+// System.out.println(fastMethod);
+ /*
+ * The current implementation runs each method as a separate test.
+ * Could be amended to run each value as a separate test
+ */
+ list.add(new Object[]{mathMethod, fastMethod, types, values});
+// setupMethodCall(mathMethod, fastMethod, params, data);
+ } else {
+ System.out.println("Cannot find public FastMath method corresponding to: "+mathMethod);
+ }
+ } catch (NoSuchMethodException e) {
+ System.out.println("Cannot find FastMath method corresponding to: "+mathMethod);
+ }
+ }
+ }
+ }
+ return list;
+ }
+
+}
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathStrictComparisonTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision