blob: 7440dfde1a3a5e7e7aa05c6efeb6f25202420698 [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"
13
reed@google.com772813a2011-03-30 22:34:45 +000014#if 0
15static U8CPU premul_fast(U8CPU a, U8CPU x) {
16 return a * x * 32897 >> 23;
17}
18
19static U8CPU premul_trunc(U8CPU a, U8CPU x) {
20 double result = a * x;
21 result /= 255.0;
22 return (unsigned)floor(result + 0.0);
23}
24
25static U8CPU premul_round(U8CPU a, U8CPU x) {
26 double result = a * x;
27 result /= 255.0;
28 return (unsigned)floor(result + 0.5);
29}
30
31static void test_premul(skiatest::Reporter* reporter) {
32 for (int a = 0; a <= 255; a++) {
33 for (int x = 0; x <= 255; x++) {
34 unsigned curr_trunc = SkMulDiv255Trunc(a, x);
35 unsigned curr_round = SkMulDiv255Round(a, x);
36 unsigned fast = premul_fast(a, x);
37 unsigned slow_round = premul_round(a, x);
38 unsigned slow_trunc = premul_trunc(a, x);
39 if (fast != slow || curr != fast) {
40 SkDebugf("---- premul(%d %d) curr=%d fast=%d slow=%d\n", a, x,
41 curr, fast, slow);
42 }
43 }
44 }
45}
46#endif
47
reed@android.comed673312009-02-27 16:24:51 +000048#if defined(SkLONGLONG)
49static int symmetric_fixmul(int a, int b) {
50 int sa = SkExtractSign(a);
51 int sb = SkExtractSign(b);
reed@android.com80e39a72009-04-02 16:59:40 +000052
reed@android.comed673312009-02-27 16:24:51 +000053 a = SkApplySign(a, sa);
54 b = SkApplySign(b, sb);
reed@android.com80e39a72009-04-02 16:59:40 +000055
reed@android.comed673312009-02-27 16:24:51 +000056#if 1
57 int c = (int)(((SkLONGLONG)a * b) >> 16);
reed@android.com80e39a72009-04-02 16:59:40 +000058
reed@android.comed673312009-02-27 16:24:51 +000059 return SkApplySign(c, sa ^ sb);
60#else
61 SkLONGLONG ab = (SkLONGLONG)a * b;
62 if (sa ^ sb) {
63 ab = -ab;
64 }
65 return ab >> 16;
66#endif
67}
68#endif
69
70static void check_length(skiatest::Reporter* reporter,
71 const SkPoint& p, SkScalar targetLen) {
72#ifdef SK_CAN_USE_FLOAT
73 float x = SkScalarToFloat(p.fX);
74 float y = SkScalarToFloat(p.fY);
75 float len = sk_float_sqrt(x*x + y*y);
reed@android.com80e39a72009-04-02 16:59:40 +000076
reed@android.comed673312009-02-27 16:24:51 +000077 len /= SkScalarToFloat(targetLen);
reed@android.com80e39a72009-04-02 16:59:40 +000078
reed@android.comed673312009-02-27 16:24:51 +000079 REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
80#endif
81}
82
83#if defined(SK_CAN_USE_FLOAT)
84
85static float nextFloat(SkRandom& rand) {
86 SkFloatIntUnion data;
87 data.fSignBitInt = rand.nextU();
88 return data.fFloat;
89}
90
91/* returns true if a == b as resulting from (int)x. Since it is undefined
92 what to do if the float exceeds 2^32-1, we check for that explicitly.
93 */
94static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
95 if (!(x == x)) { // NAN
96 return si == SK_MaxS32 || si == SK_MinS32;
97 }
98 // for out of range, C is undefined, but skia always should return NaN32
99 if (x > SK_MaxS32) {
100 return si == SK_MaxS32;
101 }
102 if (x < -SK_MaxS32) {
103 return si == SK_MinS32;
104 }
105 return si == ni;
106}
107
108static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
109 float x, uint32_t ni, uint32_t si) {
110 if (!equal_float_native_skia(x, ni, si)) {
111 SkString desc;
112 desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si);
113 reporter->reportFailed(desc);
114 }
115}
116
117static void test_float_cast(skiatest::Reporter* reporter, float x) {
118 int ix = (int)x;
119 int iix = SkFloatToIntCast(x);
120 assert_float_equal(reporter, "cast", x, ix, iix);
121}
122
123static void test_float_floor(skiatest::Reporter* reporter, float x) {
124 int ix = (int)floor(x);
125 int iix = SkFloatToIntFloor(x);
126 assert_float_equal(reporter, "floor", x, ix, iix);
127}
128
129static void test_float_round(skiatest::Reporter* reporter, float x) {
130 double xx = x + 0.5; // need intermediate double to avoid temp loss
131 int ix = (int)floor(xx);
132 int iix = SkFloatToIntRound(x);
133 assert_float_equal(reporter, "round", x, ix, iix);
134}
135
136static void test_float_ceil(skiatest::Reporter* reporter, float x) {
137 int ix = (int)ceil(x);
138 int iix = SkFloatToIntCeil(x);
139 assert_float_equal(reporter, "ceil", x, ix, iix);
140}
141
142static void test_float_conversions(skiatest::Reporter* reporter, float x) {
143 test_float_cast(reporter, x);
144 test_float_floor(reporter, x);
145 test_float_round(reporter, x);
146 test_float_ceil(reporter, x);
147}
148
149static void test_int2float(skiatest::Reporter* reporter, int ival) {
150 float x0 = (float)ival;
151 float x1 = SkIntToFloatCast(ival);
152 float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
153 REPORTER_ASSERT(reporter, x0 == x1);
154 REPORTER_ASSERT(reporter, x0 == x2);
155}
156
157static void unittest_fastfloat(skiatest::Reporter* reporter) {
158 SkRandom rand;
159 size_t i;
reed@android.com80e39a72009-04-02 16:59:40 +0000160
reed@android.comed673312009-02-27 16:24:51 +0000161 static const float gFloats[] = {
162 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
163 0.000000001f, 1000000000.f, // doesn't overflow
164 0.0000000001f, 10000000000.f // does overflow
165 };
166 for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
reed@android.comed673312009-02-27 16:24:51 +0000167 test_float_conversions(reporter, gFloats[i]);
168 test_float_conversions(reporter, -gFloats[i]);
169 }
reed@android.com80e39a72009-04-02 16:59:40 +0000170
reed@android.comed673312009-02-27 16:24:51 +0000171 for (int outer = 0; outer < 100; outer++) {
172 rand.setSeed(outer);
173 for (i = 0; i < 100000; i++) {
174 float x = nextFloat(rand);
175 test_float_conversions(reporter, x);
176 }
reed@android.com80e39a72009-04-02 16:59:40 +0000177
reed@android.comed673312009-02-27 16:24:51 +0000178 test_int2float(reporter, 0);
179 test_int2float(reporter, 1);
180 test_int2float(reporter, -1);
181 for (i = 0; i < 100000; i++) {
182 // for now only test ints that are 24bits or less, since we don't
183 // round (down) large ints the same as IEEE...
184 int ival = rand.nextU() & 0xFFFFFF;
185 test_int2float(reporter, ival);
186 test_int2float(reporter, -ival);
187 }
188 }
189}
190
reed@android.comd4134452011-02-09 02:24:26 +0000191#ifdef SK_SCALAR_IS_FLOAT
reed@google.com077910e2011-02-08 21:56:39 +0000192static float make_zero() {
193 return sk_float_sin(0);
194}
reed@android.comd4134452011-02-09 02:24:26 +0000195#endif
reed@google.com077910e2011-02-08 21:56:39 +0000196
197static void unittest_isfinite(skiatest::Reporter* reporter) {
198#ifdef SK_SCALAR_IS_FLOAT
epoger@google.combf083a92011-06-08 18:26:08 +0000199 float nan = sk_float_asin(2);
reed@google.com077910e2011-02-08 21:56:39 +0000200 float inf = 1.0 / make_zero();
201 float big = 3.40282e+038;
202
reed@google.com077910e2011-02-08 21:56:39 +0000203 REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf));
reed@android.comd4134452011-02-09 02:24:26 +0000204 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf));
205 REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf));
206 REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf));
207#else
208 SkFixed nan = SK_FixedNaN;
209 SkFixed big = SK_FixedMax;
210#endif
211
212 REPORTER_ASSERT(reporter, SkScalarIsNaN(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000213 REPORTER_ASSERT(reporter, !SkScalarIsNaN(big));
214 REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big));
215 REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
reed@android.comd4134452011-02-09 02:24:26 +0000216
reed@google.com077910e2011-02-08 21:56:39 +0000217 REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan));
reed@google.com077910e2011-02-08 21:56:39 +0000218 REPORTER_ASSERT(reporter, SkScalarIsFinite(big));
219 REPORTER_ASSERT(reporter, SkScalarIsFinite(-big));
220 REPORTER_ASSERT(reporter, SkScalarIsFinite(0));
reed@google.com077910e2011-02-08 21:56:39 +0000221}
222
reed@android.comed673312009-02-27 16:24:51 +0000223#endif
224
225static void test_muldiv255(skiatest::Reporter* reporter) {
226#ifdef SK_CAN_USE_FLOAT
227 for (int a = 0; a <= 255; a++) {
228 for (int b = 0; b <= 255; b++) {
229 int ab = a * b;
230 float s = ab / 255.0f;
231 int round = (int)floorf(s + 0.5f);
232 int trunc = (int)floorf(s);
reed@android.com80e39a72009-04-02 16:59:40 +0000233
reed@android.comed673312009-02-27 16:24:51 +0000234 int iround = SkMulDiv255Round(a, b);
235 int itrunc = SkMulDiv255Trunc(a, b);
reed@android.com80e39a72009-04-02 16:59:40 +0000236
reed@android.comed673312009-02-27 16:24:51 +0000237 REPORTER_ASSERT(reporter, iround == round);
238 REPORTER_ASSERT(reporter, itrunc == trunc);
reed@android.com80e39a72009-04-02 16:59:40 +0000239
reed@android.comed673312009-02-27 16:24:51 +0000240 REPORTER_ASSERT(reporter, itrunc <= iround);
241 REPORTER_ASSERT(reporter, iround <= a);
242 REPORTER_ASSERT(reporter, iround <= b);
243 }
244 }
245#endif
246}
247
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000248static void test_muldiv255ceiling(skiatest::Reporter* reporter) {
249 for (int c = 0; c <= 255; c++) {
250 for (int a = 0; a <= 255; a++) {
251 int product = (c * a + 255);
252 int expected_ceiling = (product + (product >> 8)) >> 8;
253 int webkit_ceiling = (c * a + 254) / 255;
254 REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling);
255 int skia_ceiling = SkMulDiv255Ceiling(c, a);
256 REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling);
257 }
258 }
259}
260
reed@android.comf0ad0862010-02-09 19:18:38 +0000261static void test_copysign(skiatest::Reporter* reporter) {
262 static const int32_t gTriples[] = {
263 // x, y, expected result
264 0, 0, 0,
265 0, 1, 0,
266 0, -1, 0,
267 1, 0, 1,
268 1, 1, 1,
269 1, -1, -1,
270 -1, 0, 1,
271 -1, 1, 1,
272 -1, -1, -1,
273 };
274 for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) {
275 REPORTER_ASSERT(reporter,
276 SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]);
277#ifdef SK_CAN_USE_FLOAT
278 float x = (float)gTriples[i];
279 float y = (float)gTriples[i+1];
280 float expected = (float)gTriples[i+2];
281 REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected);
282#endif
283 }
284
285 SkRandom rand;
286 for (int j = 0; j < 1000; j++) {
287 int ix = rand.nextS();
288 REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix);
289 REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix);
290 REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix);
291 REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix);
292
293 SkScalar sx = rand.nextSScalar1();
294 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx);
295 REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
296 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx);
297 REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
298 }
299}
300
reed@android.com80e39a72009-04-02 16:59:40 +0000301static void TestMath(skiatest::Reporter* reporter) {
reed@android.comed673312009-02-27 16:24:51 +0000302 int i;
303 int32_t x;
304 SkRandom rand;
reed@android.com80e39a72009-04-02 16:59:40 +0000305
reed@android.comed673312009-02-27 16:24:51 +0000306 // these should assert
307#if 0
308 SkToS8(128);
309 SkToS8(-129);
310 SkToU8(256);
311 SkToU8(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000312
reed@android.comed673312009-02-27 16:24:51 +0000313 SkToS16(32768);
314 SkToS16(-32769);
315 SkToU16(65536);
316 SkToU16(-5);
reed@android.com80e39a72009-04-02 16:59:40 +0000317
reed@android.comed673312009-02-27 16:24:51 +0000318 if (sizeof(size_t) > 4) {
319 SkToS32(4*1024*1024);
320 SkToS32(-4*1024*1024);
321 SkToU32(5*1024*1024);
322 SkToU32(-5);
323 }
324#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000325
reed@android.comed673312009-02-27 16:24:51 +0000326 test_muldiv255(reporter);
senorblanco@chromium.orgec7a30c2010-12-07 21:07:56 +0000327 test_muldiv255ceiling(reporter);
reed@android.comf0ad0862010-02-09 19:18:38 +0000328 test_copysign(reporter);
reed@android.com80e39a72009-04-02 16:59:40 +0000329
reed@android.comed673312009-02-27 16:24:51 +0000330 {
331 SkScalar x = SK_ScalarNaN;
332 REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
333 }
reed@android.com80e39a72009-04-02 16:59:40 +0000334
reed@android.comed673312009-02-27 16:24:51 +0000335 for (i = 1; i <= 10; i++) {
336 x = SkCubeRootBits(i*i*i, 11);
337 REPORTER_ASSERT(reporter, x == i);
338 }
reed@android.com80e39a72009-04-02 16:59:40 +0000339
reed@android.comed673312009-02-27 16:24:51 +0000340 x = SkFixedSqrt(SK_Fixed1);
341 REPORTER_ASSERT(reporter, x == SK_Fixed1);
342 x = SkFixedSqrt(SK_Fixed1/4);
343 REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
344 x = SkFixedSqrt(SK_Fixed1*4);
345 REPORTER_ASSERT(reporter, x == SK_Fixed1*2);
reed@android.com80e39a72009-04-02 16:59:40 +0000346
reed@android.comed673312009-02-27 16:24:51 +0000347 x = SkFractSqrt(SK_Fract1);
348 REPORTER_ASSERT(reporter, x == SK_Fract1);
349 x = SkFractSqrt(SK_Fract1/4);
350 REPORTER_ASSERT(reporter, x == SK_Fract1/2);
351 x = SkFractSqrt(SK_Fract1/16);
352 REPORTER_ASSERT(reporter, x == SK_Fract1/4);
reed@android.com80e39a72009-04-02 16:59:40 +0000353
reed@android.comed673312009-02-27 16:24:51 +0000354 for (i = 1; i < 100; i++) {
355 x = SkFixedSqrt(SK_Fixed1 * i * i);
356 REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
357 }
reed@android.com80e39a72009-04-02 16:59:40 +0000358
reed@android.comed673312009-02-27 16:24:51 +0000359 for (i = 0; i < 1000; i++) {
360 int value = rand.nextS16();
361 int max = rand.nextU16();
reed@android.com80e39a72009-04-02 16:59:40 +0000362
reed@android.comed673312009-02-27 16:24:51 +0000363 int clamp = SkClampMax(value, max);
364 int clamp2 = value < 0 ? 0 : (value > max ? max : value);
365 REPORTER_ASSERT(reporter, clamp == clamp2);
366 }
reed@android.com80e39a72009-04-02 16:59:40 +0000367
reed@android.come72fee52009-11-16 14:52:01 +0000368 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000369 SkPoint p;
reed@android.com80e39a72009-04-02 16:59:40 +0000370
reed@android.comed673312009-02-27 16:24:51 +0000371 p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1);
372 check_length(reporter, p, SK_Scalar1);
373 p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1);
374 check_length(reporter, p, SK_Scalar1);
375 }
reed@android.com80e39a72009-04-02 16:59:40 +0000376
reed@android.comed673312009-02-27 16:24:51 +0000377 {
378 SkFixed result = SkFixedDiv(100, 100);
379 REPORTER_ASSERT(reporter, result == SK_Fixed1);
380 result = SkFixedDiv(1, SK_Fixed1);
381 REPORTER_ASSERT(reporter, result == 1);
382 }
reed@android.com80e39a72009-04-02 16:59:40 +0000383
reed@android.comed673312009-02-27 16:24:51 +0000384#ifdef SK_CAN_USE_FLOAT
385 unittest_fastfloat(reporter);
reed@google.com077910e2011-02-08 21:56:39 +0000386 unittest_isfinite(reporter);
reed@android.comed673312009-02-27 16:24:51 +0000387#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000388
reed@android.comed673312009-02-27 16:24:51 +0000389#ifdef SkLONGLONG
reed@android.come72fee52009-11-16 14:52:01 +0000390 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000391 SkFixed numer = rand.nextS();
392 SkFixed denom = rand.nextS();
393 SkFixed result = SkFixedDiv(numer, denom);
394 SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000395
reed@android.comed673312009-02-27 16:24:51 +0000396 (void)SkCLZ(numer);
397 (void)SkCLZ(denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000398
reed@android.comed673312009-02-27 16:24:51 +0000399 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
400 if (check > SK_MaxS32) {
401 check = SK_MaxS32;
402 } else if (check < -SK_MaxS32) {
403 check = SK_MinS32;
404 }
405 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000406
reed@android.comed673312009-02-27 16:24:51 +0000407 result = SkFractDiv(numer, denom);
408 check = ((SkLONGLONG)numer << 30) / denom;
reed@android.com80e39a72009-04-02 16:59:40 +0000409
reed@android.comed673312009-02-27 16:24:51 +0000410 REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
411 if (check > SK_MaxS32) {
412 check = SK_MaxS32;
413 } else if (check < -SK_MaxS32) {
414 check = SK_MinS32;
415 }
416 REPORTER_ASSERT(reporter, result == (int32_t)check);
reed@android.com80e39a72009-04-02 16:59:40 +0000417
reed@android.comed673312009-02-27 16:24:51 +0000418 // make them <= 2^24, so we don't overflow in fixmul
419 numer = numer << 8 >> 8;
420 denom = denom << 8 >> 8;
reed@android.com80e39a72009-04-02 16:59:40 +0000421
reed@android.comed673312009-02-27 16:24:51 +0000422 result = SkFixedMul(numer, denom);
423 SkFixed r2 = symmetric_fixmul(numer, denom);
424 // SkASSERT(result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000425
reed@android.comed673312009-02-27 16:24:51 +0000426 result = SkFixedMul(numer, numer);
427 r2 = SkFixedSquare(numer);
428 REPORTER_ASSERT(reporter, result == r2);
reed@android.com80e39a72009-04-02 16:59:40 +0000429
reed@android.comed673312009-02-27 16:24:51 +0000430#ifdef SK_CAN_USE_FLOAT
431 if (numer >= 0 && denom >= 0) {
432 SkFixed mean = SkFixedMean(numer, denom);
reed@android.com80e39a72009-04-02 16:59:40 +0000433 float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom);
434 float fm = sk_float_sqrt(sk_float_abs(prod));
reed@android.comed673312009-02-27 16:24:51 +0000435 SkFixed mean2 = SkFloatToFixed(fm);
436 int diff = SkAbs32(mean - mean2);
437 REPORTER_ASSERT(reporter, diff <= 1);
438 }
reed@android.com80e39a72009-04-02 16:59:40 +0000439
reed@android.comed673312009-02-27 16:24:51 +0000440 {
441 SkFixed mod = SkFixedMod(numer, denom);
442 float n = SkFixedToFloat(numer);
443 float d = SkFixedToFloat(denom);
444 float m = sk_float_mod(n, d);
reed@android.com80e39a72009-04-02 16:59:40 +0000445 // ensure the same sign
446 REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0));
reed@android.comed673312009-02-27 16:24:51 +0000447 int diff = SkAbs32(mod - SkFloatToFixed(m));
448 REPORTER_ASSERT(reporter, (diff >> 7) == 0);
449 }
450#endif
451 }
452#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000453
reed@android.comed673312009-02-27 16:24:51 +0000454#ifdef SK_CAN_USE_FLOAT
reed@android.come72fee52009-11-16 14:52:01 +0000455 for (i = 0; i < 10000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000456 SkFract x = rand.nextU() >> 1;
457 double xx = (double)x / SK_Fract1;
458 SkFract xr = SkFractSqrt(x);
459 SkFract check = SkFloatToFract(sqrt(xx));
reed@android.com80e39a72009-04-02 16:59:40 +0000460 REPORTER_ASSERT(reporter, xr == check ||
461 xr == check-1 ||
462 xr == check+1);
463
reed@android.comed673312009-02-27 16:24:51 +0000464 xr = SkFixedSqrt(x);
465 xx = (double)x / SK_Fixed1;
466 check = SkFloatToFixed(sqrt(xx));
467 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
reed@android.com80e39a72009-04-02 16:59:40 +0000468
reed@android.comed673312009-02-27 16:24:51 +0000469 xr = SkSqrt32(x);
470 xx = (double)x;
471 check = (int32_t)sqrt(xx);
472 REPORTER_ASSERT(reporter, xr == check || xr == check-1);
473 }
474#endif
reed@android.com80e39a72009-04-02 16:59:40 +0000475
reed@android.comed673312009-02-27 16:24:51 +0000476#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
477 {
478 SkFixed s, c;
479 s = SkFixedSinCos(0, &c);
480 REPORTER_ASSERT(reporter, s == 0);
481 REPORTER_ASSERT(reporter, c == SK_Fixed1);
482 }
reed@android.com80e39a72009-04-02 16:59:40 +0000483
reed@android.comed673312009-02-27 16:24:51 +0000484 int maxDiff = 0;
reed@android.come72fee52009-11-16 14:52:01 +0000485 for (i = 0; i < 1000; i++) {
reed@android.comed673312009-02-27 16:24:51 +0000486 SkFixed rads = rand.nextS() >> 10;
487 double frads = SkFixedToFloat(rads);
reed@android.com80e39a72009-04-02 16:59:40 +0000488
reed@android.comed673312009-02-27 16:24:51 +0000489 SkFixed s, c;
490 s = SkScalarSinCos(rads, &c);
reed@android.com80e39a72009-04-02 16:59:40 +0000491
reed@android.comed673312009-02-27 16:24:51 +0000492 double fs = sin(frads);
493 double fc = cos(frads);
reed@android.com80e39a72009-04-02 16:59:40 +0000494
reed@android.comed673312009-02-27 16:24:51 +0000495 SkFixed is = SkFloatToFixed(fs);
496 SkFixed ic = SkFloatToFixed(fc);
reed@android.com80e39a72009-04-02 16:59:40 +0000497
reed@android.comed673312009-02-27 16:24:51 +0000498 maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
499 maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
500 }
501 SkDebugf("SinCos: maximum error = %d\n", maxDiff);
502#endif
reed@google.com772813a2011-03-30 22:34:45 +0000503
504// test_premul(reporter);
reed@android.comed673312009-02-27 16:24:51 +0000505}
506
reed@android.comd8730ea2009-02-27 22:06:06 +0000507#include "TestClassDef.h"
508DEFINE_TESTCLASS("Math", MathTestClass, TestMath)