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