• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
bool_table_test(skiatest::Reporter * reporter,const Sk64 & a,const BoolTable & table)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
asLL(const Sk64 & a)21     static SkLONGLONG asLL(const Sk64& a)
22     {
23         return ((SkLONGLONG)a.fHi << 32) | a.fLo;
24     }
25 #endif
26 
TestSk64(skiatest::Reporter * reporter)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