more tests (need more meat in there)



git-svn-id: http://skia.googlecode.com/svn/trunk@97 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/Sk64Test.cpp b/tests/Sk64Test.cpp
new file mode 100644
index 0000000..1829c64
--- /dev/null
+++ b/tests/Sk64Test.cpp
@@ -0,0 +1,200 @@
+#include "Test.h"
+#include "SkRandom.h"
+#include <math.h>
+
+#ifdef SK_SUPPORT_UNITTEST
+struct BoolTable {
+    int8_t  zero, pos, neg, toBool, sign;
+};
+
+static void bool_table_test(skiatest::Reporter* reporter,
+                            const Sk64& a, const BoolTable& table)
+{
+    REPORTER_ASSERT(reporter, a.isZero() != a.nonZero());
+
+    REPORTER_ASSERT(reporter, !a.isZero() == !table.zero);
+    REPORTER_ASSERT(reporter, !a.isPos() == !table.pos);
+    REPORTER_ASSERT(reporter, !a.isNeg() == !table.neg);
+    REPORTER_ASSERT(reporter, a.getSign() == table.sign);
+}
+
+#ifdef SkLONGLONG
+    static SkLONGLONG asLL(const Sk64& a)
+    {
+        return ((SkLONGLONG)a.fHi << 32) | a.fLo;
+    }
+#endif
+#endif
+
+static void TestSk64(skiatest::Reporter* reporter) {
+    enum BoolTests {
+        kZero_BoolTest,
+        kPos_BoolTest,
+        kNeg_BoolTest
+    };
+    static const BoolTable gBoolTable[] = {
+        { 1, 0, 0, 0, 0 },
+        { 0, 1, 0, 1, 1 },
+        { 0, 0, 1, 1, -1 }
+    };
+
+    Sk64    a, b, c;
+
+    a.fHi = a.fLo = 0;
+    b.set(0);
+    c.setZero();
+    REPORTER_ASSERT(reporter, a == b);
+    REPORTER_ASSERT(reporter, a == c);
+    bool_table_test(reporter, a, gBoolTable[kZero_BoolTest]);
+
+    a.fHi = 0;  a.fLo = 5;
+    b.set(5);
+    REPORTER_ASSERT(reporter, a == b);
+    REPORTER_ASSERT(reporter, a.is32() && a.get32() == 5 && !a.is64());
+    bool_table_test(reporter, a, gBoolTable[kPos_BoolTest]);
+
+    a.fHi = -1; a.fLo = (uint32_t)-5;
+    b.set(-5);
+    REPORTER_ASSERT(reporter, a == b);
+    REPORTER_ASSERT(reporter, a.is32() && a.get32() == -5 && !a.is64());
+    bool_table_test(reporter, a, gBoolTable[kNeg_BoolTest]);
+
+    a.setZero();
+    b.set(6);
+    c.set(-6);
+    REPORTER_ASSERT(reporter, a != b && b != c && a != c);
+    REPORTER_ASSERT(reporter, !(a == b) && !(a == b) && !(a == b));
+    REPORTER_ASSERT(reporter, a < b && b > a && a <= b && b >= a);
+    REPORTER_ASSERT(reporter, c < a && a > c && c <= a && a >= c);
+    REPORTER_ASSERT(reporter, c < b && b > c && c <= b && b >= c);
+
+    // Now test add/sub
+
+    SkRandom    rand;
+    int         i;
+
+    for (i = 0; i < 1000; i++)
+    {
+        int aa = rand.nextS() >> 1;
+        int bb = rand.nextS() >> 1;
+        a.set(aa);
+        b.set(bb);
+        REPORTER_ASSERT(reporter, a.get32() == aa && b.get32() == bb);
+        c = a; c.add(bb);
+        REPORTER_ASSERT(reporter, c.get32() == aa + bb);
+        c = a; c.add(-bb);
+        REPORTER_ASSERT(reporter, c.get32() == aa - bb);
+        c = a; c.add(b);
+        REPORTER_ASSERT(reporter, c.get32() == aa + bb);
+        c = a; c.sub(b);
+        REPORTER_ASSERT(reporter, c.get32() == aa - bb);
+    }
+
+#ifdef SkLONGLONG
+    for (i = 0; i < 1000; i++)
+    {
+        rand.next64(&a); //a.fHi >>= 1; // avoid overflow
+        rand.next64(&b); //b.fHi >>= 1; // avoid overflow
+
+        if (!(i & 3))   // want to explicitly test these cases
+        {
+            a.fLo = 0;
+            b.fLo = 0;
+        }
+        else if (!(i & 7))  // want to explicitly test these cases
+        {
+            a.fHi = 0;
+            b.fHi = 0;
+        }
+
+        SkLONGLONG aa = asLL(a);
+        SkLONGLONG bb = asLL(b);
+
+        REPORTER_ASSERT(reporter, (a < b) == (aa < bb));
+        REPORTER_ASSERT(reporter, (a <= b) == (aa <= bb));
+        REPORTER_ASSERT(reporter, (a > b) == (aa > bb));
+        REPORTER_ASSERT(reporter, (a >= b) == (aa >= bb));
+        REPORTER_ASSERT(reporter, (a == b) == (aa == bb));
+        REPORTER_ASSERT(reporter, (a != b) == (aa != bb));
+
+        c = a; c.add(b);
+        REPORTER_ASSERT(reporter, asLL(c) == aa + bb);
+        c = a; c.sub(b);
+        REPORTER_ASSERT(reporter, asLL(c) == aa - bb);
+        c = a; c.rsub(b);
+        REPORTER_ASSERT(reporter, asLL(c) == bb - aa);
+        c = a; c.negate();
+        REPORTER_ASSERT(reporter, asLL(c) == -aa);
+
+        int bits = rand.nextU() & 63;
+        c = a; c.shiftLeft(bits);
+        REPORTER_ASSERT(reporter, asLL(c) == (aa << bits));
+        c = a; c.shiftRight(bits);
+        REPORTER_ASSERT(reporter, asLL(c) == (aa >> bits));
+        c = a; c.roundRight(bits);
+
+        SkLONGLONG tmp;
+
+        tmp = aa;
+        if (bits > 0)
+            tmp += (SkLONGLONG)1 << (bits - 1);
+        REPORTER_ASSERT(reporter, asLL(c) == (tmp >> bits));
+
+        c.setMul(a.fHi, b.fHi);
+        tmp = (SkLONGLONG)a.fHi * b.fHi;
+        REPORTER_ASSERT(reporter, asLL(c) == tmp);
+    }
+
+
+    for (i = 0; i < 100000; i++)
+    {
+        Sk64    wide;
+        int32_t denom = rand.nextS();
+
+        while (denom == 0)
+            denom = rand.nextS();
+        wide.setMul(rand.nextS(), rand.nextS());
+        SkLONGLONG check = wide.getLongLong();
+
+        wide.div(denom, Sk64::kTrunc_DivOption);
+        check /= denom;
+        SkLONGLONG w = wide.getLongLong();
+
+        REPORTER_ASSERT(reporter, check == w);
+
+#ifdef SK_CAN_USE_FLOAT
+        wide.setMul(rand.nextS(), rand.nextS());
+        wide.abs();
+        denom = wide.getSqrt();
+        int32_t ck = (int32_t)sqrt((double)wide.getLongLong());
+        int diff = denom - ck;
+        REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1);
+
+        wide.setMul(rand.nextS(), rand.nextS());
+        Sk64    dwide;
+        dwide.setMul(rand.nextS(), rand.nextS());
+        SkFixed fixdiv = wide.getFixedDiv(dwide);
+        double dnumer = (double)wide.getLongLong();
+        double ddenom = (double)dwide.getLongLong();
+        double ddiv = dnumer / ddenom;
+        SkFixed dfixdiv;
+        if (ddiv >= (double)SK_MaxS32 / (double)SK_Fixed1)
+            dfixdiv = SK_MaxS32;
+        else if (ddiv <= -(double)SK_MaxS32 / (double)SK_Fixed1)
+            dfixdiv = SK_MinS32;
+        else
+            dfixdiv = SkFloatToFixed(dnumer / ddenom);
+        diff = fixdiv - dfixdiv;
+        
+        if (SkAbs32(diff) > 1) {
+            SkDebugf(" %d === numer %g denom %g div %g xdiv %x fxdiv %x\n",
+                     i, dnumer, ddenom, ddiv, dfixdiv, fixdiv);
+        }
+        REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1);
+#endif
+    }
+#endif
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64)