From 0e6e8cc627242cc7e301401cfe112ba98a008101 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Thu, 15 Aug 2013 13:43:23 +0000 Subject: 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 --- include/config/SkUserConfig.h | 7 +++ include/core/Sk64.h | 4 ++ include/core/SkFixed.h | 57 ++++++++++++++-------- include/core/SkPostConfig.h | 11 +++++ src/core/Sk64.cpp | 9 ++++ src/core/SkMath.cpp | 65 +++++++++++++++++++++++++ tests/MathTest.cpp | 12 +++-- tests/Sk64Test.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 252 insertions(+), 23 deletions(-) diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h index e78205db48..236a99a03e 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 47ec15e0d3..6db3001fb5 100644 --- a/include/core/Sk64.h +++ b/include/core/Sk64.h @@ -221,6 +221,10 @@ struct SK_API Sk64 { 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 a4a515d30a..acfbe9af95 100644 --- a/include/core/SkFixed.h +++ b/include/core/SkFixed.h @@ -120,6 +120,20 @@ inline SkFixed SkFixedFraction(SkFixed x) #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 @@ inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) 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 @@ inline SkFixed SkFixedSquare_longlong(SkFixed value) #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 e992f42916..4a819d369a 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 #include diff --git a/src/core/Sk64.cpp b/src/core/Sk64.cpp index 2061ebbf4f..7c195ce4fe 100644 --- a/src/core/Sk64.cpp +++ b/src/core/Sk64.cpp @@ -299,6 +299,15 @@ int32_t Sk64::getSqrt() const 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 6c6c6d5670..2693e5c13c 100644 --- a/src/core/SkMath.cpp +++ b/src/core/SkMath.cpp @@ -105,6 +105,71 @@ int32_t SkMulShift(int32_t a, int32_t b, unsigned shift) { } } +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((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((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 f9849194cb..fe54594100 100644 --- a/tests/MathTest.cpp +++ b/tests/MathTest.cpp @@ -186,6 +186,7 @@ static void test_blend(skiatest::Reporter* reporter) { } } +#if defined(SkLONGLONG) static int symmetric_fixmul(int a, int b) { int sa = SkExtractSign(a); int sb = SkExtractSign(b); @@ -194,17 +195,18 @@ static int symmetric_fixmul(int a, int b) { 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 @@ static void TestMath(skiatest::Reporter* reporter) { 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 @@ static void TestMath(skiatest::Reporter* reporter) { 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 @@ static void TestMath(skiatest::Reporter* reporter) { 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 c257487d7b..e956cbbd51 100644 --- a/tests/Sk64Test.cpp +++ b/tests/Sk64Test.cpp @@ -24,6 +24,13 @@ static void bool_table_test(skiatest::Reporter* reporter, 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 @@ static void TestSk64(skiatest::Reporter* reporter) { 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" -- cgit v1.2.3