1#include "Test.h" 2#include "SkFloatingPoint.h" 3#include "SkPoint.h" 4#include "SkRandom.h" 5 6#if 0 7static U8CPU premul_fast(U8CPU a, U8CPU x) { 8 return a * x * 32897 >> 23; 9} 10 11static U8CPU premul_trunc(U8CPU a, U8CPU x) { 12 double result = a * x; 13 result /= 255.0; 14 return (unsigned)floor(result + 0.0); 15} 16 17static U8CPU premul_round(U8CPU a, U8CPU x) { 18 double result = a * x; 19 result /= 255.0; 20 return (unsigned)floor(result + 0.5); 21} 22 23static void test_premul(skiatest::Reporter* reporter) { 24 for (int a = 0; a <= 255; a++) { 25 for (int x = 0; x <= 255; x++) { 26 unsigned curr_trunc = SkMulDiv255Trunc(a, x); 27 unsigned curr_round = SkMulDiv255Round(a, x); 28 unsigned fast = premul_fast(a, x); 29 unsigned slow_round = premul_round(a, x); 30 unsigned slow_trunc = premul_trunc(a, x); 31 if (fast != slow || curr != fast) { 32 SkDebugf("---- premul(%d %d) curr=%d fast=%d slow=%d\n", a, x, 33 curr, fast, slow); 34 } 35 } 36 } 37} 38#endif 39 40#if defined(SkLONGLONG) 41static int symmetric_fixmul(int a, int b) { 42 int sa = SkExtractSign(a); 43 int sb = SkExtractSign(b); 44 45 a = SkApplySign(a, sa); 46 b = SkApplySign(b, sb); 47 48#if 1 49 int c = (int)(((SkLONGLONG)a * b) >> 16); 50 51 return SkApplySign(c, sa ^ sb); 52#else 53 SkLONGLONG ab = (SkLONGLONG)a * b; 54 if (sa ^ sb) { 55 ab = -ab; 56 } 57 return ab >> 16; 58#endif 59} 60#endif 61 62static void check_length(skiatest::Reporter* reporter, 63 const SkPoint& p, SkScalar targetLen) { 64#ifdef SK_CAN_USE_FLOAT 65 float x = SkScalarToFloat(p.fX); 66 float y = SkScalarToFloat(p.fY); 67 float len = sk_float_sqrt(x*x + y*y); 68 69 len /= SkScalarToFloat(targetLen); 70 71 REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f); 72#endif 73} 74 75#if defined(SK_CAN_USE_FLOAT) 76 77static float nextFloat(SkRandom& rand) { 78 SkFloatIntUnion data; 79 data.fSignBitInt = rand.nextU(); 80 return data.fFloat; 81} 82 83/* returns true if a == b as resulting from (int)x. Since it is undefined 84 what to do if the float exceeds 2^32-1, we check for that explicitly. 85 */ 86static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) { 87 if (!(x == x)) { // NAN 88 return si == SK_MaxS32 || si == SK_MinS32; 89 } 90 // for out of range, C is undefined, but skia always should return NaN32 91 if (x > SK_MaxS32) { 92 return si == SK_MaxS32; 93 } 94 if (x < -SK_MaxS32) { 95 return si == SK_MinS32; 96 } 97 return si == ni; 98} 99 100static void assert_float_equal(skiatest::Reporter* reporter, const char op[], 101 float x, uint32_t ni, uint32_t si) { 102 if (!equal_float_native_skia(x, ni, si)) { 103 SkString desc; 104 desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si); 105 reporter->reportFailed(desc); 106 } 107} 108 109static void test_float_cast(skiatest::Reporter* reporter, float x) { 110 int ix = (int)x; 111 int iix = SkFloatToIntCast(x); 112 assert_float_equal(reporter, "cast", x, ix, iix); 113} 114 115static void test_float_floor(skiatest::Reporter* reporter, float x) { 116 int ix = (int)floor(x); 117 int iix = SkFloatToIntFloor(x); 118 assert_float_equal(reporter, "floor", x, ix, iix); 119} 120 121static void test_float_round(skiatest::Reporter* reporter, float x) { 122 double xx = x + 0.5; // need intermediate double to avoid temp loss 123 int ix = (int)floor(xx); 124 int iix = SkFloatToIntRound(x); 125 assert_float_equal(reporter, "round", x, ix, iix); 126} 127 128static void test_float_ceil(skiatest::Reporter* reporter, float x) { 129 int ix = (int)ceil(x); 130 int iix = SkFloatToIntCeil(x); 131 assert_float_equal(reporter, "ceil", x, ix, iix); 132} 133 134static void test_float_conversions(skiatest::Reporter* reporter, float x) { 135 test_float_cast(reporter, x); 136 test_float_floor(reporter, x); 137 test_float_round(reporter, x); 138 test_float_ceil(reporter, x); 139} 140 141static void test_int2float(skiatest::Reporter* reporter, int ival) { 142 float x0 = (float)ival; 143 float x1 = SkIntToFloatCast(ival); 144 float x2 = SkIntToFloatCast_NoOverflowCheck(ival); 145 REPORTER_ASSERT(reporter, x0 == x1); 146 REPORTER_ASSERT(reporter, x0 == x2); 147} 148 149static void unittest_fastfloat(skiatest::Reporter* reporter) { 150 SkRandom rand; 151 size_t i; 152 153 static const float gFloats[] = { 154 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3, 155 0.000000001f, 1000000000.f, // doesn't overflow 156 0.0000000001f, 10000000000.f // does overflow 157 }; 158 for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) { 159 test_float_conversions(reporter, gFloats[i]); 160 test_float_conversions(reporter, -gFloats[i]); 161 } 162 163 for (int outer = 0; outer < 100; outer++) { 164 rand.setSeed(outer); 165 for (i = 0; i < 100000; i++) { 166 float x = nextFloat(rand); 167 test_float_conversions(reporter, x); 168 } 169 170 test_int2float(reporter, 0); 171 test_int2float(reporter, 1); 172 test_int2float(reporter, -1); 173 for (i = 0; i < 100000; i++) { 174 // for now only test ints that are 24bits or less, since we don't 175 // round (down) large ints the same as IEEE... 176 int ival = rand.nextU() & 0xFFFFFF; 177 test_int2float(reporter, ival); 178 test_int2float(reporter, -ival); 179 } 180 } 181} 182 183#ifdef SK_SCALAR_IS_FLOAT 184static float make_zero() { 185 return sk_float_sin(0); 186} 187#endif 188 189static void unittest_isfinite(skiatest::Reporter* reporter) { 190#ifdef SK_SCALAR_IS_FLOAT 191 float nan = sk_float_asin(2); 192 float inf = 1.0 / make_zero(); 193 float big = 3.40282e+038; 194 195 REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf)); 196 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf)); 197 REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf)); 198 REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf)); 199#else 200 SkFixed nan = SK_FixedNaN; 201 SkFixed big = SK_FixedMax; 202#endif 203 204 REPORTER_ASSERT(reporter, SkScalarIsNaN(nan)); 205 REPORTER_ASSERT(reporter, !SkScalarIsNaN(big)); 206 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big)); 207 REPORTER_ASSERT(reporter, !SkScalarIsNaN(0)); 208 209 REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan)); 210 REPORTER_ASSERT(reporter, SkScalarIsFinite(big)); 211 REPORTER_ASSERT(reporter, SkScalarIsFinite(-big)); 212 REPORTER_ASSERT(reporter, SkScalarIsFinite(0)); 213} 214 215#endif 216 217static void test_muldiv255(skiatest::Reporter* reporter) { 218#ifdef SK_CAN_USE_FLOAT 219 for (int a = 0; a <= 255; a++) { 220 for (int b = 0; b <= 255; b++) { 221 int ab = a * b; 222 float s = ab / 255.0f; 223 int round = (int)floorf(s + 0.5f); 224 int trunc = (int)floorf(s); 225 226 int iround = SkMulDiv255Round(a, b); 227 int itrunc = SkMulDiv255Trunc(a, b); 228 229 REPORTER_ASSERT(reporter, iround == round); 230 REPORTER_ASSERT(reporter, itrunc == trunc); 231 232 REPORTER_ASSERT(reporter, itrunc <= iround); 233 REPORTER_ASSERT(reporter, iround <= a); 234 REPORTER_ASSERT(reporter, iround <= b); 235 } 236 } 237#endif 238} 239 240static void test_muldiv255ceiling(skiatest::Reporter* reporter) { 241 for (int c = 0; c <= 255; c++) { 242 for (int a = 0; a <= 255; a++) { 243 int product = (c * a + 255); 244 int expected_ceiling = (product + (product >> 8)) >> 8; 245 int webkit_ceiling = (c * a + 254) / 255; 246 REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling); 247 int skia_ceiling = SkMulDiv255Ceiling(c, a); 248 REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling); 249 } 250 } 251} 252 253static void test_copysign(skiatest::Reporter* reporter) { 254 static const int32_t gTriples[] = { 255 // x, y, expected result 256 0, 0, 0, 257 0, 1, 0, 258 0, -1, 0, 259 1, 0, 1, 260 1, 1, 1, 261 1, -1, -1, 262 -1, 0, 1, 263 -1, 1, 1, 264 -1, -1, -1, 265 }; 266 for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) { 267 REPORTER_ASSERT(reporter, 268 SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]); 269#ifdef SK_CAN_USE_FLOAT 270 float x = (float)gTriples[i]; 271 float y = (float)gTriples[i+1]; 272 float expected = (float)gTriples[i+2]; 273 REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected); 274#endif 275 } 276 277 SkRandom rand; 278 for (int j = 0; j < 1000; j++) { 279 int ix = rand.nextS(); 280 REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix); 281 REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix); 282 REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix); 283 REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix); 284 285 SkScalar sx = rand.nextSScalar1(); 286 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx); 287 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx); 288 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx); 289 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx); 290 } 291} 292 293static void TestMath(skiatest::Reporter* reporter) { 294 int i; 295 int32_t x; 296 SkRandom rand; 297 298 // these should assert 299#if 0 300 SkToS8(128); 301 SkToS8(-129); 302 SkToU8(256); 303 SkToU8(-5); 304 305 SkToS16(32768); 306 SkToS16(-32769); 307 SkToU16(65536); 308 SkToU16(-5); 309 310 if (sizeof(size_t) > 4) { 311 SkToS32(4*1024*1024); 312 SkToS32(-4*1024*1024); 313 SkToU32(5*1024*1024); 314 SkToU32(-5); 315 } 316#endif 317 318 test_muldiv255(reporter); 319 test_muldiv255ceiling(reporter); 320 test_copysign(reporter); 321 322 { 323 SkScalar x = SK_ScalarNaN; 324 REPORTER_ASSERT(reporter, SkScalarIsNaN(x)); 325 } 326 327 for (i = 1; i <= 10; i++) { 328 x = SkCubeRootBits(i*i*i, 11); 329 REPORTER_ASSERT(reporter, x == i); 330 } 331 332 x = SkFixedSqrt(SK_Fixed1); 333 REPORTER_ASSERT(reporter, x == SK_Fixed1); 334 x = SkFixedSqrt(SK_Fixed1/4); 335 REPORTER_ASSERT(reporter, x == SK_Fixed1/2); 336 x = SkFixedSqrt(SK_Fixed1*4); 337 REPORTER_ASSERT(reporter, x == SK_Fixed1*2); 338 339 x = SkFractSqrt(SK_Fract1); 340 REPORTER_ASSERT(reporter, x == SK_Fract1); 341 x = SkFractSqrt(SK_Fract1/4); 342 REPORTER_ASSERT(reporter, x == SK_Fract1/2); 343 x = SkFractSqrt(SK_Fract1/16); 344 REPORTER_ASSERT(reporter, x == SK_Fract1/4); 345 346 for (i = 1; i < 100; i++) { 347 x = SkFixedSqrt(SK_Fixed1 * i * i); 348 REPORTER_ASSERT(reporter, x == SK_Fixed1 * i); 349 } 350 351 for (i = 0; i < 1000; i++) { 352 int value = rand.nextS16(); 353 int max = rand.nextU16(); 354 355 int clamp = SkClampMax(value, max); 356 int clamp2 = value < 0 ? 0 : (value > max ? max : value); 357 REPORTER_ASSERT(reporter, clamp == clamp2); 358 } 359 360 for (i = 0; i < 10000; i++) { 361 SkPoint p; 362 363 p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1); 364 check_length(reporter, p, SK_Scalar1); 365 p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1); 366 check_length(reporter, p, SK_Scalar1); 367 } 368 369 { 370 SkFixed result = SkFixedDiv(100, 100); 371 REPORTER_ASSERT(reporter, result == SK_Fixed1); 372 result = SkFixedDiv(1, SK_Fixed1); 373 REPORTER_ASSERT(reporter, result == 1); 374 } 375 376#ifdef SK_CAN_USE_FLOAT 377 unittest_fastfloat(reporter); 378 unittest_isfinite(reporter); 379#endif 380 381#ifdef SkLONGLONG 382 for (i = 0; i < 10000; i++) { 383 SkFixed numer = rand.nextS(); 384 SkFixed denom = rand.nextS(); 385 SkFixed result = SkFixedDiv(numer, denom); 386 SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom; 387 388 (void)SkCLZ(numer); 389 (void)SkCLZ(denom); 390 391 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32); 392 if (check > SK_MaxS32) { 393 check = SK_MaxS32; 394 } else if (check < -SK_MaxS32) { 395 check = SK_MinS32; 396 } 397 REPORTER_ASSERT(reporter, result == (int32_t)check); 398 399 result = SkFractDiv(numer, denom); 400 check = ((SkLONGLONG)numer << 30) / denom; 401 402 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32); 403 if (check > SK_MaxS32) { 404 check = SK_MaxS32; 405 } else if (check < -SK_MaxS32) { 406 check = SK_MinS32; 407 } 408 REPORTER_ASSERT(reporter, result == (int32_t)check); 409 410 // make them <= 2^24, so we don't overflow in fixmul 411 numer = numer << 8 >> 8; 412 denom = denom << 8 >> 8; 413 414 result = SkFixedMul(numer, denom); 415 SkFixed r2 = symmetric_fixmul(numer, denom); 416 // SkASSERT(result == r2); 417 418 result = SkFixedMul(numer, numer); 419 r2 = SkFixedSquare(numer); 420 REPORTER_ASSERT(reporter, result == r2); 421 422#ifdef SK_CAN_USE_FLOAT 423 if (numer >= 0 && denom >= 0) { 424 SkFixed mean = SkFixedMean(numer, denom); 425 float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom); 426 float fm = sk_float_sqrt(sk_float_abs(prod)); 427 SkFixed mean2 = SkFloatToFixed(fm); 428 int diff = SkAbs32(mean - mean2); 429 REPORTER_ASSERT(reporter, diff <= 1); 430 } 431 432 { 433 SkFixed mod = SkFixedMod(numer, denom); 434 float n = SkFixedToFloat(numer); 435 float d = SkFixedToFloat(denom); 436 float m = sk_float_mod(n, d); 437 // ensure the same sign 438 REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0)); 439 int diff = SkAbs32(mod - SkFloatToFixed(m)); 440 REPORTER_ASSERT(reporter, (diff >> 7) == 0); 441 } 442#endif 443 } 444#endif 445 446#ifdef SK_CAN_USE_FLOAT 447 for (i = 0; i < 10000; i++) { 448 SkFract x = rand.nextU() >> 1; 449 double xx = (double)x / SK_Fract1; 450 SkFract xr = SkFractSqrt(x); 451 SkFract check = SkFloatToFract(sqrt(xx)); 452 REPORTER_ASSERT(reporter, xr == check || 453 xr == check-1 || 454 xr == check+1); 455 456 xr = SkFixedSqrt(x); 457 xx = (double)x / SK_Fixed1; 458 check = SkFloatToFixed(sqrt(xx)); 459 REPORTER_ASSERT(reporter, xr == check || xr == check-1); 460 461 xr = SkSqrt32(x); 462 xx = (double)x; 463 check = (int32_t)sqrt(xx); 464 REPORTER_ASSERT(reporter, xr == check || xr == check-1); 465 } 466#endif 467 468#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT) 469 { 470 SkFixed s, c; 471 s = SkFixedSinCos(0, &c); 472 REPORTER_ASSERT(reporter, s == 0); 473 REPORTER_ASSERT(reporter, c == SK_Fixed1); 474 } 475 476 int maxDiff = 0; 477 for (i = 0; i < 1000; i++) { 478 SkFixed rads = rand.nextS() >> 10; 479 double frads = SkFixedToFloat(rads); 480 481 SkFixed s, c; 482 s = SkScalarSinCos(rads, &c); 483 484 double fs = sin(frads); 485 double fc = cos(frads); 486 487 SkFixed is = SkFloatToFixed(fs); 488 SkFixed ic = SkFloatToFixed(fc); 489 490 maxDiff = SkMax32(maxDiff, SkAbs32(is - s)); 491 maxDiff = SkMax32(maxDiff, SkAbs32(ic - c)); 492 } 493 SkDebugf("SinCos: maximum error = %d\n", maxDiff); 494#endif 495 496// test_premul(reporter); 497} 498 499#include "TestClassDef.h" 500DEFINE_TESTCLASS("Math", MathTestClass, TestMath) 501