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