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