add test for isFinite



git-svn-id: http://skia.googlecode.com/svn/trunk@2800 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/ScalarTest.cpp b/tests/ScalarTest.cpp
new file mode 100644
index 0000000..2848516
--- /dev/null
+++ b/tests/ScalarTest.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+#include "SkFloatingPoint.h"
+#include "SkMath.h"
+#include "SkPoint.h"
+#include "SkRandom.h"
+
+#ifdef SK_CAN_USE_FLOAT
+
+static bool isFinite_int(float x) {
+    uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
+    int exponent = bits << 1 >> 24;
+    return exponent != 0xFF;
+}
+
+static bool isFinite_float(float x) {
+    return isfinite(x);
+}
+
+static bool isFinite_mulzero(float x) {
+    float y = x * 0;
+    return y == y;
+}
+
+// return true if the float is finite
+typedef bool (*IsFiniteProc1)(float);
+
+static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
+    return proc(x) && proc(y);
+}
+
+static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
+    return proc(x * 0 + y * 0);
+}
+
+// return true if both floats are finite
+typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
+
+#endif
+
+static void test_isfinite(skiatest::Reporter* reporter) {
+#ifdef SK_CAN_USE_FLOAT
+    struct Rec {
+        float   fValue;
+        bool    fIsFinite;
+    };
+    
+    float max = 3.402823466e+38f;
+    float inf = max * max;
+    float nan = 1 / sk_float_sin(0);
+
+    const Rec data[] = {
+        {   0,          true    },
+        {   1,          true    },
+        {  -1,          true    },
+        {  max * 0.75,  true    },
+        {  max,         true    },
+        {  -max * 0.75, true    },
+        {  -max,        true    },
+        {  inf,         false   },
+        { -inf,         false   },
+        {  nan,         false   },
+    };
+
+    const IsFiniteProc1 gProc1[] = {
+        isFinite_int,
+        isFinite_float,
+        isFinite_mulzero
+    };
+    const IsFiniteProc2 gProc2[] = {
+        isFinite2_and,
+        isFinite2_mulzeroadd
+    };
+
+    int i, n = SK_ARRAY_COUNT(data);
+
+    for (i = 0; i < n; ++i) {
+        for (int k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
+            const Rec& rec = data[i];
+            bool finite = gProc1[k](rec.fValue);
+            REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
+        }
+    }
+
+    for (i = 0; i < n; ++i) {
+        const Rec& rec0 = data[i];
+        for (int j = 0; j < n; ++j) {
+            const Rec& rec1 = data[j];
+            for (int k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
+                IsFiniteProc1 proc1 = gProc1[k];
+                
+                for (int m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
+                    bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
+                    bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
+                    REPORTER_ASSERT(reporter, finite2 == finite);
+                }
+            }
+        }
+    }
+#endif
+}
+
+static void TestScalar(skiatest::Reporter* reporter) {
+    test_isfinite(reporter);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
+