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