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