xref: /third_party/skia/tests/MathTest.cpp (revision cb93a386)
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
23static 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
42static 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
63static float sk_fsel(float pred, float result_ge, float result_lt) {
64    return pred >= 0 ? result_ge : result_lt;
65}
66
67static 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
73static float std_floor(float x) {
74    return sk_float_floor(x);
75}
76
77static 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
86static 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
99static float float_blend(int src, int dst, float unit) {
100    return dst + (src - dst) * unit;
101}
102
103static 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
108static 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
114static 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
120static 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
126static int (*blend_functions[])(int, int, int) = {
127    blend31,
128    blend31_slow,
129    blend31_round,
130    blend31_old
131};
132
133static 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
167static 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
178static 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
199static 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
254template <typename RSqrtFn>
255static 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
289static 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
331static 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
352static 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
365static 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
403static 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
418DEF_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
519template <typename T> struct PairRec {
520    T   fYin;
521    T   fYang;
522};
523
524DEF_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
556template <typename T>
557static 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
597DEF_TEST(divmod_u8, r) {
598    test_divmod<uint8_t>(r);
599}
600
601DEF_TEST(divmod_u16, r) {
602    test_divmod<uint16_t>(r);
603}
604
605DEF_TEST(divmod_u32, r) {
606    test_divmod<uint32_t>(r);
607}
608
609DEF_TEST(divmod_u64, r) {
610    test_divmod<uint64_t>(r);
611}
612
613DEF_TEST(divmod_s8, r) {
614    test_divmod<int8_t>(r);
615}
616
617DEF_TEST(divmod_s16, r) {
618    test_divmod<int16_t>(r);
619}
620
621DEF_TEST(divmod_s32, r) {
622    test_divmod<int32_t>(r);
623}
624
625DEF_TEST(divmod_s64, r) {
626    test_divmod<int64_t>(r);
627}
628
629static 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
636DEF_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
667DEF_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
693DEF_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
715DEF_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
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
759DEF_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