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