blob: 9fb49ebbed1c6f4f3d088cf60968887471a6fa50 [file] [log] [blame]
reed@android.comd8730ea2009-02-27 22:06:06 +00001#include "Test.h"
2#include "SkRandom.h"
3#include <math.h>
4
reed@android.comd8730ea2009-02-27 22:06:06 +00005struct BoolTable {
6 int8_t zero, pos, neg, toBool, sign;
7};
8
9static 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
reed@android.comd8730ea2009-02-27 22:06:06 +000026
27static 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;
reed@android.com80e39a72009-04-02 16:59:40 +0000186
reed@android.comd8730ea2009-02-27 22:06:06 +0000187 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"
198DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64)