Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MathTest.cpp
Go to the documentation of this file.
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
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
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
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
68static float sk_fsel(float pred, float result_ge, float result_lt) {
69 return pred >= 0 ? result_ge : result_lt;
70}
71
72static 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
78static float std_floor(float x) {
79 return std::floor(x);
80}
81
82static 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
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
104static float float_blend(int src, int dst, float unit) {
105 return dst + (src - dst) * unit;
106}
107
108static 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
113static 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
119static 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
125static 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
131static int (*blend_functions[])(int, int, int) = {
132 blend31,
136};
137
138static 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
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
183template <typename T>
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
195
200
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
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);
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);
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);
269
270 static const FloatUnion nan32 = { 255 << 23 | 1 };
271 h = SkFloatToHalf(nan32.fF);
272 f = SkHalfToFloat(h);
274
275}
276
277template <typename RSqrtFn>
278static 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
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
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
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) {
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();
378 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
380 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
381 }
382}
383
385 // these values should fail (overflow/underflow) trying to normalize
386 const SkVector fail[] = {
387 { 0, 0 },
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
399DEF_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
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);
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
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
523
524 {
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);
538 p.setLength((SkScalar) (rand.nextS() >> 13),
539 (SkScalar) (rand.nextS() >> 13),
540 SK_Scalar1);
542 }
543
544 {
545 SkFixed result = SkFixedDiv(100, 100);
549 result = SkFixedDiv(10 - 1, SK_Fixed1 * 3);
551 }
552
553 {
557 }
558
560 unittest_isfinite<float>(reporter);
561 unittest_isfinite<double>(reporter);
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
576 if (check > SK_MaxS32) {
578 } else if (check < -SK_MaxS32) {
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
595}
596
597template <typename T> struct PairRec {
600};
601
602DEF_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
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
634template <typename T>
636#if !defined(__MSVC_RUNTIME_CHECKS)
637 const struct {
638 T numer;
639 T denom;
640 } kEdgeCases[] = {
641 {(T)17, (T)17},
642 {(T)17, (T)4},
643 {(T)0, (T)17},
644 // For unsigned T these negatives are just some large numbers. Doesn't hurt to test them.
645 {(T)-17, (T)-17},
646 {(T)-17, (T)4},
647 {(T)17, (T)-4},
648 {(T)-17, (T)-4},
649 };
650
651 for (size_t i = 0; i < std::size(kEdgeCases); i++) {
652 const T numer = kEdgeCases[i].numer;
653 const T denom = kEdgeCases[i].denom;
654 T div, mod;
655 SkTDivMod(numer, denom, &div, &mod);
656 REPORTER_ASSERT(r, numer/denom == div);
657 REPORTER_ASSERT(r, numer%denom == mod);
658 }
659
660 SkRandom rand;
661 for (size_t i = 0; i < 10000; i++) {
662 const T numer = (T)rand.nextS();
663 T denom = 0;
664 while (0 == denom) {
665 denom = (T)rand.nextS();
666 }
667 T div, mod;
668 SkTDivMod(numer, denom, &div, &mod);
669 REPORTER_ASSERT(r, numer/denom == div);
670 REPORTER_ASSERT(r, numer%denom == mod);
671 }
672#endif
673}
674
675DEF_TEST(divmod_u8, r) {
676 test_divmod<uint8_t>(r);
677}
678
679DEF_TEST(divmod_u16, r) {
680 test_divmod<uint16_t>(r);
681}
682
683DEF_TEST(divmod_u32, r) {
684 test_divmod<uint32_t>(r);
685}
686
687DEF_TEST(divmod_u64, r) {
688 test_divmod<uint64_t>(r);
689}
690
691DEF_TEST(divmod_s8, r) {
692 test_divmod<int8_t>(r);
693}
694
695DEF_TEST(divmod_s16, r) {
696 test_divmod<int16_t>(r);
697}
698
699DEF_TEST(divmod_s32, r) {
700 test_divmod<int32_t>(r);
701}
702
703DEF_TEST(divmod_s64, r) {
704 test_divmod<int64_t>(r);
705}
706
707static void test_nextsizepow2(skiatest::Reporter* r, size_t test, size_t expectedAns) {
708 size_t ans = GrNextSizePow2(test);
709
710 REPORTER_ASSERT(r, ans == expectedAns);
711 //SkDebugf("0x%zx -> 0x%zx (0x%zx)\n", test, ans, expectedAns);
712}
713
715 constexpr int kNumSizeTBits = 8 * sizeof(size_t);
716
717 size_t test = 0, expectedAns = 1;
718
719 test_nextsizepow2(reporter, test, expectedAns);
720
721 test = 1; expectedAns = 1;
722
723 for (int i = 1; i < kNumSizeTBits; ++i) {
724 test_nextsizepow2(reporter, test, expectedAns);
725
726 test++;
727 expectedAns <<= 1;
728
729 test_nextsizepow2(reporter, test, expectedAns);
730
731 test = expectedAns;
732 }
733
734 // For the remaining three tests there is no higher power (of 2)
735 test = 0x1;
736 test <<= kNumSizeTBits-1;
738
739 test++;
741
742 test_nextsizepow2(reporter, SIZE_MAX, SIZE_MAX);
743}
744
745DEF_TEST(FloatSaturate32, reporter) {
746 const struct {
747 float fFloat;
748 int fExpectedInt;
749 } recs[] = {
750 { 0, 0 },
751 { 100.5f, 100 },
754 { SK_MaxS32 * 100.0f, SK_MaxS32FitsInFloat },
755 { SK_MinS32 * 100.0f, SK_MinS32FitsInFloat },
759 };
760
761 for (auto r : recs) {
762 int i = sk_float_saturate2int(r.fFloat);
763 REPORTER_ASSERT(reporter, r.fExpectedInt == i);
764
765 // Ensure that SkTPin bounds even non-finite values (including NaN)
766 SkScalar p = SkTPin<SkScalar>(r.fFloat, 0, 100);
767 REPORTER_ASSERT(reporter, p >= 0 && p <= 100);
768 }
769}
770
771DEF_TEST(FloatSaturate64, reporter) {
772 const struct {
773 float fFloat;
774 int64_t fExpected64;
775 } recs[] = {
776 { 0, 0 },
777 { 100.5f, 100 },
780 { SK_MaxS64 * 100.0f, SK_MaxS64FitsInFloat },
781 { SK_MinS64 * 100.0f, SK_MinS64FitsInFloat },
785 };
786
787 for (auto r : recs) {
788 int64_t i = sk_float_saturate2int64(r.fFloat);
789 REPORTER_ASSERT(reporter, r.fExpected64 == i);
790 }
791}
792
793DEF_TEST(DoubleSaturate32, reporter) {
794 const struct {
795 double fDouble;
796 int fExpectedInt;
797 } recs[] = {
798 { 0, 0 },
799 { 100.5, 100 },
800 { SK_MaxS32, SK_MaxS32 },
801 { SK_MinS32, SK_MinS32 },
802 { SK_MaxS32 - 1, SK_MaxS32 - 1 },
803 { SK_MinS32 + 1, SK_MinS32 + 1 },
804 { SK_MaxS32 * 100.0, SK_MaxS32 },
805 { SK_MinS32 * 100.0, SK_MinS32 },
809 };
810
811 for (auto r : recs) {
812 int i = sk_double_saturate2int(r.fDouble);
813 REPORTER_ASSERT(reporter, r.fExpectedInt == i);
814 }
815}
816
817#if defined(__ARM_NEON)
818 #include <arm_neon.h>
819
820 DEF_TEST(NeonU16Div255, r) {
821
822 for (int v = 0; v <= 255*255; v++) {
823 int want = (v + 127)/255;
824
825 uint16x8_t V = vdupq_n_u16(v);
826 int got = vrshrq_n_u16(vrsraq_n_u16(V, V, 8), 8)[0];
827
828 if (got != want) {
829 SkDebugf("%d -> %d, want %d\n", v, got, want);
830 }
831 REPORTER_ASSERT(r, got == want);
832 }
833 }
834
835#endif
static void fail(const SkString &err)
Definition DM.cpp:234
reporter
static void round(SkPoint *p)
static float float_blend(int src, int dst, float unit)
Definition MathTest.cpp:104
static int blend31_old(int src, int dst, int a31)
Definition MathTest.cpp:125
static void test_copysign(skiatest::Reporter *reporter)
Definition MathTest.cpp:346
static void test_muldiv255ceiling(skiatest::Reporter *reporter)
Definition MathTest.cpp:333
static void test_divmod(skiatest::Reporter *r)
Definition MathTest.cpp:635
static int blend31_slow(int src, int dst, int a31)
Definition MathTest.cpp:113
static void unittest_isfinite(skiatest::Reporter *reporter)
Definition MathTest.cpp:184
static void huge_vector_normalize(skiatest::Reporter *reporter)
Definition MathTest.cpp:384
static float fast_floor(float x)
Definition MathTest.cpp:72
static void check_length(skiatest::Reporter *reporter, const SkPoint &p, SkScalar targetLen)
Definition MathTest.cpp:172
static void test_blend31()
Definition MathTest.cpp:138
static int blend31(int src, int dst, int a31)
Definition MathTest.cpp:108
static void test_floor(skiatest::Reporter *reporter)
Definition MathTest.cpp:91
static void test_clz(skiatest::Reporter *reporter)
Definition MathTest.cpp:28
static int blend31_round(int src, int dst, int a31)
Definition MathTest.cpp:119
static float sk_fsel(float pred, float result_ge, float result_lt)
Definition MathTest.cpp:68
static void test_ctz(skiatest::Reporter *reporter)
Definition MathTest.cpp:47
static void test_muldiv255(skiatest::Reporter *reporter)
Definition MathTest.cpp:312
static void test_nextsizepow2(skiatest::Reporter *r, size_t test, size_t expectedAns)
Definition MathTest.cpp:707
static void test_floor_value(skiatest::Reporter *reporter, float value)
Definition MathTest.cpp:82
static void test_rsqrt(skiatest::Reporter *reporter, RSqrtFn rsqrt)
Definition MathTest.cpp:278
static float std_floor(float x)
Definition MathTest.cpp:78
static int(* blend_functions[])(int, int, int)
Definition MathTest.cpp:131
static void unittest_half(skiatest::Reporter *reporter)
Definition MathTest.cpp:222
#define check(reporter, ref, unref, make, kill)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static uint64_t SkEndianSwap64(uint64_t value)
Definition SkEndian.h:85
static uint16_t SkEndianSwap16(uint16_t value)
Definition SkEndian.h:33
static constexpr uint32_t SkEndianSwap32(uint32_t value)
Definition SkEndian.h:56
int32_t SkFixed
Definition SkFixed.h:25
#define SK_Fixed1
Definition SkFixed.h:26
static SkFixed SkFixedCeilToFixed(SkFixed x)
Definition SkFixed.h:83
#define SkFixedDiv(numer, denom)
Definition SkFixed.h:93
static SkFixed SkFixedFloorToFixed(SkFixed x)
Definition SkFixed.h:86
static SkFixed SkFixedRoundToFixed(SkFixed x)
Definition SkFixed.h:80
constexpr int64_t SK_MinS64FitsInFloat
static bool SkIsFinite(T x, Pack... values)
static bool SkIsNaN(T x)
static constexpr int64_t sk_float_saturate2int64(float x)
constexpr int64_t SK_MaxS64FitsInFloat
constexpr int SK_MinS32FitsInFloat
static float sk_float_rsqrt_portable(float x)
constexpr int SK_MaxS32FitsInFloat
static float sk_float_rsqrt(float x)
static constexpr int sk_double_saturate2int(double x)
static constexpr int sk_float_saturate2int(float x)
float SkHalfToFloat(SkHalf h)
Definition SkHalf.cpp:24
SkHalf SkFloatToHalf(float f)
Definition SkHalf.cpp:16
uint16_t SkHalf
Definition SkHalf.h:16
int SkNthSet(uint32_t target, int n)
static int SkPopCount(uint32_t n)
Definition SkMathPriv.h:136
constexpr int SkCTZ_portable(uint32_t x)
Returns the number of trailing zero bits (0...32)
Definition SkMathPriv.h:193
static int SkCTZ(uint32_t mask)
Definition SkMathPriv.h:224
static U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b)
Definition SkMathPriv.h:92
static U8CPU SkMulDiv255Ceiling(U8CPU a, U8CPU b)
Definition SkMathPriv.h:102
void SkTDivMod(In numer, In denom, Out *div, Out *mod)
Definition SkMathPriv.h:38
static int32_t SkCopySign32(int32_t x, int32_t y)
Definition SkMathPriv.h:56
constexpr int SkCLZ_portable(uint32_t x)
Returns the number of leading zero bits (0...32)
Definition SkMathPriv.h:149
static int SkCLZ(uint32_t mask)
Definition SkMathPriv.h:186
static size_t GrNextSizePow2(size_t n)
Definition SkMathPriv.h:309
static constexpr int64_t SK_MaxS64
Definition SkMath.h:25
static U8CPU SkMulDiv255Round(U16CPU a, U16CPU b)
Definition SkMath.h:73
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition SkMath.h:37
static constexpr int32_t SK_NaN32
Definition SkMath.h:23
static constexpr int32_t SK_MinS32
Definition SkMath.h:22
static constexpr int64_t SK_MinS64
Definition SkMath.h:26
static constexpr int32_t SK_MaxS32
Definition SkMath.h:21
#define SkScalarCopySign(x, y)
Definition SkScalar.h:40
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:107
#define SK_Scalar1
Definition SkScalar.h:18
#define SK_ScalarNaN
Definition SkScalar.h:28
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
#define SK_ScalarInfinity
Definition SkScalar.h:26
#define SK_ScalarNegativeInfinity
Definition SkScalar.h:27
constexpr int8_t SkToS8(S x)
Definition SkTo.h:21
constexpr uint16_t SkToU16(S x)
Definition SkTo.h:24
constexpr int32_t SkToS32(S x)
Definition SkTo.h:25
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22
constexpr int16_t SkToS16(S x)
Definition SkTo.h:23
constexpr uint32_t SkToU32(S x)
Definition SkTo.h:26
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define ERRORF(r,...)
Definition Test.h:293
Vec2Value v2
Type::kYUV Type::kRGBA() int(0.7 *637)
uint32_t nextU()
Definition SkRandom.h:42
int32_t nextS()
Definition SkRandom.h:50
uint32_t nextULessThan(uint32_t count)
Definition SkRandom.h:93
SkScalar nextSScalar1()
Definition SkRandom.h:113
uint32_t nextRangeU(uint32_t min, uint32_t max)
Definition SkRandom.h:80
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct s
struct MyStruct a[10]
uint8_t value
GAsyncResult * result
T __attribute__((ext_vector_type(N))) V
double y
double x
Definition ab.py:1
Definition ref_ptr.h:256
SkScalar h
#define T