1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8#include "Test.h" 9#include "SkRandom.h" 10#include <math.h> 11 12struct BoolTable { 13 int8_t zero, pos, neg, toBool, sign; 14}; 15 16static void bool_table_test(skiatest::Reporter* reporter, 17 const Sk64& a, const BoolTable& table) 18{ 19 REPORTER_ASSERT(reporter, a.isZero() != a.nonZero()); 20 21 REPORTER_ASSERT(reporter, !a.isZero() == !table.zero); 22 REPORTER_ASSERT(reporter, !a.isPos() == !table.pos); 23 REPORTER_ASSERT(reporter, !a.isNeg() == !table.neg); 24 REPORTER_ASSERT(reporter, a.getSign() == table.sign); 25} 26 27#ifdef SkLONGLONG 28 static SkLONGLONG asLL(const Sk64& a) 29 { 30 return ((SkLONGLONG)a.fHi << 32) | a.fLo; 31 } 32#endif 33 34static void TestSk64(skiatest::Reporter* reporter) { 35 enum BoolTests { 36 kZero_BoolTest, 37 kPos_BoolTest, 38 kNeg_BoolTest 39 }; 40 static const BoolTable gBoolTable[] = { 41 { 1, 0, 0, 0, 0 }, 42 { 0, 1, 0, 1, 1 }, 43 { 0, 0, 1, 1, -1 } 44 }; 45 46 Sk64 a, b, c; 47 48 a.fHi = a.fLo = 0; 49 b.set(0); 50 c.setZero(); 51 REPORTER_ASSERT(reporter, a == b); 52 REPORTER_ASSERT(reporter, a == c); 53 bool_table_test(reporter, a, gBoolTable[kZero_BoolTest]); 54 55 a.fHi = 0; a.fLo = 5; 56 b.set(5); 57 REPORTER_ASSERT(reporter, a == b); 58 REPORTER_ASSERT(reporter, a.is32() && a.get32() == 5 && !a.is64()); 59 bool_table_test(reporter, a, gBoolTable[kPos_BoolTest]); 60 61 a.fHi = -1; a.fLo = (uint32_t)-5; 62 b.set(-5); 63 REPORTER_ASSERT(reporter, a == b); 64 REPORTER_ASSERT(reporter, a.is32() && a.get32() == -5 && !a.is64()); 65 bool_table_test(reporter, a, gBoolTable[kNeg_BoolTest]); 66 67 a.setZero(); 68 b.set(6); 69 c.set(-6); 70 REPORTER_ASSERT(reporter, a != b && b != c && a != c); 71 REPORTER_ASSERT(reporter, !(a == b) && !(a == b) && !(a == b)); 72 REPORTER_ASSERT(reporter, a < b && b > a && a <= b && b >= a); 73 REPORTER_ASSERT(reporter, c < a && a > c && c <= a && a >= c); 74 REPORTER_ASSERT(reporter, c < b && b > c && c <= b && b >= c); 75 76 // Now test add/sub 77 78 SkRandom rand; 79 int i; 80 81 for (i = 0; i < 1000; i++) 82 { 83 int aa = rand.nextS() >> 1; 84 int bb = rand.nextS() >> 1; 85 a.set(aa); 86 b.set(bb); 87 REPORTER_ASSERT(reporter, a.get32() == aa && b.get32() == bb); 88 c = a; c.add(bb); 89 REPORTER_ASSERT(reporter, c.get32() == aa + bb); 90 c = a; c.add(-bb); 91 REPORTER_ASSERT(reporter, c.get32() == aa - bb); 92 c = a; c.add(b); 93 REPORTER_ASSERT(reporter, c.get32() == aa + bb); 94 c = a; c.sub(b); 95 REPORTER_ASSERT(reporter, c.get32() == aa - bb); 96 } 97 98#ifdef SkLONGLONG 99 for (i = 0; i < 1000; i++) 100 { 101 rand.next64(&a); //a.fHi >>= 1; // avoid overflow 102 rand.next64(&b); //b.fHi >>= 1; // avoid overflow 103 104 if (!(i & 3)) // want to explicitly test these cases 105 { 106 a.fLo = 0; 107 b.fLo = 0; 108 } 109 else if (!(i & 7)) // want to explicitly test these cases 110 { 111 a.fHi = 0; 112 b.fHi = 0; 113 } 114 115 SkLONGLONG aa = asLL(a); 116 SkLONGLONG bb = asLL(b); 117 118 REPORTER_ASSERT(reporter, (a < b) == (aa < bb)); 119 REPORTER_ASSERT(reporter, (a <= b) == (aa <= bb)); 120 REPORTER_ASSERT(reporter, (a > b) == (aa > bb)); 121 REPORTER_ASSERT(reporter, (a >= b) == (aa >= bb)); 122 REPORTER_ASSERT(reporter, (a == b) == (aa == bb)); 123 REPORTER_ASSERT(reporter, (a != b) == (aa != bb)); 124 125 c = a; c.add(b); 126 REPORTER_ASSERT(reporter, asLL(c) == aa + bb); 127 c = a; c.sub(b); 128 REPORTER_ASSERT(reporter, asLL(c) == aa - bb); 129 c = a; c.rsub(b); 130 REPORTER_ASSERT(reporter, asLL(c) == bb - aa); 131 c = a; c.negate(); 132 REPORTER_ASSERT(reporter, asLL(c) == -aa); 133 134 int bits = rand.nextU() & 63; 135 c = a; c.shiftLeft(bits); 136 REPORTER_ASSERT(reporter, asLL(c) == (aa << bits)); 137 c = a; c.shiftRight(bits); 138 REPORTER_ASSERT(reporter, asLL(c) == (aa >> bits)); 139 c = a; c.roundRight(bits); 140 141 SkLONGLONG tmp; 142 143 tmp = aa; 144 if (bits > 0) 145 tmp += (SkLONGLONG)1 << (bits - 1); 146 REPORTER_ASSERT(reporter, asLL(c) == (tmp >> bits)); 147 148 c.setMul(a.fHi, b.fHi); 149 tmp = (SkLONGLONG)a.fHi * b.fHi; 150 REPORTER_ASSERT(reporter, asLL(c) == tmp); 151 } 152 153 154 for (i = 0; i < 100000; i++) 155 { 156 Sk64 wide; 157 int32_t denom = rand.nextS(); 158 159 while (denom == 0) 160 denom = rand.nextS(); 161 wide.setMul(rand.nextS(), rand.nextS()); 162 SkLONGLONG check = wide.getLongLong(); 163 164 wide.div(denom, Sk64::kTrunc_DivOption); 165 check /= denom; 166 SkLONGLONG w = wide.getLongLong(); 167 168 REPORTER_ASSERT(reporter, check == w); 169 170 wide.setMul(rand.nextS(), rand.nextS()); 171 wide.abs(); 172 denom = wide.getSqrt(); 173 int32_t ck = (int32_t)sqrt((double)wide.getLongLong()); 174 int diff = denom - ck; 175 REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1); 176 177 wide.setMul(rand.nextS(), rand.nextS()); 178 Sk64 dwide; 179 dwide.setMul(rand.nextS(), rand.nextS()); 180 SkFixed fixdiv = wide.getFixedDiv(dwide); 181 double dnumer = (double)wide.getLongLong(); 182 double ddenom = (double)dwide.getLongLong(); 183 double ddiv = dnumer / ddenom; 184 SkFixed dfixdiv; 185 if (ddiv >= (double)SK_MaxS32 / (double)SK_Fixed1) 186 dfixdiv = SK_MaxS32; 187 else if (ddiv <= -(double)SK_MaxS32 / (double)SK_Fixed1) 188 dfixdiv = SK_MinS32; 189 else 190 dfixdiv = SkFloatToFixed(dnumer / ddenom); 191 diff = fixdiv - dfixdiv; 192 193 if (SkAbs32(diff) > 1) { 194 SkDebugf(" %d === numer %g denom %g div %g xdiv %x fxdiv %x\n", 195 i, dnumer, ddenom, ddiv, dfixdiv, fixdiv); 196 } 197 REPORTER_ASSERT(reporter, SkAbs32(diff) <= 1); 198 } 199#endif 200} 201 202#include "TestClassDef.h" 203DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64) 204