1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkColorPriv.h"
9 #include "SkEndian.h"
10 #include "SkFloatBits.h"
11 #include "SkFloatingPoint.h"
12 #include "SkHalf.h"
13 #include "SkMathPriv.h"
14 #include "SkPoint.h"
15 #include "SkRandom.h"
16 #include "Test.h"
17 
test_clz(skiatest::Reporter * reporter)18 static void test_clz(skiatest::Reporter* reporter) {
19     REPORTER_ASSERT(reporter, 32 == SkCLZ(0));
20     REPORTER_ASSERT(reporter, 31 == SkCLZ(1));
21     REPORTER_ASSERT(reporter, 1 == SkCLZ(1 << 30));
22     REPORTER_ASSERT(reporter, 0 == SkCLZ(~0U));
23 
24     SkRandom rand;
25     for (int i = 0; i < 1000; ++i) {
26         uint32_t mask = rand.nextU();
27         // need to get some zeros for testing, but in some obscure way so the
28         // compiler won't "see" that, and work-around calling the functions.
29         mask >>= (mask & 31);
30         int intri = SkCLZ(mask);
31         int porta = SkCLZ_portable(mask);
32         REPORTER_ASSERT(reporter, intri == porta);
33     }
34 }
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 
sk_fsel(float pred,float result_ge,float result_lt)38 static float sk_fsel(float pred, float result_ge, float result_lt) {
39     return pred >= 0 ? result_ge : result_lt;
40 }
41 
fast_floor(float x)42 static float fast_floor(float x) {
43 //    float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23);
44     float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23));
45     return (float)(x + big) - big;
46 }
47 
std_floor(float x)48 static float std_floor(float x) {
49     return sk_float_floor(x);
50 }
51 
test_floor_value(skiatest::Reporter * reporter,float value)52 static void test_floor_value(skiatest::Reporter* reporter, float value) {
53     float fast = fast_floor(value);
54     float std = std_floor(value);
55     if (std != fast) {
56         ERRORF(reporter, "fast_floor(%.9g) == %.9g != %.9g == std_floor(%.9g)",
57                value, fast, std, value);
58     }
59 }
60 
test_floor(skiatest::Reporter * reporter)61 static void test_floor(skiatest::Reporter* reporter) {
62     static const float gVals[] = {
63         0, 1, 1.1f, 1.01f, 1.001f, 1.0001f, 1.00001f, 1.000001f, 1.0000001f
64     };
65 
66     for (size_t i = 0; i < SK_ARRAY_COUNT(gVals); ++i) {
67         test_floor_value(reporter, gVals[i]);
68 //        test_floor_value(reporter, -gVals[i]);
69     }
70 }
71 
72 ///////////////////////////////////////////////////////////////////////////////
73 
74 // test that SkMul16ShiftRound and SkMulDiv255Round return the same result
test_muldivround(skiatest::Reporter * reporter)75 static void test_muldivround(skiatest::Reporter* reporter) {
76 #if 0
77     // this "complete" test is too slow, so we test a random sampling of it
78 
79     for (int a = 0; a <= 32767; ++a) {
80         for (int b = 0; b <= 32767; ++b) {
81             unsigned prod0 = SkMul16ShiftRound(a, b, 8);
82             unsigned prod1 = SkMulDiv255Round(a, b);
83             SkASSERT(prod0 == prod1);
84         }
85     }
86 #endif
87 
88     SkRandom rand;
89     for (int i = 0; i < 10000; ++i) {
90         unsigned a = rand.nextU() & 0x7FFF;
91         unsigned b = rand.nextU() & 0x7FFF;
92 
93         unsigned prod0 = SkMul16ShiftRound(a, b, 8);
94         unsigned prod1 = SkMulDiv255Round(a, b);
95 
96         REPORTER_ASSERT(reporter, prod0 == prod1);
97     }
98 }
99 
float_blend(int src,int dst,float unit)100 static float float_blend(int src, int dst, float unit) {
101     return dst + (src - dst) * unit;
102 }
103 
blend31(int src,int dst,int a31)104 static int blend31(int src, int dst, int a31) {
105     return dst + ((src - dst) * a31 * 2114 >> 16);
106     //    return dst + ((src - dst) * a31 * 33 >> 10);
107 }
108 
blend31_slow(int src,int dst,int a31)109 static int blend31_slow(int src, int dst, int a31) {
110     int prod = src * a31 + (31 - a31) * dst + 16;
111     prod = (prod + (prod >> 5)) >> 5;
112     return prod;
113 }
114 
blend31_round(int src,int dst,int a31)115 static int blend31_round(int src, int dst, int a31) {
116     int prod = (src - dst) * a31 + 16;
117     prod = (prod + (prod >> 5)) >> 5;
118     return dst + prod;
119 }
120 
blend31_old(int src,int dst,int a31)121 static int blend31_old(int src, int dst, int a31) {
122     a31 += a31 >> 4;
123     return dst + ((src - dst) * a31 >> 5);
124 }
125 
126 // suppress unused code warning
127 static int (*blend_functions[])(int, int, int) = {
128     blend31,
129     blend31_slow,
130     blend31_round,
131     blend31_old
132 };
133 
test_blend31()134 static void test_blend31() {
135     int failed = 0;
136     int death = 0;
137     if (false) { // avoid bit rot, suppress warning
138         failed = (*blend_functions[0])(0,0,0);
139     }
140     for (int src = 0; src <= 255; src++) {
141         for (int dst = 0; dst <= 255; dst++) {
142             for (int a = 0; a <= 31; a++) {
143 //                int r0 = blend31(src, dst, a);
144 //                int r0 = blend31_round(src, dst, a);
145 //                int r0 = blend31_old(src, dst, a);
146                 int r0 = blend31_slow(src, dst, a);
147 
148                 float f = float_blend(src, dst, a / 31.f);
149                 int r1 = (int)f;
150                 int r2 = SkScalarRoundToInt(f);
151 
152                 if (r0 != r1 && r0 != r2) {
153                     SkDebugf("src:%d dst:%d a:%d result:%d float:%g\n",
154                                  src,   dst, a,        r0,      f);
155                     failed += 1;
156                 }
157                 if (r0 > 255) {
158                     death += 1;
159                     SkDebugf("death src:%d dst:%d a:%d result:%d float:%g\n",
160                                         src,   dst, a,        r0,      f);
161                 }
162             }
163         }
164     }
165     SkDebugf("---- failed %d death %d\n", failed, death);
166 }
167 
test_blend(skiatest::Reporter * reporter)168 static void test_blend(skiatest::Reporter* reporter) {
169     for (int src = 0; src <= 255; src++) {
170         for (int dst = 0; dst <= 255; dst++) {
171             for (int a = 0; a <= 255; a++) {
172                 int r0 = SkAlphaBlend255(src, dst, a);
173                 float f1 = float_blend(src, dst, a / 255.f);
174                 int r1 = SkScalarRoundToInt(f1);
175 
176                 if (r0 != r1) {
177                     float diff = sk_float_abs(f1 - r1);
178                     diff = sk_float_abs(diff - 0.5f);
179                     if (diff > (1 / 255.f)) {
180                         ERRORF(reporter, "src:%d dst:%d a:%d "
181                                "result:%d float:%g\n", src, dst, a, r0, f1);
182                     }
183                 }
184             }
185         }
186     }
187 }
188 
check_length(skiatest::Reporter * reporter,const SkPoint & p,SkScalar targetLen)189 static void check_length(skiatest::Reporter* reporter,
190                          const SkPoint& p, SkScalar targetLen) {
191     float x = SkScalarToFloat(p.fX);
192     float y = SkScalarToFloat(p.fY);
193     float len = sk_float_sqrt(x*x + y*y);
194 
195     len /= SkScalarToFloat(targetLen);
196 
197     REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
198 }
199 
nextFloat(SkRandom & rand)200 static float nextFloat(SkRandom& rand) {
201     SkFloatIntUnion data;
202     data.fSignBitInt = rand.nextU();
203     return data.fFloat;
204 }
205 
206 /*  returns true if a == b as resulting from (int)x. Since it is undefined
207  what to do if the float exceeds 2^32-1, we check for that explicitly.
208  */
equal_float_native_skia(float x,uint32_t ni,uint32_t si)209 static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
210     if (!(x == x)) {    // NAN
211         return ((int32_t)si) == SK_MaxS32 || ((int32_t)si) == SK_MinS32;
212     }
213     // for out of range, C is undefined, but skia always should return NaN32
214     if (x > SK_MaxS32) {
215         return ((int32_t)si) == SK_MaxS32;
216     }
217     if (x < -SK_MaxS32) {
218         return ((int32_t)si) == SK_MinS32;
219     }
220     return si == ni;
221 }
222 
assert_float_equal(skiatest::Reporter * reporter,const char op[],float x,uint32_t ni,uint32_t si)223 static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
224                                float x, uint32_t ni, uint32_t si) {
225     if (!equal_float_native_skia(x, ni, si)) {
226         ERRORF(reporter, "%s float %g bits %x native %x skia %x\n",
227                op, x, SkFloat2Bits(x), ni, si);
228     }
229 }
230 
test_float_cast(skiatest::Reporter * reporter,float x)231 static void test_float_cast(skiatest::Reporter* reporter, float x) {
232     int ix = (int)x;
233     int iix = SkFloatToIntCast(x);
234     assert_float_equal(reporter, "cast", x, ix, iix);
235 }
236 
test_float_floor(skiatest::Reporter * reporter,float x)237 static void test_float_floor(skiatest::Reporter* reporter, float x) {
238     int ix = (int)floor(x);
239     int iix = SkFloatToIntFloor(x);
240     assert_float_equal(reporter, "floor", x, ix, iix);
241 }
242 
test_float_round(skiatest::Reporter * reporter,float x)243 static void test_float_round(skiatest::Reporter* reporter, float x) {
244     double xx = x + 0.5;    // need intermediate double to avoid temp loss
245     int ix = (int)floor(xx);
246     int iix = SkFloatToIntRound(x);
247     assert_float_equal(reporter, "round", x, ix, iix);
248 }
249 
test_float_ceil(skiatest::Reporter * reporter,float x)250 static void test_float_ceil(skiatest::Reporter* reporter, float x) {
251     int ix = (int)ceil(x);
252     int iix = SkFloatToIntCeil(x);
253     assert_float_equal(reporter, "ceil", x, ix, iix);
254 }
255 
test_float_conversions(skiatest::Reporter * reporter,float x)256 static void test_float_conversions(skiatest::Reporter* reporter, float x) {
257     test_float_cast(reporter, x);
258     test_float_floor(reporter, x);
259     test_float_round(reporter, x);
260     test_float_ceil(reporter, x);
261 }
262 
test_int2float(skiatest::Reporter * reporter,int ival)263 static void test_int2float(skiatest::Reporter* reporter, int ival) {
264     float x0 = (float)ival;
265     float x1 = SkIntToFloatCast(ival);
266     REPORTER_ASSERT(reporter, x0 == x1);
267 }
268 
unittest_fastfloat(skiatest::Reporter * reporter)269 static void unittest_fastfloat(skiatest::Reporter* reporter) {
270     SkRandom rand;
271     size_t i;
272 
273     static const float gFloats[] = {
274         0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
275         0.000000001f, 1000000000.f,     // doesn't overflow
276         0.0000000001f, 10000000000.f    // does overflow
277     };
278     for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
279         test_float_conversions(reporter, gFloats[i]);
280         test_float_conversions(reporter, -gFloats[i]);
281     }
282 
283     for (int outer = 0; outer < 100; outer++) {
284         rand.setSeed(outer);
285         for (i = 0; i < 100000; i++) {
286             float x = nextFloat(rand);
287             test_float_conversions(reporter, x);
288         }
289 
290         test_int2float(reporter, 0);
291         test_int2float(reporter, 1);
292         test_int2float(reporter, -1);
293         for (i = 0; i < 100000; i++) {
294             // for now only test ints that are 24bits or less, since we don't
295             // round (down) large ints the same as IEEE...
296             int ival = rand.nextU() & 0xFFFFFF;
297             test_int2float(reporter, ival);
298             test_int2float(reporter, -ival);
299         }
300     }
301 }
302 
make_zero()303 static float make_zero() {
304     return sk_float_sin(0);
305 }
306 
unittest_isfinite(skiatest::Reporter * reporter)307 static void unittest_isfinite(skiatest::Reporter* reporter) {
308     float nan = sk_float_asin(2);
309     float inf = 1.0f / make_zero();
310     float big = 3.40282e+038f;
311 
312     REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf));
313     REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf));
314     REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf));
315     REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf));
316 
317     REPORTER_ASSERT(reporter,  SkScalarIsNaN(nan));
318     REPORTER_ASSERT(reporter, !SkScalarIsNaN(big));
319     REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big));
320     REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
321 
322     REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan));
323     REPORTER_ASSERT(reporter,  SkScalarIsFinite(big));
324     REPORTER_ASSERT(reporter,  SkScalarIsFinite(-big));
325     REPORTER_ASSERT(reporter,  SkScalarIsFinite(0));
326 }
327 
unittest_half(skiatest::Reporter * reporter)328 static void unittest_half(skiatest::Reporter* reporter) {
329     static const float gFloats[] = {
330         0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
331         -0.f, -1.f, -0.5f, -0.499999f, -0.5000001f, -1.f/3
332     };
333 
334     for (size_t i = 0; i < SK_ARRAY_COUNT(gFloats); ++i) {
335         SkHalf h = SkFloatToHalf(gFloats[i]);
336         float f = SkHalfToFloat(h);
337         REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, gFloats[i]));
338     }
339 
340     // check some special values
341     union FloatUnion {
342         uint32_t fU;
343         float    fF;
344     };
345 
346     static const FloatUnion largestPositiveHalf = { ((142 << 23) | (1023 << 13)) };
347     SkHalf h = SkFloatToHalf(largestPositiveHalf.fF);
348     float f = SkHalfToFloat(h);
349     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, largestPositiveHalf.fF));
350 
351     static const FloatUnion largestNegativeHalf = { (1u << 31) | (142u << 23) | (1023u << 13) };
352     h = SkFloatToHalf(largestNegativeHalf.fF);
353     f = SkHalfToFloat(h);
354     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, largestNegativeHalf.fF));
355 
356     static const FloatUnion smallestPositiveHalf = { 102 << 23 };
357     h = SkFloatToHalf(smallestPositiveHalf.fF);
358     f = SkHalfToFloat(h);
359     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(f, smallestPositiveHalf.fF));
360 
361     static const FloatUnion overflowHalf = { ((143 << 23) | (1023 << 13)) };
362     h = SkFloatToHalf(overflowHalf.fF);
363     f = SkHalfToFloat(h);
364     REPORTER_ASSERT(reporter, !SkScalarIsFinite(f) );
365 
366     static const FloatUnion underflowHalf = { 101 << 23 };
367     h = SkFloatToHalf(underflowHalf.fF);
368     f = SkHalfToFloat(h);
369     REPORTER_ASSERT(reporter, f == 0.0f );
370 
371     static const FloatUnion inf32 = { 255 << 23 };
372     h = SkFloatToHalf(inf32.fF);
373     f = SkHalfToFloat(h);
374     REPORTER_ASSERT(reporter, !SkScalarIsFinite(f) );
375 
376     static const FloatUnion nan32 = { 255 << 23 | 1 };
377     h = SkFloatToHalf(nan32.fF);
378     f = SkHalfToFloat(h);
379     REPORTER_ASSERT(reporter, SkScalarIsNaN(f) );
380 
381 }
382 
383 template <typename RSqrtFn>
test_rsqrt(skiatest::Reporter * reporter,RSqrtFn rsqrt)384 static void test_rsqrt(skiatest::Reporter* reporter, RSqrtFn rsqrt) {
385     const float maxRelativeError = 6.50196699e-4f;
386 
387     // test close to 0 up to 1
388     float input = 0.000001f;
389     for (int i = 0; i < 1000; ++i) {
390         float exact = 1.0f/sk_float_sqrt(input);
391         float estimate = rsqrt(input);
392         float relativeError = sk_float_abs(exact - estimate)/exact;
393         REPORTER_ASSERT(reporter, relativeError <= maxRelativeError);
394         input += 0.001f;
395     }
396 
397     // test 1 to ~100
398     input = 1.0f;
399     for (int i = 0; i < 1000; ++i) {
400         float exact = 1.0f/sk_float_sqrt(input);
401         float estimate = rsqrt(input);
402         float relativeError = sk_float_abs(exact - estimate)/exact;
403         REPORTER_ASSERT(reporter, relativeError <= maxRelativeError);
404         input += 0.01f;
405     }
406 
407     // test some big numbers
408     input = 1000000.0f;
409     for (int i = 0; i < 100; ++i) {
410         float exact = 1.0f/sk_float_sqrt(input);
411         float estimate = rsqrt(input);
412         float relativeError = sk_float_abs(exact - estimate)/exact;
413         REPORTER_ASSERT(reporter, relativeError <= maxRelativeError);
414         input += 754326.f;
415     }
416 }
417 
test_muldiv255(skiatest::Reporter * reporter)418 static void test_muldiv255(skiatest::Reporter* reporter) {
419     for (int a = 0; a <= 255; a++) {
420         for (int b = 0; b <= 255; b++) {
421             int ab = a * b;
422             float s = ab / 255.0f;
423             int round = (int)floorf(s + 0.5f);
424             int trunc = (int)floorf(s);
425 
426             int iround = SkMulDiv255Round(a, b);
427             int itrunc = SkMulDiv255Trunc(a, b);
428 
429             REPORTER_ASSERT(reporter, iround == round);
430             REPORTER_ASSERT(reporter, itrunc == trunc);
431 
432             REPORTER_ASSERT(reporter, itrunc <= iround);
433             REPORTER_ASSERT(reporter, iround <= a);
434             REPORTER_ASSERT(reporter, iround <= b);
435         }
436     }
437 }
438 
test_muldiv255ceiling(skiatest::Reporter * reporter)439 static void test_muldiv255ceiling(skiatest::Reporter* reporter) {
440     for (int c = 0; c <= 255; c++) {
441         for (int a = 0; a <= 255; a++) {
442             int product = (c * a + 255);
443             int expected_ceiling = (product + (product >> 8)) >> 8;
444             int webkit_ceiling = (c * a + 254) / 255;
445             REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling);
446             int skia_ceiling = SkMulDiv255Ceiling(c, a);
447             REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling);
448         }
449     }
450 }
451 
test_copysign(skiatest::Reporter * reporter)452 static void test_copysign(skiatest::Reporter* reporter) {
453     static const int32_t gTriples[] = {
454         // x, y, expected result
455         0, 0, 0,
456         0, 1, 0,
457         0, -1, 0,
458         1, 0, 1,
459         1, 1, 1,
460         1, -1, -1,
461         -1, 0, 1,
462         -1, 1, 1,
463         -1, -1, -1,
464     };
465     for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) {
466         REPORTER_ASSERT(reporter,
467                         SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]);
468         float x = (float)gTriples[i];
469         float y = (float)gTriples[i+1];
470         float expected = (float)gTriples[i+2];
471         REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected);
472     }
473 
474     SkRandom rand;
475     for (int j = 0; j < 1000; j++) {
476         int ix = rand.nextS();
477         REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix);
478         REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix);
479         REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix);
480         REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix);
481 
482         SkScalar sx = rand.nextSScalar1();
483         REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx);
484         REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
485         REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx);
486         REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
487     }
488 }
489 
DEF_TEST(Math,reporter)490 DEF_TEST(Math, reporter) {
491     int         i;
492     SkRandom    rand;
493 
494     // these should assert
495 #if 0
496     SkToS8(128);
497     SkToS8(-129);
498     SkToU8(256);
499     SkToU8(-5);
500 
501     SkToS16(32768);
502     SkToS16(-32769);
503     SkToU16(65536);
504     SkToU16(-5);
505 
506     if (sizeof(size_t) > 4) {
507         SkToS32(4*1024*1024);
508         SkToS32(-4*1024*1024);
509         SkToU32(5*1024*1024);
510         SkToU32(-5);
511     }
512 #endif
513 
514     test_muldiv255(reporter);
515     test_muldiv255ceiling(reporter);
516     test_copysign(reporter);
517 
518     {
519         SkScalar x = SK_ScalarNaN;
520         REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
521     }
522 
523     for (i = 0; i < 1000; i++) {
524         int value = rand.nextS16();
525         int max = rand.nextU16();
526 
527         int clamp = SkClampMax(value, max);
528         int clamp2 = value < 0 ? 0 : (value > max ? max : value);
529         REPORTER_ASSERT(reporter, clamp == clamp2);
530     }
531 
532     for (i = 0; i < 10000; i++) {
533         SkPoint p;
534 
535         // These random values are being treated as 32-bit-patterns, not as
536         // ints; calling SkIntToScalar() here produces crashes.
537         p.setLength((SkScalar) rand.nextS(),
538                     (SkScalar) rand.nextS(),
539                     SK_Scalar1);
540         check_length(reporter, p, SK_Scalar1);
541         p.setLength((SkScalar) (rand.nextS() >> 13),
542                     (SkScalar) (rand.nextS() >> 13),
543                     SK_Scalar1);
544         check_length(reporter, p, SK_Scalar1);
545     }
546 
547     {
548         SkFixed result = SkFixedDiv(100, 100);
549         REPORTER_ASSERT(reporter, result == SK_Fixed1);
550         result = SkFixedDiv(1, SK_Fixed1);
551         REPORTER_ASSERT(reporter, result == 1);
552     }
553 
554     unittest_fastfloat(reporter);
555     unittest_isfinite(reporter);
556     unittest_half(reporter);
557     test_rsqrt(reporter, sk_float_rsqrt);
558     test_rsqrt(reporter, sk_float_rsqrt_portable);
559 
560     for (i = 0; i < 10000; i++) {
561         SkFixed numer = rand.nextS();
562         SkFixed denom = rand.nextS();
563         SkFixed result = SkFixedDiv(numer, denom);
564         int64_t check = SkLeftShift((int64_t)numer, 16) / denom;
565 
566         (void)SkCLZ(numer);
567         (void)SkCLZ(denom);
568 
569         REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
570         if (check > SK_MaxS32) {
571             check = SK_MaxS32;
572         } else if (check < -SK_MaxS32) {
573             check = SK_MinS32;
574         }
575         if (result != (int32_t)check) {
576             ERRORF(reporter, "\nFixed Divide: %8x / %8x -> %8x %8x\n", numer, denom, result, check);
577         }
578         REPORTER_ASSERT(reporter, result == (int32_t)check);
579     }
580 
581     test_blend(reporter);
582 
583     if (false) test_floor(reporter);
584 
585     // disable for now
586     if (false) test_blend31();  // avoid bit rot, suppress warning
587 
588     test_muldivround(reporter);
589     test_clz(reporter);
590 }
591 
592 template <typename T> struct PairRec {
593     T   fYin;
594     T   fYang;
595 };
596 
DEF_TEST(TestEndian,reporter)597 DEF_TEST(TestEndian, reporter) {
598     static const PairRec<uint16_t> g16[] = {
599         { 0x0,      0x0     },
600         { 0xFFFF,   0xFFFF  },
601         { 0x1122,   0x2211  },
602     };
603     static const PairRec<uint32_t> g32[] = {
604         { 0x0,          0x0         },
605         { 0xFFFFFFFF,   0xFFFFFFFF  },
606         { 0x11223344,   0x44332211  },
607     };
608     static const PairRec<uint64_t> g64[] = {
609         { 0x0,      0x0                             },
610         { 0xFFFFFFFFFFFFFFFFULL,  0xFFFFFFFFFFFFFFFFULL  },
611         { 0x1122334455667788ULL,  0x8877665544332211ULL  },
612     };
613 
614     REPORTER_ASSERT(reporter, 0x1122 == SkTEndianSwap16<0x2211>::value);
615     REPORTER_ASSERT(reporter, 0x11223344 == SkTEndianSwap32<0x44332211>::value);
616     REPORTER_ASSERT(reporter, 0x1122334455667788ULL == SkTEndianSwap64<0x8877665544332211ULL>::value);
617 
618     for (size_t i = 0; i < SK_ARRAY_COUNT(g16); ++i) {
619         REPORTER_ASSERT(reporter, g16[i].fYang == SkEndianSwap16(g16[i].fYin));
620     }
621     for (size_t i = 0; i < SK_ARRAY_COUNT(g32); ++i) {
622         REPORTER_ASSERT(reporter, g32[i].fYang == SkEndianSwap32(g32[i].fYin));
623     }
624     for (size_t i = 0; i < SK_ARRAY_COUNT(g64); ++i) {
625         REPORTER_ASSERT(reporter, g64[i].fYang == SkEndianSwap64(g64[i].fYin));
626     }
627 }
628 
629 template <typename T>
test_divmod(skiatest::Reporter * r)630 static void test_divmod(skiatest::Reporter* r) {
631     const struct {
632         T numer;
633         T denom;
634     } kEdgeCases[] = {
635         {(T)17, (T)17},
636         {(T)17, (T)4},
637         {(T)0,  (T)17},
638         // For unsigned T these negatives are just some large numbers.  Doesn't hurt to test them.
639         {(T)-17, (T)-17},
640         {(T)-17, (T)4},
641         {(T)17,  (T)-4},
642         {(T)-17, (T)-4},
643     };
644 
645     for (size_t i = 0; i < SK_ARRAY_COUNT(kEdgeCases); i++) {
646         const T numer = kEdgeCases[i].numer;
647         const T denom = kEdgeCases[i].denom;
648         T div, mod;
649         SkTDivMod(numer, denom, &div, &mod);
650         REPORTER_ASSERT(r, numer/denom == div);
651         REPORTER_ASSERT(r, numer%denom == mod);
652     }
653 
654     SkRandom rand;
655     for (size_t i = 0; i < 10000; i++) {
656         const T numer = (T)rand.nextS();
657         T denom = 0;
658         while (0 == denom) {
659             denom = (T)rand.nextS();
660         }
661         T div, mod;
662         SkTDivMod(numer, denom, &div, &mod);
663         REPORTER_ASSERT(r, numer/denom == div);
664         REPORTER_ASSERT(r, numer%denom == mod);
665     }
666 }
667 
DEF_TEST(divmod_u8,r)668 DEF_TEST(divmod_u8, r) {
669     test_divmod<uint8_t>(r);
670 }
671 
DEF_TEST(divmod_u16,r)672 DEF_TEST(divmod_u16, r) {
673     test_divmod<uint16_t>(r);
674 }
675 
DEF_TEST(divmod_u32,r)676 DEF_TEST(divmod_u32, r) {
677     test_divmod<uint32_t>(r);
678 }
679 
DEF_TEST(divmod_u64,r)680 DEF_TEST(divmod_u64, r) {
681     test_divmod<uint64_t>(r);
682 }
683 
DEF_TEST(divmod_s8,r)684 DEF_TEST(divmod_s8, r) {
685     test_divmod<int8_t>(r);
686 }
687 
DEF_TEST(divmod_s16,r)688 DEF_TEST(divmod_s16, r) {
689     test_divmod<int16_t>(r);
690 }
691 
DEF_TEST(divmod_s32,r)692 DEF_TEST(divmod_s32, r) {
693     test_divmod<int32_t>(r);
694 }
695 
DEF_TEST(divmod_s64,r)696 DEF_TEST(divmod_s64, r) {
697     test_divmod<int64_t>(r);
698 }
699