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