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