• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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  */
8 #include "Test.h"
9 #include "SkRandom.h"
10 #include <math.h>
11 
12 struct BoolTable {
13     int8_t  zero, pos, neg, toBool, sign;
14 };
15 
bool_table_test(skiatest::Reporter * reporter,const Sk64 & a,const BoolTable & table)16 static 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
asLL(const Sk64 & a)28     static SkLONGLONG asLL(const Sk64& a)
29     {
30         return ((SkLONGLONG)a.fHi << 32) | a.fLo;
31     }
32 #endif
33 
TestSk64(skiatest::Reporter * reporter)34 static 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;
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 #endif
200     }
201 #endif
202 }
203 
204 #include "TestClassDef.h"
205 DEFINE_TESTCLASS("Sk64", Sk64TestClass, TestSk64)
206