blob: fda5abdec4fecf0d4003b25aad440d7addac169b [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"
reed@android.comc846ede2010-04-13 15:29:15 +00009#include "SkFloatingPoint.h"
tomhudson@google.com889bd8b2011-09-27 17:38:17 +000010#include "SkMath.h"
reed@android.comed673312009-02-27 16:24:51 +000011#include "SkPoint.h"
12#include "SkRandom.h"
reed@google.com0abb4992011-10-06 20:04:36 +000013#include "SkColorPriv.h"
reed@android.comed673312009-02-27 16:24:51 +000014
reed@google.coma7d74612012-05-30 12:30:09 +000015static float sk_fsel(float pred, float result_ge, float result_lt) {
16 return pred >= 0 ? result_ge : result_lt;
17}
18
19static float fast_floor(float x) {
20 float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23);
21 return (x + big) - big;
22}
23
24static float std_floor(float x) {
25 return sk_float_floor(x);
26}
27
28static void test_floor_value(skiatest::Reporter* reporter, float value) {
29 float fast = fast_floor(value);
30 float std = std_floor(value);
31 REPORTER_ASSERT(reporter, std == fast);
32// SkDebugf("value[%1.9f] std[%g] fast[%g] equal[%d]\n",
33// value, std, fast, std == fast);
34}
35
36static void test_floor(skiatest::Reporter* reporter) {
37 static const float gVals[] = {
38 0, 1, 1.1f, 1.01f, 1.001f, 1.0001f, 1.00001f, 1.000001f, 1.0000001f
39 };
40
41 for (size_t i = 0; i < SK_ARRAY_COUNT(gVals); ++i) {
42 test_floor_value(reporter, gVals[i]);
43// test_floor_value(reporter, -gVals[i]);
44 }
45}
46
47///////////////////////////////////////////////////////////////////////////////
48
reed@google.com0abb4992011-10-06 20:04:36 +000049static float float_blend(int src, int dst, float unit) {
50 return dst + (src - dst) * unit;
reed@google.com772813a2011-03-30 22:34:45 +000051}
52
reed@google.com8d7e39c2011-11-09 17:12:08 +000053static int blend31(int src, int dst, int a31) {
54 return dst + ((src - dst) * a31 * 2114 >> 16);
55 // return dst + ((src - dst) * a31 * 33 >> 10);
56}
57
58static int blend31_slow(int src, int dst, int a31) {
59 int prod = src * a31 + (31 - a31) * dst + 16;
60 prod = (prod + (prod >> 5)) >> 5;
61 return prod;
62}
63
64static int blend31_round(int src, int dst, int a31) {
65 int prod = (src - dst) * a31 + 16;
66 prod = (prod + (prod >> 5)) >> 5;
67 return dst + prod;
68}
69
70static int blend31_old(int src, int dst, int a31) {
71 a31 += a31 >> 4;
72 return dst + ((src - dst) * a31 >> 5);
73}
74
75static void test_blend31() {
76 int failed = 0;
77 int death = 0;
78 for (int src = 0; src <= 255; src++) {
79 for (int dst = 0; dst <= 255; dst++) {
80 for (int a = 0; a <= 31; a++) {
81// int r0 = blend31(src, dst, a);
82// int r0 = blend31_round(src, dst, a);
83// int r0 = blend31_old(src, dst, a);
84 int r0 = blend31_slow(src, dst, a);
85
86 float f = float_blend(src, dst, a / 31.f);
87 int r1 = (int)f;
88 int r2 = SkScalarRoundToInt(SkFloatToScalar(f));
89
90 if (r0 != r1 && r0 != r2) {
91 printf("src:%d dst:%d a:%d result:%d float:%g\n",
92 src, dst, a, r0, f);
93 failed += 1;
94 }
95 if (r0 > 255) {
96 death += 1;
97 printf("death src:%d dst:%d a:%d result:%d float:%g\n",
98 src, dst, a, r0, f);
99 }
100 }
101 }
102 }
103 SkDebugf("---- failed %d death %d\n", failed, death);
104}
105
reed@google.com0abb4992011-10-06 20:04:36 +0000106static void test_blend(skiatest::Reporter* reporter) {
107 for (int src = 0; src <= 255; src++) {
108 for (int dst = 0; dst <= 255; dst++) {
109 for (int a = 0; a <= 255; a++) {
110 int r0 = SkAlphaBlend255(src, dst, a);
111 float f1 = float_blend(src, dst, a / 255.f);
reed@google.com111c19b2011-10-06 20:13:22 +0000112 int r1 = SkScalarRoundToInt(SkFloatToScalar(f1));
reed@google.com772813a2011-03-30 22:34:45 +0000113
reed@google.com0abb4992011-10-06 20:04:36 +0000114 if (r0 != r1) {
115 float diff = sk_float_abs(f1 - r1);
116 diff = sk_float_abs(diff - 0.5f);
117 if (diff > (1 / 255.f)) {
118#ifdef SK_DEBUG
119 SkDebugf("src:%d dst:%d a:%d result:%d float:%g\n",
120 src, dst, a, r0, f1);
121#endif
122 REPORTER_ASSERT(reporter, false);
123 }
124 }
reed@google.com772813a2011-03-30 22:34:45 +0000125 }
126 }
127 }
128}
reed@google.com772813a2011-03-30 22:34:45 +0000129
reed@android.comed673312009-02-27 16:24:51 +0000130#if defined(SkLONGLONG)
131static int symmetric_fixmul(int a, int b) {
132 int sa = SkExtractSign(a);
133 int sb = SkExtractSign(b);
reed@android.com80e39a72009-04-02 16:59:40 +0000134
reed@android.comed673312009-02-27 16:24:51 +0000135 a = SkApplySign(a, sa);
136 b = SkApplySign(b, sb);
reed@android.com80e39a72009-04-02 16:59:40 +0000137
reed@android.comed673312009-02-27 16:24:51 +0000138#if 1
139 int c = (int)(((SkLONGLONG)a * b) >> 16);
reed@android.com80e39a72009-04-02 16:59:40 +0000140
reed@android.comed673312009-02-27 16:24:51 +0000141 return SkApplySign(c, sa ^ sb);
142#else
143 SkLONGLONG ab = (SkLONGLONG)a * b;
144 if (sa ^ sb) {
145 ab = -ab;
146 }
147 return ab >> 16;
148#endif
149}
150#endif
151
152static void check_length(skiatest::Reporter* reporter,
153 const SkPoint& p, SkScalar targetLen) {
154#ifdef SK_CAN_USE_FLOAT
155 float x = SkScalarToFloat(p.fX);
156 float y = SkScalarToFloat(p.fY);
157 float len = sk_float_sqrt(x*x + y*y);
reed@android.com80e39a72009-04-02 16:59:40 +0000158
reed@android.comed673312009-02-27 16:24:51 +0000159 len /= SkScalarToFloat(targetLen);
reed@android.com80e39a72009-04-02 16:59:40 +0000160
reed@android.comed673312009-02-27 16:24:51 +0000161 REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
162#endif
163}
164
165#if defined(SK_CAN_USE_FLOAT)
166
167static float nextFloat(SkRandom& rand) {
168 SkFloatIntUnion data;
169 data.fSignBitInt = rand.nextU();
170 return data.fFloat;
171}
172
173/* returns true if a == b as resulting from (int)x. Since it is undefined
174 what to do if the float exceeds 2^32-1, we check for that explicitly.
175 */
176static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
177 if (!(x == x)) { // NAN
178 return si == SK_MaxS32 || si == SK_MinS32;
179 }
180 // for out of range, C is undefined, but skia always should return NaN32
181 if (x > SK_MaxS32) {
182 return si == SK_MaxS32;
183 }
184 if (x < -SK_MaxS32) {
185 return si == SK_MinS32;
186 }
187 return si == ni;
188}
189
190static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
191 float x, uint32_t ni, uint32_t si) {
192 if (!equal_float_native_skia(x, ni, si)) {
193 SkString desc;
194 desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si);
195 reporter->reportFailed(desc);
196 }
197}
198
199static void test_float_cast(skiatest::Reporter* reporter, float x) {
200 int ix = (int)x;
201 int iix = SkFloatToIntCast(x);
202 assert_float_equal(reporter, "cast", x, ix, iix);
203}
204
205static void test_float_floor(skiatest::Reporter* reporter, float x) {
206 int ix = (int)floor(x);
207 int iix = SkFloatToIntFloor(x);
208 assert_float_equal(reporter, "floor", x, ix, iix);
209}
210
211static void test_float_round(skiatest::Reporter* reporter, float x) {
212 double xx = x + 0.5; // need intermediate double to avoid temp loss
213 int ix = (int)floor(xx);
214 int iix = SkFloatToIntRound(x);
215 assert_float_equal(reporter, "round", x, ix, iix);
216}
217
218static void test_float_ceil(skiatest::Reporter* reporter, float x) {
219 int ix = (int)ceil(x);
220 int iix = SkFloatToIntCeil(x);
221 assert_float_equal(reporter, "ceil", x, ix, iix);
222}
223
224static void test_float_conversions(skiatest::Reporter* reporter, float x) {
225 test_float_cast(reporter, x);
226 test_float_floor(reporter, x);
227 test_float_round(reporter, x);
228 test_float_ceil(reporter, x);
229}
230
231static void test_int2float(skiatest::Reporter* reporter, int ival) {
232 float x0 = (float)ival;
233 float x1 = SkIntToFloatCast(ival);
234 float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
235 REPORTER_ASSERT(reporter, x0 == x1);
236 REPORTER_ASSERT(reporter, x0 == x2);
237}
238
239static void unittest_fastfloat(skiatest::Reporter* reporter) {
240 SkRandom rand;
241 size_t i;
reed@android.com80e39a72009-04-02 16:59:40 +0000242
reed@android.comed673312009-02-27 16:24:51 +0000243 static const float gFloats[] = {
244 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
245 0.000000001f, 1000000000.f, // doesn't overflow
246 0.0000000001f, 10000000000.f // does overflow
247 };
248 for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
reed@android.comed673312009-02-27 16:24:51 +0000249 test_float_conversions(reporter, gFloats[i]);
250 test_float_conversions(reporter, -gFloats[i]);
251 }
reed@android.com80e39a72009-04-02 16:59:40 +0000252
reed@android.comed673312009-02-27 16:24:51 +0000253 for (int outer = 0; outer < 100; outer++) {
254 rand.setSeed(outer);
255 for (i = 0; i < 100000; i++) {
256 float x = nextFloat(rand);
257 test_float_conversions(reporter, x);
258 }
reed@android.com80e39a72009-04-02 16:59:40 +0000259
reed@android.comed673312009-02-27 16:24:51 +0000260 test_int2float(reporter, 0);
261 test_int2float(reporter, 1);
262 test_int2float(reporter, -1);
263 for (i = 0; i < 100000; i++) {
264 // for now only test ints that are 24bits or less, since we don't
265 // round (down) large ints the same as IEEE...
266 int ival = rand.nextU() & 0xFFFFFF;
267 test_int2float(reporter, ival);
268 test_int2float(reporter, -ival);
269 }
270 }
271}
272
reed@android.comd4134452011-02-09 02:24:26 +0000273#ifdef SK_SCALAR_IS_FLOAT
reed@google.com077910e2011-02-08 21:56:39 +0000274static float make_zero() {
275 return sk_float_sin(0);
276}
reed@android.comd4134452011-02-09 02:24:26 +0000277#endif
reed@google.com077910e2011-02-08 21:56:39 +0000278
279static void unittest_isfinite(skiatest::Reporter* reporter) {
280#ifdef SK_SCALAR_IS_FLOAT
epoger@google.combf083a92011-06-08 18:26:08 +0000281 float nan = sk_float_asin(2);
tomhudson@google.com75589252012-04-10 17:42:21 +0000282 float inf = 1.0f / make_zero();
283 float big = 3.40282e+038f;
reed@google.com077910e2011-02-08 21:56:39 +0000284
reed@google.com077910e2011-02-08 21:56:39 +0000285 REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf));
reed@android.comd4134452011-02-09 02:24:26 +0000286 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf));
287 REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf));
288 REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf));
289#else
290 SkFixed nan = SK_FixedNaN;
291 SkFixed big = SK_FixedMax;
292#endif
293
294 REPORTER_ASSERT(reporter, SkScalarIsNaN(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000295 REPORTER_ASSERT(reporter, !SkScalarIsNaN(big));
296 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big));
297 REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
reed@android.comd4134452011-02-09 02:24:26 +0000298
reed@google.com077910e2011-02-08 21:56:39 +0000299 REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000300 REPORTER_ASSERT(reporter, SkScalarIsFinite(big));
301 REPORTER_ASSERT(reporter, SkScalarIsFinite(-big));
302 REPORTER_ASSERT(reporter, SkScalarIsFinite(0));
reed@google.com077910e2011-02-08 21:56:39 +0000303}
304
reed@android.comed673312009-02-27 16:24:51 +0000305#endif
306
307static void test_muldiv255(skiatest::Reporter* reporter) {
308#ifdef SK_CAN_USE_FLOAT
309 for (int a = 0; a <= 255; a++) {
310 for (int b = 0; b <= 255; b++) {
311 int ab = a * b;
312 float s = ab / 255.0f;
313 int round = (int)floorf(s + 0.5f);
314 int trunc = (int)floorf(s);
reed@android.com80e39a72009-04-02 16:59:40 +0000315
reed@android.comed673312009-02-27 16:24:51 +0000316 int iround = SkMulDiv255Round(a, b);
317 int itrunc = SkMulDiv255Trunc(a, b);
reed@android.com80e39a72009-04-02 16:59:40 +0000318
reed@android.comed673312009-02-27 16:24:51 +0000319 REPORTER_ASSERT(reporter, iround == round);
320 REPORTER_ASSERT(reporter, itrunc == trunc);
reed@android.com80e39a72009-04-02 16:59:40 +0000321
reed@android.comed673312009-02-27 16:24:51 +0000322 REPORTER_ASSERT(reporter, itrunc <= iround);
323 REPORTER_ASSERT(reporter, iround <= a);
324 REPORTER_ASSERT(reporter, iround <= b);
325 }
326 }
327#endif
328}
329
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000330static void test_muldiv255ceiling(skiatest::Reporter* reporter) {
331 for (int c = 0; c <= 255; c++) {
332 for (int a = 0; a <= 255; a++) {
333 int product = (c * a + 255);
334 int expected_ceiling = (product + (product >> 8)) >> 8;
335 int webkit_ceiling = (c * a + 254) / 255;
336 REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling);
337 int skia_ceiling = SkMulDiv255Ceiling(c, a);
338 REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling);
339 }
340 }
341}
342
reed@android.comf0ad0862010-02-09 19:18:38 +0000343static void test_copysign(skiatest::Reporter* reporter) {
344 static const int32_t gTriples[] = {
345 // x, y, expected result
346 0, 0, 0,
347 0, 1, 0,
348 0, -1, 0,
349 1, 0, 1,
350 1, 1, 1,
351 1, -1, -1,
352 -1, 0, 1,
353 -1, 1, 1,
354 -1, -1, -1,
355 };
356 for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) {
357 REPORTER_ASSERT(reporter,
358 SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]);
359#ifdef SK_CAN_USE_FLOAT
360 float x = (float)gTriples[i];
361 float y = (float)gTriples[i+1];
362 float expected = (float)gTriples[i+2];
363 REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected);
364#endif
365 }
366
367 SkRandom rand;
368 for (int j = 0; j < 1000; j++) {
369 int ix = rand.nextS();
370 REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix);
371 REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix);
372 REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix);
373 REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix);
374
375 SkScalar sx = rand.nextSScalar1();
376 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx);
377 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
378 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx);
379 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
380 }
381}
382
reed@android.com80e39a72009-04-02 16:59:40 +0000383static void TestMath(skiatest::Reporter* reporter) {
reed@android.comed673312009-02-27 16:24:51 +0000384 int i;
385 int32_t x;
386 SkRandom rand;
reed@android.com80e39a72009-04-02 16:59:40 +0000387
reed@android.comed673312009-02-27 16:24:51 +0000388 // these should assert
389#if 0
390 SkToS8(128);
391 SkToS8(-129);
392 SkToU8(256);
393 SkToU8(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000394
reed@android.comed673312009-02-27 16:24:51 +0000395 SkToS16(32768);
396 SkToS16(-32769);
397 SkToU16(65536);
398 SkToU16(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000399
reed@android.comed673312009-02-27 16:24:51 +0000400 if (sizeof(size_t) > 4) {
401 SkToS32(4*1024*1024);
402 SkToS32(-4*1024*1024);
403 SkToU32(5*1024*1024);
404 SkToU32(-5);
405 }
406#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000407
reed@android.comed673312009-02-27 16:24:51 +0000408 test_muldiv255(reporter);
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000409 test_muldiv255ceiling(reporter);
reed@android.comf0ad0862010-02-09 19:18:38 +0000410 test_copysign(reporter);
reed@android.com80e39a72009-04-02 16:59:40 +0000411
reed@android.comed673312009-02-27 16:24:51 +0000412 {
413 SkScalar x = SK_ScalarNaN;
414 REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
415 }
reed@android.com80e39a72009-04-02 16:59:40 +0000416
reed@android.comed673312009-02-27 16:24:51 +0000417 for (i = 1; i <= 10; i++) {
418 x = SkCubeRootBits(i*i*i, 11);
419 REPORTER_ASSERT(reporter, x == i);
420 }
reed@android.com80e39a72009-04-02 16:59:40 +0000421
reed@android.comed673312009-02-27 16:24:51 +0000422 x = SkFixedSqrt(SK_Fixed1);
423 REPORTER_ASSERT(reporter, x == SK_Fixed1);
424 x = SkFixedSqrt(SK_Fixed1/4);
425 REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
426 x = SkFixedSqrt(SK_Fixed1*4);
427 REPORTER_ASSERT(reporter, x == SK_Fixed1*2);
reed@android.com80e39a72009-04-02 16:59:40 +0000428
reed@android.comed673312009-02-27 16:24:51 +0000429 x = SkFractSqrt(SK_Fract1);
430 REPORTER_ASSERT(reporter, x == SK_Fract1);
431 x = SkFractSqrt(SK_Fract1/4);
432 REPORTER_ASSERT(reporter, x == SK_Fract1/2);
433 x = SkFractSqrt(SK_Fract1/16);
434 REPORTER_ASSERT(reporter, x == SK_Fract1/4);
reed@android.com80e39a72009-04-02 16:59:40 +0000435
reed@android.comed673312009-02-27 16:24:51 +0000436 for (i = 1; i < 100; i++) {
437 x = SkFixedSqrt(SK_Fixed1 * i * i);
438 REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
439 }
reed@android.com80e39a72009-04-02 16:59:40 +0000440
reed@android.comed673312009-02-27 16:24:51 +0000441 for (i = 0; i < 1000; i++) {
442 int value = rand.nextS16();
443 int max = rand.nextU16();
reed@android.com80e39a72009-04-02 16:59:40 +0000444
reed@android.comed673312009-02-27 16:24:51 +0000445 int clamp = SkClampMax(value, max);
446 int clamp2 = value < 0 ? 0 : (value > max ? max : value);
447 REPORTER_ASSERT(reporter, clamp == clamp2);
448 }
reed@android.com80e39a72009-04-02 16:59:40 +0000449
reed@android.come72fee52009-11-16 14:52:01 +0000450 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000451 SkPoint p;
reed@android.com80e39a72009-04-02 16:59:40 +0000452
tomhudson@google.com75589252012-04-10 17:42:21 +0000453 // These random values are being treated as 32-bit-patterns, not as
454 // ints; calling SkIntToScalar() here produces crashes.
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000455 p.setLength((SkScalar) rand.nextS(),
456 (SkScalar) rand.nextS(),
457 SK_Scalar1);
reed@android.comed673312009-02-27 16:24:51 +0000458 check_length(reporter, p, SK_Scalar1);
robertphillips@google.com4debcac2012-05-14 16:33:36 +0000459 p.setLength((SkScalar) (rand.nextS() >> 13),
460 (SkScalar) (rand.nextS() >> 13),
461 SK_Scalar1);
reed@android.comed673312009-02-27 16:24:51 +0000462 check_length(reporter, p, SK_Scalar1);
463 }
reed@android.com80e39a72009-04-02 16:59:40 +0000464
reed@android.comed673312009-02-27 16:24:51 +0000465 {
466 SkFixed result = SkFixedDiv(100, 100);
467 REPORTER_ASSERT(reporter, result == SK_Fixed1);
468 result = SkFixedDiv(1, SK_Fixed1);
469 REPORTER_ASSERT(reporter, result == 1);
470 }
reed@android.com80e39a72009-04-02 16:59:40 +0000471
reed@android.comed673312009-02-27 16:24:51 +0000472#ifdef SK_CAN_USE_FLOAT
473 unittest_fastfloat(reporter);
reed@google.com077910e2011-02-08 21:56:39 +0000474 unittest_isfinite(reporter);
reed@android.comed673312009-02-27 16:24:51 +0000475#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000476
reed@android.comed673312009-02-27 16:24:51 +0000477#ifdef SkLONGLONG
reed@android.come72fee52009-11-16 14:52:01 +0000478 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000479 SkFixed numer = rand.nextS();
480 SkFixed denom = rand.nextS();
481 SkFixed result = SkFixedDiv(numer, denom);
482 SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000483
reed@android.comed673312009-02-27 16:24:51 +0000484 (void)SkCLZ(numer);
485 (void)SkCLZ(denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000486
reed@android.comed673312009-02-27 16:24:51 +0000487 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
488 if (check > SK_MaxS32) {
489 check = SK_MaxS32;
490 } else if (check < -SK_MaxS32) {
491 check = SK_MinS32;
492 }
493 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000494
reed@android.comed673312009-02-27 16:24:51 +0000495 result = SkFractDiv(numer, denom);
496 check = ((SkLONGLONG)numer << 30) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000497
reed@android.comed673312009-02-27 16:24:51 +0000498 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
499 if (check > SK_MaxS32) {
500 check = SK_MaxS32;
501 } else if (check < -SK_MaxS32) {
502 check = SK_MinS32;
503 }
504 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000505
reed@android.comed673312009-02-27 16:24:51 +0000506 // make them <= 2^24, so we don't overflow in fixmul
507 numer = numer << 8 >> 8;
508 denom = denom << 8 >> 8;
reed@android.com80e39a72009-04-02 16:59:40 +0000509
reed@android.comed673312009-02-27 16:24:51 +0000510 result = SkFixedMul(numer, denom);
511 SkFixed r2 = symmetric_fixmul(numer, denom);
512 // SkASSERT(result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000513
reed@android.comed673312009-02-27 16:24:51 +0000514 result = SkFixedMul(numer, numer);
515 r2 = SkFixedSquare(numer);
516 REPORTER_ASSERT(reporter, result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000517
reed@android.comed673312009-02-27 16:24:51 +0000518#ifdef SK_CAN_USE_FLOAT
519 if (numer >= 0 && denom >= 0) {
520 SkFixed mean = SkFixedMean(numer, denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000521 float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom);
522 float fm = sk_float_sqrt(sk_float_abs(prod));
reed@android.comed673312009-02-27 16:24:51 +0000523 SkFixed mean2 = SkFloatToFixed(fm);
524 int diff = SkAbs32(mean - mean2);
525 REPORTER_ASSERT(reporter, diff <= 1);
526 }
reed@android.com80e39a72009-04-02 16:59:40 +0000527
reed@android.comed673312009-02-27 16:24:51 +0000528 {
529 SkFixed mod = SkFixedMod(numer, denom);
530 float n = SkFixedToFloat(numer);
531 float d = SkFixedToFloat(denom);
532 float m = sk_float_mod(n, d);
reed@android.com80e39a72009-04-02 16:59:40 +0000533 // ensure the same sign
534 REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0));
reed@android.comed673312009-02-27 16:24:51 +0000535 int diff = SkAbs32(mod - SkFloatToFixed(m));
536 REPORTER_ASSERT(reporter, (diff >> 7) == 0);
537 }
538#endif
539 }
540#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000541
reed@android.comed673312009-02-27 16:24:51 +0000542#ifdef SK_CAN_USE_FLOAT
reed@android.come72fee52009-11-16 14:52:01 +0000543 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000544 SkFract x = rand.nextU() >> 1;
545 double xx = (double)x / SK_Fract1;
546 SkFract xr = SkFractSqrt(x);
547 SkFract check = SkFloatToFract(sqrt(xx));
reed@android.com80e39a72009-04-02 16:59:40 +0000548 REPORTER_ASSERT(reporter, xr == check ||
549 xr == check-1 ||
550 xr == check+1);
551
reed@android.comed673312009-02-27 16:24:51 +0000552 xr = SkFixedSqrt(x);
553 xx = (double)x / SK_Fixed1;
554 check = SkFloatToFixed(sqrt(xx));
555 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
reed@android.com80e39a72009-04-02 16:59:40 +0000556
reed@android.comed673312009-02-27 16:24:51 +0000557 xr = SkSqrt32(x);
558 xx = (double)x;
559 check = (int32_t)sqrt(xx);
560 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
561 }
562#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000563
reed@android.comed673312009-02-27 16:24:51 +0000564#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
565 {
566 SkFixed s, c;
567 s = SkFixedSinCos(0, &c);
568 REPORTER_ASSERT(reporter, s == 0);
569 REPORTER_ASSERT(reporter, c == SK_Fixed1);
570 }
reed@android.com80e39a72009-04-02 16:59:40 +0000571
reed@android.comed673312009-02-27 16:24:51 +0000572 int maxDiff = 0;
reed@android.come72fee52009-11-16 14:52:01 +0000573 for (i = 0; i < 1000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000574 SkFixed rads = rand.nextS() >> 10;
575 double frads = SkFixedToFloat(rads);
reed@android.com80e39a72009-04-02 16:59:40 +0000576
reed@android.comed673312009-02-27 16:24:51 +0000577 SkFixed s, c;
578 s = SkScalarSinCos(rads, &c);
reed@android.com80e39a72009-04-02 16:59:40 +0000579
reed@android.comed673312009-02-27 16:24:51 +0000580 double fs = sin(frads);
581 double fc = cos(frads);
reed@android.com80e39a72009-04-02 16:59:40 +0000582
reed@android.comed673312009-02-27 16:24:51 +0000583 SkFixed is = SkFloatToFixed(fs);
584 SkFixed ic = SkFloatToFixed(fc);
reed@android.com80e39a72009-04-02 16:59:40 +0000585
reed@android.comed673312009-02-27 16:24:51 +0000586 maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
587 maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
588 }
589 SkDebugf("SinCos: maximum error = %d\n", maxDiff);
590#endif
reed@google.com772813a2011-03-30 22:34:45 +0000591
reed@google.com0abb4992011-10-06 20:04:36 +0000592#ifdef SK_SCALAR_IS_FLOAT
593 test_blend(reporter);
594#endif
reed@google.com8d7e39c2011-11-09 17:12:08 +0000595
reed@google.coma7d74612012-05-30 12:30:09 +0000596#ifdef SK_CAN_USE_FLOAT
597 test_floor(reporter);
598#endif
599
reed@google.com8d7e39c2011-11-09 17:12:08 +0000600 // disable for now
601// test_blend31();
reed@android.comed673312009-02-27 16:24:51 +0000602}
603
reed@android.comd8730ea2009-02-27 22:06:06 +0000604#include "TestClassDef.h"
605DEFINE_TESTCLASS("Math", MathTestClass, TestMath)