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