blob: 7fc53a9285c598df04ac2c8f1a0027712a46c232 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.comed673312009-02-27 16:24:51 +00008#include "Test.h"
tomhudson@google.com8afae612012-08-14 15:03:35 +00009#include "SkFloatBits.h"
reed@android.comc846ede2010-04-13 15:29:15 +000010#include "SkFloatingPoint.h"
reed@google.com4b163ed2012-08-07 21:35:13 +000011#include "SkMathPriv.h"
reed@android.comed673312009-02-27 16:24:51 +000012#include "SkPoint.h"
13#include "SkRandom.h"
reed@google.com0abb4992011-10-06 20:04:36 +000014#include "SkColorPriv.h"
reed@android.comed673312009-02-27 16:24:51 +000015
reed@google.coma7d74612012-05-30 12:30:09 +000016static float sk_fsel(float pred, float result_ge, float result_lt) {
17 return pred >= 0 ? result_ge : result_lt;
18}
19
20static float fast_floor(float x) {
reed@google.comc20bc252012-05-30 13:48:14 +000021// float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23);
22 float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23));
robertphillips@google.com00bf06a2012-05-30 15:19:17 +000023 return (float)(x + big) - big;
reed@google.coma7d74612012-05-30 12:30:09 +000024}
25
26static float std_floor(float x) {
27 return sk_float_floor(x);
28}
29
30static void test_floor_value(skiatest::Reporter* reporter, float value) {
31 float fast = fast_floor(value);
32 float std = std_floor(value);
33 REPORTER_ASSERT(reporter, std == fast);
34// SkDebugf("value[%1.9f] std[%g] fast[%g] equal[%d]\n",
35// value, std, fast, std == fast);
36}
37
38static void test_floor(skiatest::Reporter* reporter) {
39 static const float gVals[] = {
40 0, 1, 1.1f, 1.01f, 1.001f, 1.0001f, 1.00001f, 1.000001f, 1.0000001f
41 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000042
reed@google.coma7d74612012-05-30 12:30:09 +000043 for (size_t i = 0; i < SK_ARRAY_COUNT(gVals); ++i) {
44 test_floor_value(reporter, gVals[i]);
45// test_floor_value(reporter, -gVals[i]);
46 }
47}
48
49///////////////////////////////////////////////////////////////////////////////
50
reed@google.com0abb4992011-10-06 20:04:36 +000051static float float_blend(int src, int dst, float unit) {
52 return dst + (src - dst) * unit;
reed@google.com772813a2011-03-30 22:34:45 +000053}
54
reed@google.com8d7e39c2011-11-09 17:12:08 +000055static int blend31(int src, int dst, int a31) {
56 return dst + ((src - dst) * a31 * 2114 >> 16);
57 // return dst + ((src - dst) * a31 * 33 >> 10);
58}
59
60static int blend31_slow(int src, int dst, int a31) {
61 int prod = src * a31 + (31 - a31) * dst + 16;
62 prod = (prod + (prod >> 5)) >> 5;
63 return prod;
64}
65
66static int blend31_round(int src, int dst, int a31) {
67 int prod = (src - dst) * a31 + 16;
68 prod = (prod + (prod >> 5)) >> 5;
69 return dst + prod;
70}
71
72static int blend31_old(int src, int dst, int a31) {
73 a31 += a31 >> 4;
74 return dst + ((src - dst) * a31 >> 5);
75}
76
caryclark@google.com42639cd2012-06-06 12:03:39 +000077// suppress unused code warning
78static int (*blend_functions[])(int, int, int) = {
79 blend31,
80 blend31_slow,
81 blend31_round,
82 blend31_old
83};
84
reed@google.com8d7e39c2011-11-09 17:12:08 +000085static void test_blend31() {
86 int failed = 0;
87 int death = 0;
caryclark@google.com42639cd2012-06-06 12:03:39 +000088 if (false) { // avoid bit rot, suppress warning
89 failed = (*blend_functions[0])(0,0,0);
90 }
reed@google.com8d7e39c2011-11-09 17:12:08 +000091 for (int src = 0; src <= 255; src++) {
92 for (int dst = 0; dst <= 255; dst++) {
93 for (int a = 0; a <= 31; a++) {
94// int r0 = blend31(src, dst, a);
95// int r0 = blend31_round(src, dst, a);
96// int r0 = blend31_old(src, dst, a);
97 int r0 = blend31_slow(src, dst, a);
98
99 float f = float_blend(src, dst, a / 31.f);
100 int r1 = (int)f;
101 int r2 = SkScalarRoundToInt(SkFloatToScalar(f));
102
103 if (r0 != r1 && r0 != r2) {
104 printf("src:%d dst:%d a:%d result:%d float:%g\n",
105 src, dst, a, r0, f);
106 failed += 1;
107 }
108 if (r0 > 255) {
109 death += 1;
110 printf("death src:%d dst:%d a:%d result:%d float:%g\n",
111 src, dst, a, r0, f);
112 }
113 }
114 }
115 }
116 SkDebugf("---- failed %d death %d\n", failed, death);
117}
118
reed@google.com0abb4992011-10-06 20:04:36 +0000119static void test_blend(skiatest::Reporter* reporter) {
120 for (int src = 0; src <= 255; src++) {
121 for (int dst = 0; dst <= 255; dst++) {
122 for (int a = 0; a <= 255; a++) {
123 int r0 = SkAlphaBlend255(src, dst, a);
124 float f1 = float_blend(src, dst, a / 255.f);
reed@google.com111c19b2011-10-06 20:13:22 +0000125 int r1 = SkScalarRoundToInt(SkFloatToScalar(f1));
reed@google.com772813a2011-03-30 22:34:45 +0000126
reed@google.com0abb4992011-10-06 20:04:36 +0000127 if (r0 != r1) {
128 float diff = sk_float_abs(f1 - r1);
129 diff = sk_float_abs(diff - 0.5f);
130 if (diff > (1 / 255.f)) {
131#ifdef SK_DEBUG
132 SkDebugf("src:%d dst:%d a:%d result:%d float:%g\n",
133 src, dst, a, r0, f1);
134#endif
135 REPORTER_ASSERT(reporter, false);
136 }
137 }
reed@google.com772813a2011-03-30 22:34:45 +0000138 }
139 }
140 }
141}
reed@google.com772813a2011-03-30 22:34:45 +0000142
reed@android.comed673312009-02-27 16:24:51 +0000143#if defined(SkLONGLONG)
144static int symmetric_fixmul(int a, int b) {
145 int sa = SkExtractSign(a);
146 int sb = SkExtractSign(b);
reed@android.com80e39a72009-04-02 16:59:40 +0000147
reed@android.comed673312009-02-27 16:24:51 +0000148 a = SkApplySign(a, sa);
149 b = SkApplySign(b, sb);
reed@android.com80e39a72009-04-02 16:59:40 +0000150
reed@android.comed673312009-02-27 16:24:51 +0000151#if 1
152 int c = (int)(((SkLONGLONG)a * b) >> 16);
reed@android.com80e39a72009-04-02 16:59:40 +0000153
reed@android.comed673312009-02-27 16:24:51 +0000154 return SkApplySign(c, sa ^ sb);
155#else
156 SkLONGLONG ab = (SkLONGLONG)a * b;
157 if (sa ^ sb) {
158 ab = -ab;
159 }
160 return ab >> 16;
161#endif
162}
163#endif
164
165static void check_length(skiatest::Reporter* reporter,
166 const SkPoint& p, SkScalar targetLen) {
reed@android.comed673312009-02-27 16:24:51 +0000167 float x = SkScalarToFloat(p.fX);
168 float y = SkScalarToFloat(p.fY);
169 float len = sk_float_sqrt(x*x + y*y);
reed@android.com80e39a72009-04-02 16:59:40 +0000170
reed@android.comed673312009-02-27 16:24:51 +0000171 len /= SkScalarToFloat(targetLen);
reed@android.com80e39a72009-04-02 16:59:40 +0000172
reed@android.comed673312009-02-27 16:24:51 +0000173 REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
reed@android.comed673312009-02-27 16:24:51 +0000174}
175
reed@android.comed673312009-02-27 16:24:51 +0000176static float nextFloat(SkRandom& rand) {
177 SkFloatIntUnion data;
178 data.fSignBitInt = rand.nextU();
179 return data.fFloat;
180}
181
182/* returns true if a == b as resulting from (int)x. Since it is undefined
183 what to do if the float exceeds 2^32-1, we check for that explicitly.
184 */
185static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
186 if (!(x == x)) { // NAN
bsalomon@google.com373ebc62012-09-26 13:08:56 +0000187 return ((int32_t)si) == SK_MaxS32 || ((int32_t)si) == SK_MinS32;
reed@android.comed673312009-02-27 16:24:51 +0000188 }
189 // for out of range, C is undefined, but skia always should return NaN32
190 if (x > SK_MaxS32) {
bsalomon@google.com373ebc62012-09-26 13:08:56 +0000191 return ((int32_t)si) == SK_MaxS32;
reed@android.comed673312009-02-27 16:24:51 +0000192 }
193 if (x < -SK_MaxS32) {
bsalomon@google.com373ebc62012-09-26 13:08:56 +0000194 return ((int32_t)si) == SK_MinS32;
reed@android.comed673312009-02-27 16:24:51 +0000195 }
196 return si == ni;
197}
198
199static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
200 float x, uint32_t ni, uint32_t si) {
201 if (!equal_float_native_skia(x, ni, si)) {
202 SkString desc;
tomhudson@google.com8afae612012-08-14 15:03:35 +0000203 uint32_t xi = SkFloat2Bits(x);
204 desc.printf("%s float %g bits %x native %x skia %x\n", op, x, xi, ni, si);
reed@android.comed673312009-02-27 16:24:51 +0000205 reporter->reportFailed(desc);
206 }
207}
208
209static void test_float_cast(skiatest::Reporter* reporter, float x) {
210 int ix = (int)x;
211 int iix = SkFloatToIntCast(x);
212 assert_float_equal(reporter, "cast", x, ix, iix);
213}
214
215static void test_float_floor(skiatest::Reporter* reporter, float x) {
216 int ix = (int)floor(x);
217 int iix = SkFloatToIntFloor(x);
218 assert_float_equal(reporter, "floor", x, ix, iix);
219}
220
221static void test_float_round(skiatest::Reporter* reporter, float x) {
222 double xx = x + 0.5; // need intermediate double to avoid temp loss
223 int ix = (int)floor(xx);
224 int iix = SkFloatToIntRound(x);
225 assert_float_equal(reporter, "round", x, ix, iix);
226}
227
228static void test_float_ceil(skiatest::Reporter* reporter, float x) {
229 int ix = (int)ceil(x);
230 int iix = SkFloatToIntCeil(x);
231 assert_float_equal(reporter, "ceil", x, ix, iix);
232}
233
234static void test_float_conversions(skiatest::Reporter* reporter, float x) {
235 test_float_cast(reporter, x);
236 test_float_floor(reporter, x);
237 test_float_round(reporter, x);
238 test_float_ceil(reporter, x);
239}
240
241static void test_int2float(skiatest::Reporter* reporter, int ival) {
242 float x0 = (float)ival;
243 float x1 = SkIntToFloatCast(ival);
244 float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
245 REPORTER_ASSERT(reporter, x0 == x1);
246 REPORTER_ASSERT(reporter, x0 == x2);
247}
248
249static void unittest_fastfloat(skiatest::Reporter* reporter) {
250 SkRandom rand;
251 size_t i;
reed@android.com80e39a72009-04-02 16:59:40 +0000252
reed@android.comed673312009-02-27 16:24:51 +0000253 static const float gFloats[] = {
254 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
255 0.000000001f, 1000000000.f, // doesn't overflow
256 0.0000000001f, 10000000000.f // does overflow
257 };
258 for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
reed@android.comed673312009-02-27 16:24:51 +0000259 test_float_conversions(reporter, gFloats[i]);
260 test_float_conversions(reporter, -gFloats[i]);
261 }
reed@android.com80e39a72009-04-02 16:59:40 +0000262
reed@android.comed673312009-02-27 16:24:51 +0000263 for (int outer = 0; outer < 100; outer++) {
264 rand.setSeed(outer);
265 for (i = 0; i < 100000; i++) {
266 float x = nextFloat(rand);
267 test_float_conversions(reporter, x);
268 }
reed@android.com80e39a72009-04-02 16:59:40 +0000269
reed@android.comed673312009-02-27 16:24:51 +0000270 test_int2float(reporter, 0);
271 test_int2float(reporter, 1);
272 test_int2float(reporter, -1);
273 for (i = 0; i < 100000; i++) {
274 // for now only test ints that are 24bits or less, since we don't
275 // round (down) large ints the same as IEEE...
276 int ival = rand.nextU() & 0xFFFFFF;
277 test_int2float(reporter, ival);
278 test_int2float(reporter, -ival);
279 }
280 }
281}
282
reed@android.comd4134452011-02-09 02:24:26 +0000283#ifdef SK_SCALAR_IS_FLOAT
reed@google.com077910e2011-02-08 21:56:39 +0000284static float make_zero() {
285 return sk_float_sin(0);
286}
reed@android.comd4134452011-02-09 02:24:26 +0000287#endif
reed@google.com077910e2011-02-08 21:56:39 +0000288
289static void unittest_isfinite(skiatest::Reporter* reporter) {
290#ifdef SK_SCALAR_IS_FLOAT
epoger@google.combf083a92011-06-08 18:26:08 +0000291 float nan = sk_float_asin(2);
tomhudson@google.com75589252012-04-10 17:42:21 +0000292 float inf = 1.0f / make_zero();
293 float big = 3.40282e+038f;
reed@google.com077910e2011-02-08 21:56:39 +0000294
reed@google.com077910e2011-02-08 21:56:39 +0000295 REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf));
reed@android.comd4134452011-02-09 02:24:26 +0000296 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf));
297 REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf));
298 REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf));
299#else
300 SkFixed nan = SK_FixedNaN;
301 SkFixed big = SK_FixedMax;
302#endif
303
304 REPORTER_ASSERT(reporter, SkScalarIsNaN(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000305 REPORTER_ASSERT(reporter, !SkScalarIsNaN(big));
306 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big));
307 REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000308
reed@google.com077910e2011-02-08 21:56:39 +0000309 REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000310 REPORTER_ASSERT(reporter, SkScalarIsFinite(big));
311 REPORTER_ASSERT(reporter, SkScalarIsFinite(-big));
312 REPORTER_ASSERT(reporter, SkScalarIsFinite(0));
reed@google.com077910e2011-02-08 21:56:39 +0000313}
314
reed@android.comed673312009-02-27 16:24:51 +0000315static void test_muldiv255(skiatest::Reporter* reporter) {
reed@android.comed673312009-02-27 16:24:51 +0000316 for (int a = 0; a <= 255; a++) {
317 for (int b = 0; b <= 255; b++) {
318 int ab = a * b;
319 float s = ab / 255.0f;
320 int round = (int)floorf(s + 0.5f);
321 int trunc = (int)floorf(s);
reed@android.com80e39a72009-04-02 16:59:40 +0000322
reed@android.comed673312009-02-27 16:24:51 +0000323 int iround = SkMulDiv255Round(a, b);
324 int itrunc = SkMulDiv255Trunc(a, b);
reed@android.com80e39a72009-04-02 16:59:40 +0000325
reed@android.comed673312009-02-27 16:24:51 +0000326 REPORTER_ASSERT(reporter, iround == round);
327 REPORTER_ASSERT(reporter, itrunc == trunc);
reed@android.com80e39a72009-04-02 16:59:40 +0000328
reed@android.comed673312009-02-27 16:24:51 +0000329 REPORTER_ASSERT(reporter, itrunc <= iround);
330 REPORTER_ASSERT(reporter, iround <= a);
331 REPORTER_ASSERT(reporter, iround <= b);
332 }
333 }
reed@android.comed673312009-02-27 16:24:51 +0000334}
335
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000336static void test_muldiv255ceiling(skiatest::Reporter* reporter) {
337 for (int c = 0; c <= 255; c++) {
338 for (int a = 0; a <= 255; a++) {
339 int product = (c * a + 255);
340 int expected_ceiling = (product + (product >> 8)) >> 8;
341 int webkit_ceiling = (c * a + 254) / 255;
342 REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling);
343 int skia_ceiling = SkMulDiv255Ceiling(c, a);
344 REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling);
345 }
346 }
347}
348
reed@android.comf0ad0862010-02-09 19:18:38 +0000349static void test_copysign(skiatest::Reporter* reporter) {
350 static const int32_t gTriples[] = {
351 // x, y, expected result
352 0, 0, 0,
353 0, 1, 0,
354 0, -1, 0,
355 1, 0, 1,
356 1, 1, 1,
357 1, -1, -1,
358 -1, 0, 1,
359 -1, 1, 1,
360 -1, -1, -1,
361 };
362 for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) {
363 REPORTER_ASSERT(reporter,
364 SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]);
reed@android.comf0ad0862010-02-09 19:18:38 +0000365 float x = (float)gTriples[i];
366 float y = (float)gTriples[i+1];
367 float expected = (float)gTriples[i+2];
368 REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected);
reed@android.comf0ad0862010-02-09 19:18:38 +0000369 }
370
371 SkRandom rand;
372 for (int j = 0; j < 1000; j++) {
373 int ix = rand.nextS();
374 REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix);
375 REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix);
376 REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix);
377 REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix);
378
379 SkScalar sx = rand.nextSScalar1();
380 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx);
381 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
382 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx);
383 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
384 }
385}
386
reed@android.com80e39a72009-04-02 16:59:40 +0000387static void TestMath(skiatest::Reporter* reporter) {
reed@android.comed673312009-02-27 16:24:51 +0000388 int i;
389 int32_t x;
390 SkRandom rand;
reed@android.com80e39a72009-04-02 16:59:40 +0000391
reed@android.comed673312009-02-27 16:24:51 +0000392 // these should assert
393#if 0
394 SkToS8(128);
395 SkToS8(-129);
396 SkToU8(256);
397 SkToU8(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000398
reed@android.comed673312009-02-27 16:24:51 +0000399 SkToS16(32768);
400 SkToS16(-32769);
401 SkToU16(65536);
402 SkToU16(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000403
reed@android.comed673312009-02-27 16:24:51 +0000404 if (sizeof(size_t) > 4) {
405 SkToS32(4*1024*1024);
406 SkToS32(-4*1024*1024);
407 SkToU32(5*1024*1024);
408 SkToU32(-5);
409 }
410#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000411
reed@android.comed673312009-02-27 16:24:51 +0000412 test_muldiv255(reporter);
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000413 test_muldiv255ceiling(reporter);
reed@android.comf0ad0862010-02-09 19:18:38 +0000414 test_copysign(reporter);
reed@android.com80e39a72009-04-02 16:59:40 +0000415
reed@android.comed673312009-02-27 16:24:51 +0000416 {
417 SkScalar x = SK_ScalarNaN;
418 REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
419 }
reed@android.com80e39a72009-04-02 16:59:40 +0000420
reed@android.comed673312009-02-27 16:24:51 +0000421 for (i = 1; i <= 10; i++) {
422 x = SkCubeRootBits(i*i*i, 11);
423 REPORTER_ASSERT(reporter, x == i);
424 }
reed@android.com80e39a72009-04-02 16:59:40 +0000425
reed@android.comed673312009-02-27 16:24:51 +0000426 x = SkFixedSqrt(SK_Fixed1);
427 REPORTER_ASSERT(reporter, x == SK_Fixed1);
428 x = SkFixedSqrt(SK_Fixed1/4);
429 REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
430 x = SkFixedSqrt(SK_Fixed1*4);
431 REPORTER_ASSERT(reporter, x == SK_Fixed1*2);
reed@android.com80e39a72009-04-02 16:59:40 +0000432
reed@android.comed673312009-02-27 16:24:51 +0000433 x = SkFractSqrt(SK_Fract1);
434 REPORTER_ASSERT(reporter, x == SK_Fract1);
435 x = SkFractSqrt(SK_Fract1/4);
436 REPORTER_ASSERT(reporter, x == SK_Fract1/2);
437 x = SkFractSqrt(SK_Fract1/16);
438 REPORTER_ASSERT(reporter, x == SK_Fract1/4);
reed@android.com80e39a72009-04-02 16:59:40 +0000439
reed@android.comed673312009-02-27 16:24:51 +0000440 for (i = 1; i < 100; i++) {
441 x = SkFixedSqrt(SK_Fixed1 * i * i);
442 REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
443 }
reed@android.com80e39a72009-04-02 16:59:40 +0000444
reed@android.comed673312009-02-27 16:24:51 +0000445 for (i = 0; i < 1000; i++) {
446 int value = rand.nextS16();
447 int max = rand.nextU16();
reed@android.com80e39a72009-04-02 16:59:40 +0000448
reed@android.comed673312009-02-27 16:24:51 +0000449 int clamp = SkClampMax(value, max);
450 int clamp2 = value < 0 ? 0 : (value > max ? max : value);
451 REPORTER_ASSERT(reporter, clamp == clamp2);
452 }
reed@android.com80e39a72009-04-02 16:59:40 +0000453
reed@android.come72fee52009-11-16 14:52:01 +0000454 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000455 SkPoint p;
reed@android.com80e39a72009-04-02 16:59:40 +0000456
tomhudson@google.com75589252012-04-10 17:42:21 +0000457 // These random values are being treated as 32-bit-patterns, not as
458 // ints; calling SkIntToScalar() here produces crashes.
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000459 p.setLength((SkScalar) rand.nextS(),
rmistry@google.comd6176b02012-08-23 18:14:13 +0000460 (SkScalar) rand.nextS(),
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000461 SK_Scalar1);
reed@android.comed673312009-02-27 16:24:51 +0000462 check_length(reporter, p, SK_Scalar1);
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000463 p.setLength((SkScalar) (rand.nextS() >> 13),
rmistry@google.comd6176b02012-08-23 18:14:13 +0000464 (SkScalar) (rand.nextS() >> 13),
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000465 SK_Scalar1);
reed@android.comed673312009-02-27 16:24:51 +0000466 check_length(reporter, p, SK_Scalar1);
467 }
reed@android.com80e39a72009-04-02 16:59:40 +0000468
reed@android.comed673312009-02-27 16:24:51 +0000469 {
470 SkFixed result = SkFixedDiv(100, 100);
471 REPORTER_ASSERT(reporter, result == SK_Fixed1);
472 result = SkFixedDiv(1, SK_Fixed1);
473 REPORTER_ASSERT(reporter, result == 1);
474 }
reed@android.com80e39a72009-04-02 16:59:40 +0000475
reed@android.comed673312009-02-27 16:24:51 +0000476 unittest_fastfloat(reporter);
reed@google.com077910e2011-02-08 21:56:39 +0000477 unittest_isfinite(reporter);
reed@android.com80e39a72009-04-02 16:59:40 +0000478
reed@android.comed673312009-02-27 16:24:51 +0000479#ifdef SkLONGLONG
reed@android.come72fee52009-11-16 14:52:01 +0000480 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000481 SkFixed numer = rand.nextS();
482 SkFixed denom = rand.nextS();
483 SkFixed result = SkFixedDiv(numer, denom);
484 SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000485
reed@android.comed673312009-02-27 16:24:51 +0000486 (void)SkCLZ(numer);
487 (void)SkCLZ(denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000488
reed@android.comed673312009-02-27 16:24:51 +0000489 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
490 if (check > SK_MaxS32) {
491 check = SK_MaxS32;
492 } else if (check < -SK_MaxS32) {
493 check = SK_MinS32;
494 }
495 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000496
reed@android.comed673312009-02-27 16:24:51 +0000497 result = SkFractDiv(numer, denom);
498 check = ((SkLONGLONG)numer << 30) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000499
reed@android.comed673312009-02-27 16:24:51 +0000500 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
501 if (check > SK_MaxS32) {
502 check = SK_MaxS32;
503 } else if (check < -SK_MaxS32) {
504 check = SK_MinS32;
505 }
506 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000507
reed@android.comed673312009-02-27 16:24:51 +0000508 // make them <= 2^24, so we don't overflow in fixmul
509 numer = numer << 8 >> 8;
510 denom = denom << 8 >> 8;
reed@android.com80e39a72009-04-02 16:59:40 +0000511
reed@android.comed673312009-02-27 16:24:51 +0000512 result = SkFixedMul(numer, denom);
513 SkFixed r2 = symmetric_fixmul(numer, denom);
514 // SkASSERT(result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000515
reed@android.comed673312009-02-27 16:24:51 +0000516 result = SkFixedMul(numer, numer);
517 r2 = SkFixedSquare(numer);
518 REPORTER_ASSERT(reporter, result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000519
reed@android.comed673312009-02-27 16:24:51 +0000520 if (numer >= 0 && denom >= 0) {
521 SkFixed mean = SkFixedMean(numer, denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000522 float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom);
523 float fm = sk_float_sqrt(sk_float_abs(prod));
reed@android.comed673312009-02-27 16:24:51 +0000524 SkFixed mean2 = SkFloatToFixed(fm);
525 int diff = SkAbs32(mean - mean2);
526 REPORTER_ASSERT(reporter, diff <= 1);
527 }
reed@android.com80e39a72009-04-02 16:59:40 +0000528
reed@android.comed673312009-02-27 16:24:51 +0000529 {
530 SkFixed mod = SkFixedMod(numer, denom);
531 float n = SkFixedToFloat(numer);
532 float d = SkFixedToFloat(denom);
533 float m = sk_float_mod(n, d);
reed@android.com80e39a72009-04-02 16:59:40 +0000534 // ensure the same sign
535 REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0));
reed@android.comed673312009-02-27 16:24:51 +0000536 int diff = SkAbs32(mod - SkFloatToFixed(m));
537 REPORTER_ASSERT(reporter, (diff >> 7) == 0);
538 }
reed@android.comed673312009-02-27 16:24:51 +0000539 }
540#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000541
reed@android.come72fee52009-11-16 14:52:01 +0000542 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000543 SkFract x = rand.nextU() >> 1;
544 double xx = (double)x / SK_Fract1;
545 SkFract xr = SkFractSqrt(x);
546 SkFract check = SkFloatToFract(sqrt(xx));
reed@android.com80e39a72009-04-02 16:59:40 +0000547 REPORTER_ASSERT(reporter, xr == check ||
548 xr == check-1 ||
549 xr == check+1);
550
reed@android.comed673312009-02-27 16:24:51 +0000551 xr = SkFixedSqrt(x);
552 xx = (double)x / SK_Fixed1;
553 check = SkFloatToFixed(sqrt(xx));
554 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
reed@android.com80e39a72009-04-02 16:59:40 +0000555
reed@android.comed673312009-02-27 16:24:51 +0000556 xr = SkSqrt32(x);
557 xx = (double)x;
558 check = (int32_t)sqrt(xx);
559 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
560 }
reed@android.com80e39a72009-04-02 16:59:40 +0000561
reed@google.com7886ad32012-06-11 21:21:26 +0000562#if !defined(SK_SCALAR_IS_FLOAT)
reed@android.comed673312009-02-27 16:24:51 +0000563 {
564 SkFixed s, c;
565 s = SkFixedSinCos(0, &c);
566 REPORTER_ASSERT(reporter, s == 0);
567 REPORTER_ASSERT(reporter, c == SK_Fixed1);
568 }
reed@android.com80e39a72009-04-02 16:59:40 +0000569
reed@android.comed673312009-02-27 16:24:51 +0000570 int maxDiff = 0;
reed@android.come72fee52009-11-16 14:52:01 +0000571 for (i = 0; i < 1000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000572 SkFixed rads = rand.nextS() >> 10;
573 double frads = SkFixedToFloat(rads);
reed@android.com80e39a72009-04-02 16:59:40 +0000574
reed@android.comed673312009-02-27 16:24:51 +0000575 SkFixed s, c;
576 s = SkScalarSinCos(rads, &c);
reed@android.com80e39a72009-04-02 16:59:40 +0000577
reed@android.comed673312009-02-27 16:24:51 +0000578 double fs = sin(frads);
579 double fc = cos(frads);
reed@android.com80e39a72009-04-02 16:59:40 +0000580
reed@android.comed673312009-02-27 16:24:51 +0000581 SkFixed is = SkFloatToFixed(fs);
582 SkFixed ic = SkFloatToFixed(fc);
reed@android.com80e39a72009-04-02 16:59:40 +0000583
reed@android.comed673312009-02-27 16:24:51 +0000584 maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
585 maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
586 }
587 SkDebugf("SinCos: maximum error = %d\n", maxDiff);
588#endif
reed@google.com772813a2011-03-30 22:34:45 +0000589
reed@google.com0abb4992011-10-06 20:04:36 +0000590#ifdef SK_SCALAR_IS_FLOAT
591 test_blend(reporter);
592#endif
reed@google.com8d7e39c2011-11-09 17:12:08 +0000593
humper@google.com05af1af2013-01-07 16:47:43 +0000594 if (false) test_floor(reporter);
reed@google.coma7d74612012-05-30 12:30:09 +0000595
reed@google.com8d7e39c2011-11-09 17:12:08 +0000596 // disable for now
caryclark@google.com42639cd2012-06-06 12:03:39 +0000597 if (false) test_blend31(); // avoid bit rot, suppress warning
reed@android.comed673312009-02-27 16:24:51 +0000598}
599
reed@android.comd8730ea2009-02-27 22:06:06 +0000600#include "TestClassDef.h"
601DEFINE_TESTCLASS("Math", MathTestClass, TestMath)