Flutter Engine
The Flutter Engine
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));
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)));
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
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) {
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>
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
324 REPORTER_ASSERT(reporter, itrunc == trunc);
325
326 REPORTER_ASSERT(reporter, itrunc <= iround);
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
Definition: FontMgrTest.cpp:39
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
DEF_TEST(PopCount, reporter)
Definition: MathTest.cpp:399
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)
Definition: RefCntTest.cpp:85
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
static constexpr bool SkIsNaN(T x)
constexpr int64_t SK_MinS64FitsInFloat
static bool SkIsFinite(T x, Pack... values)
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)
Definition: SkMathPriv.cpp:53
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 REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
Vec2Value v2
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
static float max(float r, float g, float b)
Definition: hsl.cpp:49
T __attribute__((ext_vector_type(N))) V
double y
double x
SI I32 iround(F v)
Definition: ab.py:1
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
SIN Vec< N, float > trunc(const Vec< N, float > &x)
Definition: SkVx.h:704
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition: SkVx.h:706
SIN Vec< N, float > floor(const Vec< N, float > &x)
Definition: SkVx.h:703
Definition: ref_ptr.h:256
SkScalar h
#define T
Definition: precompiler.cc:65