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