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