• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "Test.h"
9 #include "SkFloatingPoint.h"
10 #include "SkMath.h"
11 #include "SkPoint.h"
12 #include "SkRandom.h"
13 
14 #ifdef SK_CAN_USE_FLOAT
15 
isFinite_int(float x)16 static bool isFinite_int(float x) {
17     uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
18     int exponent = bits << 1 >> 24;
19     return exponent != 0xFF;
20 }
21 
isFinite_float(float x)22 static bool isFinite_float(float x) {
23     return sk_float_isfinite(x);
24 }
25 
isFinite_mulzero(float x)26 static bool isFinite_mulzero(float x) {
27     float y = x * 0;
28     return y == y;
29 }
30 
31 // return true if the float is finite
32 typedef bool (*IsFiniteProc1)(float);
33 
isFinite2_and(float x,float y,IsFiniteProc1 proc)34 static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
35     return proc(x) && proc(y);
36 }
37 
isFinite2_mulzeroadd(float x,float y,IsFiniteProc1 proc)38 static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
39     return proc(x * 0 + y * 0);
40 }
41 
42 // return true if both floats are finite
43 typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
44 
45 #endif
46 
47 enum FloatClass {
48     kFinite,
49     kInfinite,
50     kNaN
51 };
52 
test_floatclass(skiatest::Reporter * reporter,float value,FloatClass fc)53 static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
54     // our sk_float_is... function may return int instead of bool,
55     // hence the double ! to turn it into a bool
56     REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
57     REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
58     REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
59 }
60 
test_isfinite(skiatest::Reporter * reporter)61 static void test_isfinite(skiatest::Reporter* reporter) {
62 #ifdef SK_CAN_USE_FLOAT
63     struct Rec {
64         float   fValue;
65         bool    fIsFinite;
66     };
67 
68     float max = 3.402823466e+38f;
69     float inf = max * max;
70     float nan = inf * 0;
71 
72     test_floatclass(reporter,    0, kFinite);
73     test_floatclass(reporter,  max, kFinite);
74     test_floatclass(reporter, -max, kFinite);
75     test_floatclass(reporter,  inf, kInfinite);
76     test_floatclass(reporter, -inf, kInfinite);
77     test_floatclass(reporter,  nan, kNaN);
78     test_floatclass(reporter, -nan, kNaN);
79 
80     const Rec data[] = {
81         {   0,          true    },
82         {   1,          true    },
83         {  -1,          true    },
84         {  max * 0.75,  true    },
85         {  max,         true    },
86         {  -max * 0.75, true    },
87         {  -max,        true    },
88         {  inf,         false   },
89         { -inf,         false   },
90         {  nan,         false   },
91     };
92 
93     const IsFiniteProc1 gProc1[] = {
94         isFinite_int,
95         isFinite_float,
96         isFinite_mulzero
97     };
98     const IsFiniteProc2 gProc2[] = {
99         isFinite2_and,
100         isFinite2_mulzeroadd
101     };
102 
103     size_t i, n = SK_ARRAY_COUNT(data);
104 
105     for (i = 0; i < n; ++i) {
106         for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
107             const Rec& rec = data[i];
108             bool finite = gProc1[k](rec.fValue);
109             REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
110         }
111     }
112 
113     for (i = 0; i < n; ++i) {
114         const Rec& rec0 = data[i];
115         for (size_t j = 0; j < n; ++j) {
116             const Rec& rec1 = data[j];
117             for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
118                 IsFiniteProc1 proc1 = gProc1[k];
119 
120                 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
121                     bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
122                     bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
123                     REPORTER_ASSERT(reporter, finite2 == finite);
124                 }
125             }
126         }
127     }
128 #endif
129 }
130 
TestScalar(skiatest::Reporter * reporter)131 static void TestScalar(skiatest::Reporter* reporter) {
132     test_isfinite(reporter);
133 }
134 
135 #include "TestClassDef.h"
136 DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
137 
138