Revert r10705 (ARM Skia NEON patches - 04 - Clean SkFixed / SkLONGLONG) due to 1000+ linux_layout failures (http://build.chromium.org/p/tryserver.chromium/builders/linux_layout_rel/builds/18997/steps/webkit_tests/logs/stdio)



git-svn-id: http://skia.googlecode.com/svn/trunk@10729 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h
index e78205d..236a99a 100644
--- a/include/config/SkUserConfig.h
+++ b/include/config/SkUserConfig.h
@@ -103,6 +103,13 @@
 //#define SK_UINT8_BITFIELD_BENDIAN
 //#define SK_UINT8_BITFIELD_LENDIAN
 
+
+/*  Some compilers don't support long long for 64bit integers. If yours does
+    not, define this to the appropriate type.
+ */
+//#define SkLONGLONG int64_t
+
+
 /*  To write debug messages to a console, skia will call SkDebugf(...) following
     printf conventions (e.g. const char* format, ...). If you want to redirect
     this to something other than printf, define yours here
diff --git a/include/core/Sk64.h b/include/core/Sk64.h
index 47ec15e..6db3001 100644
--- a/include/core/Sk64.h
+++ b/include/core/Sk64.h
@@ -221,6 +221,10 @@
     friend bool operator>=(const Sk64& a, const Sk64& b) {
         return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo >= b.fLo);
     }
+
+#ifdef SkLONGLONG
+    SkLONGLONG getLongLong() const;
+#endif
 };
 
 #endif
diff --git a/include/core/SkFixed.h b/include/core/SkFixed.h
index a4a515d..acfbe9a 100644
--- a/include/core/SkFixed.h
+++ b/include/core/SkFixed.h
@@ -120,6 +120,20 @@
 #define SkFixedAbs(x)       SkAbs32(x)
 #define SkFixedAve(a, b)    (((a) + (b)) >> 1)
 
+SkFixed SkFixedMul_portable(SkFixed, SkFixed);
+SkFract SkFractMul_portable(SkFract, SkFract);
+inline SkFixed SkFixedSquare_portable(SkFixed value)
+{
+    uint32_t a = SkAbs32(value);
+    uint32_t ah = a >> 16;
+    uint32_t al = a & 0xFFFF;
+    SkFixed result = ah * a + al * ah + (al * al >> 16);
+    if (result >= 0)
+        return result;
+    else // Overflow.
+        return SK_FixedMax;
+}
+
 #define SkFixedDiv(numer, denom)    SkDivBits(numer, denom, 16)
 SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
 SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
@@ -155,28 +169,27 @@
     return SkAbs32(x) < tolerance;
 }
 
-inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
-{
-    return (SkFixed)((int64_t)a * b >> 16);
-}
-
-inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
-{
-    return (SkFract)((int64_t)a * b >> 30);
-}
-
-inline SkFixed SkFixedSquare_longlong(SkFixed value)
-{
-    return (SkFixed)((int64_t)value * value >> 16);
-}
-
-#define SkFixedMul(a,b)     SkFixedMul_longlong(a,b)
-#define SkFractMul(a,b)     SkFractMul_longlong(a,b)
-#define SkFixedSquare(a)    SkFixedSquare_longlong(a)
-
 //////////////////////////////////////////////////////////////////////////////////////////////////////
 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
 
+#ifdef SkLONGLONG
+    inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
+    {
+        return (SkFixed)((SkLONGLONG)a * b >> 16);
+    }
+    inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
+    {
+        return (SkFract)((SkLONGLONG)a * b >> 30);
+    }
+    inline SkFixed SkFixedSquare_longlong(SkFixed value)
+    {
+        return (SkFixed)((SkLONGLONG)value * value >> 16);
+    }
+    #define SkFixedMul(a,b)     SkFixedMul_longlong(a,b)
+    #define SkFractMul(a,b)     SkFractMul_longlong(a,b)
+    #define SkFixedSquare(a)    SkFixedSquare_longlong(a)
+#endif
+
 #if defined(SK_CPU_ARM)
     /* This guy does not handle NaN or other obscurities, but is faster than
        than (int)(x*65536)
@@ -249,6 +262,12 @@
 #ifndef SkFixedSquare
     #define SkFixedSquare(x)    SkFixedSquare_portable(x)
 #endif
+#ifndef SkFixedMul
+    #define SkFixedMul(x, y)    SkFixedMul_portable(x, y)
+#endif
+#ifndef SkFractMul
+    #define SkFractMul(x, y)    SkFractMul_portable(x, y)
+#endif
 #ifndef SkFixedMulAdd
     #define SkFixedMulAdd(x, y, a)  (SkFixedMul(x, y) + (a))
 #endif
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
index e992f42..4a819d3 100644
--- a/include/core/SkPostConfig.h
+++ b/include/core/SkPostConfig.h
@@ -269,6 +269,17 @@
 
 //////////////////////////////////////////////////////////////////////
 
+#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC)
+    #ifndef SkLONGLONG
+        #ifdef SK_BUILD_FOR_WIN32
+            #define SkLONGLONG  __int64
+        #else
+            #define SkLONGLONG  long long
+        #endif
+    #endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////
 #ifndef SK_BUILD_FOR_WINCE
 #include <string.h>
 #include <stdlib.h>
diff --git a/src/core/Sk64.cpp b/src/core/Sk64.cpp
index 2061ebb..7c195ce 100644
--- a/src/core/Sk64.cpp
+++ b/src/core/Sk64.cpp
@@ -299,6 +299,15 @@
     return root;
 }
 
+#ifdef SkLONGLONG
+    SkLONGLONG Sk64::getLongLong() const
+    {
+        SkLONGLONG value = fHi;
+        value <<= 32;
+        return value | fLo;
+    }
+#endif
+
 SkFixed Sk64::getFixedDiv(const Sk64& denom) const
 {
     Sk64    N = *this;
diff --git a/src/core/SkMath.cpp b/src/core/SkMath.cpp
index 6c6c6d5..2693e5c 100644
--- a/src/core/SkMath.cpp
+++ b/src/core/SkMath.cpp
@@ -105,6 +105,71 @@
     }
 }
 
+SkFixed SkFixedMul_portable(SkFixed a, SkFixed b) {
+#if 0
+    Sk64    tmp;
+
+    tmp.setMul(a, b);
+    tmp.shiftRight(16);
+    return tmp.fLo;
+#elif defined(SkLONGLONG)
+    return static_cast<SkFixed>((SkLONGLONG)a * b >> 16);
+#else
+    int sa = SkExtractSign(a);
+    int sb = SkExtractSign(b);
+    // now make them positive
+    a = SkApplySign(a, sa);
+    b = SkApplySign(b, sb);
+
+    uint32_t    ah = a >> 16;
+    uint32_t    al = a & 0xFFFF;
+    uint32_t bh = b >> 16;
+    uint32_t bl = b & 0xFFFF;
+
+    uint32_t R = ah * b + al * bh + (al * bl >> 16);
+
+    return SkApplySign(R, sa ^ sb);
+#endif
+}
+
+SkFract SkFractMul_portable(SkFract a, SkFract b) {
+#if 0
+    Sk64 tmp;
+    tmp.setMul(a, b);
+    return tmp.getFract();
+#elif defined(SkLONGLONG)
+    return static_cast<SkFract>((SkLONGLONG)a * b >> 30);
+#else
+    int sa = SkExtractSign(a);
+    int sb = SkExtractSign(b);
+    // now make them positive
+    a = SkApplySign(a, sa);
+    b = SkApplySign(b, sb);
+
+    uint32_t ah = a >> 16;
+    uint32_t al = a & 0xFFFF;
+    uint32_t bh = b >> 16;
+    uint32_t bl = b & 0xFFFF;
+
+    uint32_t A = ah * bh;
+    uint32_t B = ah * bl + al * bh;
+    uint32_t C = al * bl;
+
+    /*  [  A  ]
+           [  B  ]
+              [  C  ]
+    */
+    uint32_t Lo = C + (B << 16);
+    uint32_t Hi = A + (B >>16) + (Lo < C);
+
+    SkASSERT((Hi >> 29) == 0);  // else overflow
+
+    int32_t R = (Hi << 2) + (Lo >> 30);
+
+    return SkApplySign(R, sa ^ sb);
+#endif
+}
+
 int SkFixedMulCommon(SkFixed a, int b, int bias) {
     // this function only works if b is 16bits
     SkASSERT(b == (int16_t)b);
diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp
index f984919..fe54594 100644
--- a/tests/MathTest.cpp
+++ b/tests/MathTest.cpp
@@ -186,6 +186,7 @@
     }
 }
 
+#if defined(SkLONGLONG)
 static int symmetric_fixmul(int a, int b) {
     int sa = SkExtractSign(a);
     int sb = SkExtractSign(b);
@@ -194,17 +195,18 @@
     b = SkApplySign(b, sb);
 
 #if 1
-    int c = (int)(((int64_t)a * b) >> 16);
+    int c = (int)(((SkLONGLONG)a * b) >> 16);
 
     return SkApplySign(c, sa ^ sb);
 #else
-    int64_t ab = (int64_t)a * b;
+    SkLONGLONG ab = (SkLONGLONG)a * b;
     if (sa ^ sb) {
         ab = -ab;
     }
     return ab >> 16;
 #endif
 }
+#endif
 
 static void check_length(skiatest::Reporter* reporter,
                          const SkPoint& p, SkScalar targetLen) {
@@ -520,11 +522,12 @@
     unittest_fastfloat(reporter);
     unittest_isfinite(reporter);
 
+#ifdef SkLONGLONG
     for (i = 0; i < 10000; i++) {
         SkFixed numer = rand.nextS();
         SkFixed denom = rand.nextS();
         SkFixed result = SkFixedDiv(numer, denom);
-        int64_t check = ((int64_t)numer << 16) / denom;
+        SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
 
         (void)SkCLZ(numer);
         (void)SkCLZ(denom);
@@ -538,7 +541,7 @@
         REPORTER_ASSERT(reporter, result == (int32_t)check);
 
         result = SkFractDiv(numer, denom);
-        check = ((int64_t)numer << 30) / denom;
+        check = ((SkLONGLONG)numer << 30) / denom;
 
         REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
         if (check > SK_MaxS32) {
@@ -580,6 +583,7 @@
             REPORTER_ASSERT(reporter, (diff >> 7) == 0);
         }
     }
+#endif
 
     for (i = 0; i < 10000; i++) {
         SkFract x = rand.nextU() >> 1;
diff --git a/tests/Sk64Test.cpp b/tests/Sk64Test.cpp
index c257487..e956cbb 100644
--- a/tests/Sk64Test.cpp
+++ b/tests/Sk64Test.cpp
@@ -24,6 +24,13 @@
     REPORTER_ASSERT(reporter, a.getSign() == table.sign);
 }
 
+#ifdef SkLONGLONG
+    static SkLONGLONG asLL(const Sk64& a)
+    {
+        return ((SkLONGLONG)a.fHi << 32) | a.fLo;
+    }
+#endif
+
 static void TestSk64(skiatest::Reporter* reporter) {
     enum BoolTests {
         kZero_BoolTest,
@@ -87,6 +94,109 @@
         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);
+
+        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
 }
 
 #include "TestClassDef.h"