blob: 64eef753b00d6cee9f7abed85df4402c4be0519c [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.comd8730ea2009-02-27 22:06:06 +00008#include "Test.h"
9#include "SkRandom.h"
10#include <math.h>
11
reed@android.comd8730ea2009-02-27 22:06:06 +000012struct 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
reed@android.comd8730ea2009-02-27 22:06:06 +000033
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#ifdef SK_CAN_USE_FLOAT
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;
reed@android.com80e39a72009-04-02 16:59:40 +0000193
reed@android.comd8730ea2009-02-27 22:06:06 +0000194 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#endif
200 }
201#endif
202}
203
204#include "TestClassDef.h"
205DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64)