blob: f2d0655d86c4e449b84a81e5276b64480f5fbeb1 [file] [log] [blame]
croachrose48ede9b2006-11-08 19:24:48 +00001/* libs/corecg/Sk64.cpp
2**
3** Copyright 2006, Google Inc.
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
croachrose0f87cd82006-09-20 15:47:42 +000018#include "Sk64.h"
19
croachrose48ede9b2006-11-08 19:24:48 +000020#define shift_left(hi, lo) \
21 hi = (hi << 1) | (lo >> 31); \
22 lo <<= 1
croachrose0f87cd82006-09-20 15:47:42 +000023
croachrose48ede9b2006-11-08 19:24:48 +000024#define shift_left_bits(hi, lo, bits) \
25 SkASSERT((unsigned)(bits) < 31); \
26 hi = (hi << (bits)) | (lo >> (32 - (bits))); \
27 lo <<= (bits)
croachrose0f87cd82006-09-20 15:47:42 +000028
29//////////////////////////////////////////////////////////////////////
30
croachrose48ede9b2006-11-08 19:24:48 +000031int Sk64::getClzAbs() const
croachrose0f87cd82006-09-20 15:47:42 +000032{
croachrose48ede9b2006-11-08 19:24:48 +000033 int32_t hi = fHi;
34 uint32_t lo = fLo;
croachrose0f87cd82006-09-20 15:47:42 +000035
croachrose48ede9b2006-11-08 19:24:48 +000036 // get abs
37 if (hi < 0)
38 {
39 hi = -hi - Sk32ToBool(lo);
40 lo = 0 - lo;
41 }
42 return hi ? SkCLZ(hi) : SkCLZ(lo) + 32;
croachrose0f87cd82006-09-20 15:47:42 +000043}
44
45void Sk64::shiftLeft(unsigned bits)
46{
croachrose48ede9b2006-11-08 19:24:48 +000047 SkASSERT(bits <= 63);
48 if (bits == 0)
49 return;
croachrose0f87cd82006-09-20 15:47:42 +000050
croachrose48ede9b2006-11-08 19:24:48 +000051 if (bits >= 32)
52 {
53 fHi = fLo << (bits - 32);
54 fLo = 0;
55 }
56 else
57 {
58 fHi = (fHi << bits) | (fLo >> (32 - bits));
59 fLo <<= bits;
60 }
croachrose0f87cd82006-09-20 15:47:42 +000061}
62
63int32_t Sk64::getShiftRight(unsigned bits) const
64{
croachrose48ede9b2006-11-08 19:24:48 +000065 SkASSERT(bits <= 63);
croachrose0f87cd82006-09-20 15:47:42 +000066
croachrose48ede9b2006-11-08 19:24:48 +000067 if (bits == 0)
68 return fLo;
croachrose0f87cd82006-09-20 15:47:42 +000069
croachrose48ede9b2006-11-08 19:24:48 +000070 if (bits >= 32)
71 return fHi >> (bits - 32);
72 else
73 {
croachrose0f87cd82006-09-20 15:47:42 +000074#ifdef SK_DEBUG
croachrose48ede9b2006-11-08 19:24:48 +000075 int32_t tmp = fHi >> bits;
76 SkASSERT(tmp == 0 || tmp == -1);
croachrose0f87cd82006-09-20 15:47:42 +000077#endif
croachrose48ede9b2006-11-08 19:24:48 +000078 return (fHi << (32 - bits)) | (fLo >> bits);
79 }
croachrose0f87cd82006-09-20 15:47:42 +000080}
81
82void Sk64::shiftRight(unsigned bits)
83{
croachrose48ede9b2006-11-08 19:24:48 +000084 SkASSERT(bits <= 63);
85 if (bits == 0)
86 return;
croachrose0f87cd82006-09-20 15:47:42 +000087
croachrose48ede9b2006-11-08 19:24:48 +000088 if (bits >= 32)
89 {
90 fLo = fHi >> (bits - 32);
91 fHi >>= 31;
92 }
93 else
94 {
95 fLo = (fHi << (32 - bits)) | (fLo >> bits);
96 fHi >>= bits;
97 }
croachrose0f87cd82006-09-20 15:47:42 +000098}
99
100void Sk64::roundRight(unsigned bits)
101{
croachrose48ede9b2006-11-08 19:24:48 +0000102 SkASSERT(bits <= 63);
103 if (bits)
104 {
105 Sk64 one;
106 one.set(1);
107 one.shiftLeft(bits - 1);
108 this->add(one);
109 this->shiftRight(bits);
110 }
croachrose0f87cd82006-09-20 15:47:42 +0000111}
112
113int Sk64::shiftToMake32() const
114{
croachrose48ede9b2006-11-08 19:24:48 +0000115 int32_t hi = fHi;
116 uint32_t lo = fLo;
croachrose0f87cd82006-09-20 15:47:42 +0000117
croachrose48ede9b2006-11-08 19:24:48 +0000118 if (hi < 0) // make it positive
119 {
120 hi = -hi - Sk32ToBool(lo);
121 lo = 0 - lo;
122 }
croachrose0f87cd82006-09-20 15:47:42 +0000123
croachrose48ede9b2006-11-08 19:24:48 +0000124 if (hi == 0)
125 return lo >> 31;
126 else
127 return 33 - SkCLZ(hi);
croachrose0f87cd82006-09-20 15:47:42 +0000128}
129
130void Sk64::negate()
131{
croachrose48ede9b2006-11-08 19:24:48 +0000132 fHi = -fHi - Sk32ToBool(fLo);
133 fLo = 0 - fLo;
croachrose0f87cd82006-09-20 15:47:42 +0000134}
135
136void Sk64::abs()
137{
croachrose48ede9b2006-11-08 19:24:48 +0000138 if (fHi < 0)
139 {
140 fHi = -fHi - Sk32ToBool(fLo);
141 fLo = 0 - fLo;
142 }
croachrose0f87cd82006-09-20 15:47:42 +0000143}
144
145////////////////////////////////////////////////////////////////
146
147static inline int32_t round_right_16(int32_t hi, uint32_t lo)
148{
croachrose48ede9b2006-11-08 19:24:48 +0000149 uint32_t sum = lo + (1 << 15);
150 hi += (sum < lo);
151 return (hi << 16) | (sum >> 16);
croachrose0f87cd82006-09-20 15:47:42 +0000152}
153
154SkBool Sk64::isFixed() const
155{
croachrose48ede9b2006-11-08 19:24:48 +0000156 Sk64 tmp = *this;
157 tmp.roundRight(16);
158 return tmp.is32();
croachrose0f87cd82006-09-20 15:47:42 +0000159}
160
croachrose48ede9b2006-11-08 19:24:48 +0000161SkFract Sk64::getFract() const
croachrose0f87cd82006-09-20 15:47:42 +0000162{
croachrose48ede9b2006-11-08 19:24:48 +0000163 Sk64 tmp = *this;
164 tmp.roundRight(30);
165 return tmp.get32();
croachrose0f87cd82006-09-20 15:47:42 +0000166}
167
168void Sk64::sub(const Sk64& a)
169{
croachrose48ede9b2006-11-08 19:24:48 +0000170 fHi = fHi - a.fHi - (fLo < a.fLo);
171 fLo = fLo - a.fLo;
croachrose0f87cd82006-09-20 15:47:42 +0000172}
173
174void Sk64::rsub(const Sk64& a)
175{
croachrose48ede9b2006-11-08 19:24:48 +0000176 fHi = a.fHi - fHi - (a.fLo < fLo);
177 fLo = a.fLo - fLo;
croachrose0f87cd82006-09-20 15:47:42 +0000178}
179
180void Sk64::setMul(int32_t a, int32_t b)
181{
croachrose48ede9b2006-11-08 19:24:48 +0000182 int sa = a >> 31;
183 int sb = b >> 31;
184 // now make them positive
185 a = (a ^ sa) - sa;
186 b = (b ^ sb) - sb;
croachrose0f87cd82006-09-20 15:47:42 +0000187
croachrose48ede9b2006-11-08 19:24:48 +0000188 uint32_t ah = a >> 16;
189 uint32_t al = a & 0xFFFF;
190 uint32_t bh = b >> 16;
191 uint32_t bl = b & 0xFFFF;
croachrose0f87cd82006-09-20 15:47:42 +0000192
croachrose48ede9b2006-11-08 19:24:48 +0000193 uint32_t A = ah * bh;
194 uint32_t B = ah * bl + al * bh;
195 uint32_t C = al * bl;
croachrose0f87cd82006-09-20 15:47:42 +0000196
croachrose48ede9b2006-11-08 19:24:48 +0000197 /* [ A ]
198 [ B ]
199 [ C ]
200 */
201 fLo = C + (B << 16);
202 fHi = A + (B >>16) + (fLo < C);
croachrose0f87cd82006-09-20 15:47:42 +0000203
croachrose48ede9b2006-11-08 19:24:48 +0000204 if (sa != sb)
205 this->negate();
croachrose0f87cd82006-09-20 15:47:42 +0000206}
207
208void Sk64::div(int32_t denom, DivOptions option)
209{
croachrose48ede9b2006-11-08 19:24:48 +0000210 SkASSERT(denom);
croachrose0f87cd82006-09-20 15:47:42 +0000211
croachrose48ede9b2006-11-08 19:24:48 +0000212 int32_t hi = fHi;
213 uint32_t lo = fLo;
214 int sign = denom ^ hi;
croachrose0f87cd82006-09-20 15:47:42 +0000215
croachrose48ede9b2006-11-08 19:24:48 +0000216 denom = SkAbs32(denom);
217 if (hi < 0)
218 {
219 hi = -hi - Sk32ToBool(lo);
220 lo = 0 - lo;
221 }
croachrose0f87cd82006-09-20 15:47:42 +0000222
croachrose48ede9b2006-11-08 19:24:48 +0000223 if (option == kRound_DivOption) // add denom/2
224 {
225 uint32_t newLo = lo + (denom >> 1);
226 hi += (newLo < lo);
227 lo = newLo;
228 }
croachrose0f87cd82006-09-20 15:47:42 +0000229
croachrose48ede9b2006-11-08 19:24:48 +0000230 if (hi == 0) // fast-case
231 {
232 if (lo < (uint32_t)denom)
233 this->set(0, 0);
234 else
235 {
236 this->set(0, lo / denom);
237 if (sign < 0)
238 this->negate();
239 }
240 return;
241 }
croachrose0f87cd82006-09-20 15:47:42 +0000242
croachrose48ede9b2006-11-08 19:24:48 +0000243 int bits;
croachrose0f87cd82006-09-20 15:47:42 +0000244
croachrose48ede9b2006-11-08 19:24:48 +0000245 {
246 int dbits = SkCLZ(denom);
247 int nbits = SkCLZ(hi);
croachrose0f87cd82006-09-20 15:47:42 +0000248
croachrose48ede9b2006-11-08 19:24:48 +0000249 bits = 32 + dbits - nbits;
250 SkASSERT(bits <= 63);
251 if (bits <= 0)
252 {
253 this->set(0, 0);
254 return;
255 }
256 denom <<= (dbits - 1);
257 shift_left_bits(hi, lo, nbits - 1);
258 }
croachrose0f87cd82006-09-20 15:47:42 +0000259
croachrose48ede9b2006-11-08 19:24:48 +0000260 int32_t rhi = 0;
261 uint32_t rlo = 0;
croachrose0f87cd82006-09-20 15:47:42 +0000262
croachrose48ede9b2006-11-08 19:24:48 +0000263 do {
264 shift_left(rhi, rlo);
croachrose0f87cd82006-09-20 15:47:42 +0000265#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
croachrose48ede9b2006-11-08 19:24:48 +0000266 if ((uint32_t)denom <= (uint32_t)hi)
267 {
268 hi -= denom;
269 rlo |= 1;
270 }
croachrose0f87cd82006-09-20 15:47:42 +0000271#else
croachrose48ede9b2006-11-08 19:24:48 +0000272 int32_t diff = (denom - hi - 1) >> 31;
273 hi -= denom & diff;
274 rlo -= diff;
croachrose0f87cd82006-09-20 15:47:42 +0000275#endif
croachrose48ede9b2006-11-08 19:24:48 +0000276 shift_left(hi, lo);
277 } while (--bits >= 0);
278 SkASSERT(rhi >= 0);
croachrose0f87cd82006-09-20 15:47:42 +0000279
croachrose48ede9b2006-11-08 19:24:48 +0000280 fHi = rhi;
281 fLo = rlo;
282 if (sign < 0)
283 this->negate();
croachrose0f87cd82006-09-20 15:47:42 +0000284}
285
croachrose48ede9b2006-11-08 19:24:48 +0000286#define shift_left_2(a, b, c) \
287 a = (a << 2) | (b >> 30); \
288 b = (b << 2) | (c >> 30); \
289 c <<= 2
croachrose0f87cd82006-09-20 15:47:42 +0000290
291int32_t Sk64::getSqrt() const
292{
croachrose48ede9b2006-11-08 19:24:48 +0000293 SkASSERT(!this->isNeg());
croachrose0f87cd82006-09-20 15:47:42 +0000294
croachrose48ede9b2006-11-08 19:24:48 +0000295 uint32_t hi = fHi;
296 uint32_t lo = fLo;
297 uint32_t sqr = 0;
298 uint32_t root = 0;
299 int count = 31;
croachrose0f87cd82006-09-20 15:47:42 +0000300
croachrose48ede9b2006-11-08 19:24:48 +0000301 do {
302 root <<= 1;
303 shift_left_2(sqr, hi, lo);
croachrose0f87cd82006-09-20 15:47:42 +0000304
croachrose48ede9b2006-11-08 19:24:48 +0000305 uint32_t testDiv = (root << 1) + 1;
306 if (sqr >= testDiv)
307 {
308 sqr -= testDiv;
309 root++;
310 }
311 } while (--count >= 0);
312 SkASSERT((int32_t)root >= 0);
croachrose0f87cd82006-09-20 15:47:42 +0000313
croachrose48ede9b2006-11-08 19:24:48 +0000314 return root;
croachrose0f87cd82006-09-20 15:47:42 +0000315}
316
317#ifdef SK_CAN_USE_LONGLONG
croachrose48ede9b2006-11-08 19:24:48 +0000318 SkLONGLONG Sk64::getLongLong() const
319 {
320 SkLONGLONG value = fHi;
321 value <<= 32;
322 return value | fLo;
323 }
croachrose0f87cd82006-09-20 15:47:42 +0000324#endif
325
326SkFixed Sk64::getFixedDiv(const Sk64& denom) const
327{
croachrose48ede9b2006-11-08 19:24:48 +0000328 Sk64 N = *this;
329 Sk64 D = denom;
330 int32_t sign = SkExtractSign(N.fHi ^ D.fHi);
331 SkFixed result;
croachrose0f87cd82006-09-20 15:47:42 +0000332
croachrose48ede9b2006-11-08 19:24:48 +0000333 N.abs();
334 D.abs();
croachrose0f87cd82006-09-20 15:47:42 +0000335
croachrose48ede9b2006-11-08 19:24:48 +0000336 // need to knock D down to just 31 bits
337 // either by rounding it to the right, or shifting N to the left
338 // then we can just call 64/32 div
croachrose0f87cd82006-09-20 15:47:42 +0000339
croachrose48ede9b2006-11-08 19:24:48 +0000340 int nclz = N.fHi ? SkCLZ(N.fHi) : 32;
341 int dclz = D.fHi ? SkCLZ(D.fHi) : (33 - (D.fLo >> 31));
croachrose0f87cd82006-09-20 15:47:42 +0000342
croachrose48ede9b2006-11-08 19:24:48 +0000343 int shiftN = nclz - 1;
344 SkASSERT(shiftN >= 0);
345 int shiftD = 33 - dclz;
346 SkASSERT(shiftD >= 0);
croachrose0f87cd82006-09-20 15:47:42 +0000347
croachrose48ede9b2006-11-08 19:24:48 +0000348 if (shiftD + shiftN < 16)
349 shiftD = 16 - shiftN;
350 else
351 shiftN = 16 - shiftD;
croachrose0f87cd82006-09-20 15:47:42 +0000352
croachrose48ede9b2006-11-08 19:24:48 +0000353 D.roundRight(shiftD);
354 if (D.isZero())
355 result = SK_MaxS32;
356 else
357 {
358 if (shiftN >= 0)
359 N.shiftLeft(shiftN);
360 else
361 N.roundRight(-shiftN);
362 N.div(D.get32(), Sk64::kTrunc_DivOption);
363 if (N.is32())
364 result = N.get32();
365 else
366 result = SK_MaxS32;
367 }
368 return SkApplySign(result, sign);
croachrose0f87cd82006-09-20 15:47:42 +0000369}
370
371///////////////////////////////////////////////////////////////////////
372
373#ifdef SK_DEBUG
374
375#include "SkRandom.h"
376#include <math.h>
377
378#ifdef SK_SUPPORT_UNITTEST
379struct BoolTable {
croachrose48ede9b2006-11-08 19:24:48 +0000380 S8 zero, pos, neg, toBool, sign;
croachrose0f87cd82006-09-20 15:47:42 +0000381};
382
383static void bool_table_test(const Sk64& a, const BoolTable& table)
384{
croachrose48ede9b2006-11-08 19:24:48 +0000385 SkASSERT(a.isZero() != a.nonZero());
croachrose0f87cd82006-09-20 15:47:42 +0000386
croachrose48ede9b2006-11-08 19:24:48 +0000387 SkASSERT(!a.isZero() == !table.zero);
388 SkASSERT(!a.isPos() == !table.pos);
389 SkASSERT(!a.isNeg() == !table.neg);
390 SkASSERT(a.sign() == table.sign);
croachrose0f87cd82006-09-20 15:47:42 +0000391}
392
393#ifdef SK_CAN_USE_LONGLONG
croachrose48ede9b2006-11-08 19:24:48 +0000394 static SkLONGLONG asLL(const Sk64& a)
395 {
396 return ((SkLONGLONG)a.fHi << 32) | a.fLo;
397 }
croachrose0f87cd82006-09-20 15:47:42 +0000398#endif
399#endif
400
401void Sk64::UnitTest()
402{
403#ifdef SK_SUPPORT_UNITTEST
croachrose48ede9b2006-11-08 19:24:48 +0000404 enum BoolTests {
405 kZero_BoolTest,
406 kPos_BoolTest,
407 kNeg_BoolTest
408 };
409 static const BoolTable gBoolTable[] = {
410 { 1, 0, 0, 0, 0 },
411 { 0, 1, 0, 1, 1 },
412 { 0, 0, 1, 1, -1 }
413 };
croachrose0f87cd82006-09-20 15:47:42 +0000414
croachrose48ede9b2006-11-08 19:24:48 +0000415 Sk64 a, b, c;
croachrose0f87cd82006-09-20 15:47:42 +0000416
croachrose48ede9b2006-11-08 19:24:48 +0000417 a.fHi = a.fLo = 0;
418 b.set(0);
419 c.setZero();
420 SkASSERT(a == b);
421 SkASSERT(a == c);
422 bool_table_test(a, gBoolTable[kZero_BoolTest]);
croachrose0f87cd82006-09-20 15:47:42 +0000423
croachrose48ede9b2006-11-08 19:24:48 +0000424 a.fHi = 0; a.fLo = 5;
425 b.set(5);
426 SkASSERT(a == b);
427 SkASSERT(a.is32() && a.get32() == 5 && !a.is64());
428 bool_table_test(a, gBoolTable[kPos_BoolTest]);
croachrose0f87cd82006-09-20 15:47:42 +0000429
croachrose48ede9b2006-11-08 19:24:48 +0000430 a.fHi = -1; a.fLo = (uint32_t)-5;
431 b.set(-5);
432 SkASSERT(a == b);
433 SkASSERT(a.is32() && a.get32() == -5 && !a.is64());
434 bool_table_test(a, gBoolTable[kNeg_BoolTest]);
croachrose0f87cd82006-09-20 15:47:42 +0000435
croachrose48ede9b2006-11-08 19:24:48 +0000436 a.setZero();
437 b.set(6);
438 c.set(-6);
439 SkASSERT(a != b && b != c && a != c);
440 SkASSERT(!(a == b) && !(a == b) && !(a == b));
441 SkASSERT(a < b && b > a && a <= b && b >= a);
442 SkASSERT(c < a && a > c && c <= a && a >= c);
443 SkASSERT(c < b && b > c && c <= b && b >= c);
croachrose0f87cd82006-09-20 15:47:42 +0000444
croachrose48ede9b2006-11-08 19:24:48 +0000445 // Now test add/sub
croachrose0f87cd82006-09-20 15:47:42 +0000446
croachrose48ede9b2006-11-08 19:24:48 +0000447 SkRandom rand;
448 int i;
croachrose0f87cd82006-09-20 15:47:42 +0000449
croachrose48ede9b2006-11-08 19:24:48 +0000450 for (i = 0; i < 1000; i++)
451 {
452 int aa = rand.nextS() >> 1;
453 int bb = rand.nextS() >> 1;
454 a.set(aa);
455 b.set(bb);
456 SkASSERT(a.get32() == aa && b.get32() == bb);
457 c = a; c.add(bb);
458 SkASSERT(c.get32() == aa + bb);
459 c = a; c.add(-bb);
460 SkASSERT(c.get32() == aa - bb);
461 c = a; c.add(b);
462 SkASSERT(c.get32() == aa + bb);
463 c = a; c.sub(b);
464 SkASSERT(c.get32() == aa - bb);
465 }
croachrose0f87cd82006-09-20 15:47:42 +0000466
467#ifdef SK_CAN_USE_LONGLONG
croachrose48ede9b2006-11-08 19:24:48 +0000468 for (i = 0; i < 1000; i++)
469 {
470 rand.next64(&a); //a.fHi >>= 1; // avoid overflow
471 rand.next64(&b); //b.fHi >>= 1; // avoid overflow
croachrose0f87cd82006-09-20 15:47:42 +0000472
croachrose48ede9b2006-11-08 19:24:48 +0000473 if (!(i & 3)) // want to explicitly test these cases
474 {
475 a.fLo = 0;
476 b.fLo = 0;
477 }
478 else if (!(i & 7)) // want to explicitly test these cases
479 {
480 a.fHi = 0;
481 b.fHi = 0;
482 }
croachrose0f87cd82006-09-20 15:47:42 +0000483
croachrose48ede9b2006-11-08 19:24:48 +0000484 SkLONGLONG aa = asLL(a);
485 SkLONGLONG bb = asLL(b);
croachrose0f87cd82006-09-20 15:47:42 +0000486
croachrose48ede9b2006-11-08 19:24:48 +0000487 SkASSERT((a < b) == (aa < bb));
488 SkASSERT((a <= b) == (aa <= bb));
489 SkASSERT((a > b) == (aa > bb));
490 SkASSERT((a >= b) == (aa >= bb));
491 SkASSERT((a == b) == (aa == bb));
492 SkASSERT((a != b) == (aa != bb));
croachrose0f87cd82006-09-20 15:47:42 +0000493
croachrose48ede9b2006-11-08 19:24:48 +0000494 c = a; c.add(b);
495 SkASSERT(asLL(c) == aa + bb);
496 c = a; c.sub(b);
497 SkASSERT(asLL(c) == aa - bb);
498 c = a; c.rsub(b);
499 SkASSERT(asLL(c) == bb - aa);
500 c = a; c.negate();
501 SkASSERT(asLL(c) == -aa);
croachrose0f87cd82006-09-20 15:47:42 +0000502
croachrose48ede9b2006-11-08 19:24:48 +0000503 int bits = rand.nextU() & 63;
504 c = a; c.shiftLeft(bits);
505 SkASSERT(asLL(c) == (aa << bits));
506 c = a; c.shiftRight(bits);
507 SkASSERT(asLL(c) == (aa >> bits));
508 c = a; c.roundRight(bits);
croachrose0f87cd82006-09-20 15:47:42 +0000509
croachrose48ede9b2006-11-08 19:24:48 +0000510 SkLONGLONG tmp;
croachrose0f87cd82006-09-20 15:47:42 +0000511
croachrose48ede9b2006-11-08 19:24:48 +0000512 tmp = aa;
513 if (bits > 0)
514 tmp += (SkLONGLONG)1 << (bits - 1);
515 SkASSERT(asLL(c) == (tmp >> bits));
croachrose0f87cd82006-09-20 15:47:42 +0000516
croachrose48ede9b2006-11-08 19:24:48 +0000517 c.setMul(a.fHi, b.fHi);
518 tmp = (SkLONGLONG)a.fHi * b.fHi;
519 SkASSERT(asLL(c) == tmp);
520 }
croachrose0f87cd82006-09-20 15:47:42 +0000521
522
croachrose48ede9b2006-11-08 19:24:48 +0000523 for (i = 0; i < 100000; i++)
524 {
525 Sk64 wide;
526 int32_t denom = rand.nextS();
croachrose0f87cd82006-09-20 15:47:42 +0000527
croachrose48ede9b2006-11-08 19:24:48 +0000528 while (denom == 0)
529 denom = rand.nextS();
530 wide.setMul(rand.nextS(), rand.nextS());
531 SkLONGLONG check = wide.getLongLong();
croachrose0f87cd82006-09-20 15:47:42 +0000532
croachrose48ede9b2006-11-08 19:24:48 +0000533 wide.div(denom, Sk64::kTrunc_DivOption);
534 check /= denom;
535 SkLONGLONG w = wide.getLongLong();
croachrose0f87cd82006-09-20 15:47:42 +0000536
croachrose48ede9b2006-11-08 19:24:48 +0000537 SkASSERT(check == w);
croachrose0f87cd82006-09-20 15:47:42 +0000538
539#ifdef SK_CAN_USE_FLOAT
croachrose48ede9b2006-11-08 19:24:48 +0000540 wide.setMul(rand.nextS(), rand.nextS());
541 wide.abs();
542 denom = wide.getSqrt();
543 int32_t ck = (int32_t)sqrt((double)wide.getLongLong());
544 int diff = denom - ck;
545 SkASSERT(SkAbs32(diff) <= 1);
croachrose0f87cd82006-09-20 15:47:42 +0000546
croachrose48ede9b2006-11-08 19:24:48 +0000547 wide.setMul(rand.nextS(), rand.nextS());
548 Sk64 dwide;
549 dwide.setMul(rand.nextS(), rand.nextS());
550 SkFixed fixdiv = wide.getFixedDiv(dwide);
551 double dnumer = (double)wide.getLongLong();
552 double ddenom = (double)dwide.getLongLong();
553 double ddiv = dnumer / ddenom;
554 SkFixed dfixdiv;
555 if (ddiv >= (double)SK_MaxS32 / (double)SK_Fixed1)
556 dfixdiv = SK_MaxS32;
557 else if (ddiv <= -(double)SK_MaxS32 / (double)SK_Fixed1)
558 dfixdiv = SK_MinS32;
559 else
560 dfixdiv = SkFloatToFixed(dnumer / ddenom);
561 diff = fixdiv - dfixdiv;
562 SkASSERT(SkAbs32(diff) <= 1);
croachrose0f87cd82006-09-20 15:47:42 +0000563#endif
croachrose48ede9b2006-11-08 19:24:48 +0000564 }
croachrose0f87cd82006-09-20 15:47:42 +0000565#endif
566#endif
567}
568
569#endif
570