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