/* * 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 "SkRandom.h" #include <math.h> 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 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)