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