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