blob: 82f61ec5c54917c8b1cb9002f4dc72a1b25f6674 [file] [log] [blame]
reed@google.comd230e3e2011-12-05 20:49:37 +00001/*
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
reed@google.comd230e3e2011-12-05 20:49:37 +00008#include "SkFloatingPoint.h"
9#include "SkMath.h"
10#include "SkPoint.h"
11#include "SkRandom.h"
reed@google.com30d90eb2012-05-15 14:17:36 +000012#include "SkRect.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000013#include "Test.h"
reed@google.comd230e3e2011-12-05 20:49:37 +000014
reed@google.com30d90eb2012-05-15 14:17:36 +000015struct PointSet {
16 const SkPoint* fPts;
17 size_t fCount;
18 bool fIsFinite;
19};
20
21static void test_isRectFinite(skiatest::Reporter* reporter) {
22 static const SkPoint gF0[] = {
23 { 0, 0 }, { 1, 1 }
24 };
25 static const SkPoint gF1[] = {
26 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }
27 };
28
29 static const SkPoint gI0[] = {
30 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarNaN, 3 }, { 2, 3 },
31 };
32 static const SkPoint gI1[] = {
33 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarNaN }, { 2, 3 },
34 };
35 static const SkPoint gI2[] = {
36 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarInfinity, 3 }, { 2, 3 },
37 };
38 static const SkPoint gI3[] = {
39 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarInfinity }, { 2, 3 },
40 };
41
42 static const struct {
43 const SkPoint* fPts;
44 size_t fCount;
45 bool fIsFinite;
46 } gSets[] = {
47 { gF0, SK_ARRAY_COUNT(gF0), true },
48 { gF1, SK_ARRAY_COUNT(gF1), true },
49
50 { gI0, SK_ARRAY_COUNT(gI0), false },
51 { gI1, SK_ARRAY_COUNT(gI1), false },
52 { gI2, SK_ARRAY_COUNT(gI2), false },
53 { gI3, SK_ARRAY_COUNT(gI3), false },
54 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000055
reed@google.com30d90eb2012-05-15 14:17:36 +000056 for (size_t i = 0; i < SK_ARRAY_COUNT(gSets); ++i) {
57 SkRect r;
58 r.set(gSets[i].fPts, gSets[i].fCount);
59 bool rectIsFinite = !r.isEmpty();
60 REPORTER_ASSERT(reporter, gSets[i].fIsFinite == rectIsFinite);
61 }
62}
63
reed@google.comd230e3e2011-12-05 20:49:37 +000064static bool isFinite_int(float x) {
65 uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
66 int exponent = bits << 1 >> 24;
67 return exponent != 0xFF;
68}
69
70static bool isFinite_float(float x) {
robertphillips@google.com6853e802012-04-16 15:50:18 +000071 return SkToBool(sk_float_isfinite(x));
reed@google.comd230e3e2011-12-05 20:49:37 +000072}
73
74static bool isFinite_mulzero(float x) {
75 float y = x * 0;
76 return y == y;
77}
78
79// return true if the float is finite
80typedef bool (*IsFiniteProc1)(float);
81
82static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
83 return proc(x) && proc(y);
84}
85
86static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
87 return proc(x * 0 + y * 0);
88}
89
90// return true if both floats are finite
91typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
92
reed@google.com5ae777d2011-12-06 20:18:05 +000093enum FloatClass {
94 kFinite,
95 kInfinite,
96 kNaN
97};
98
99static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
100 // our sk_float_is... function may return int instead of bool,
101 // hence the double ! to turn it into a bool
102 REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
103 REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
104 REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
105}
106
robertphillips@google.com706f6212012-05-14 17:51:23 +0000107#if defined _WIN32
108#pragma warning ( push )
109// we are intentionally causing an overflow here
110// (warning C4756: overflow in constant arithmetic)
111#pragma warning ( disable : 4756 )
112#endif
113
reed@google.comd230e3e2011-12-05 20:49:37 +0000114static void test_isfinite(skiatest::Reporter* reporter) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000115 struct Rec {
116 float fValue;
117 bool fIsFinite;
118 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000119
reed@google.comd230e3e2011-12-05 20:49:37 +0000120 float max = 3.402823466e+38f;
121 float inf = max * max;
reed@google.com5ae777d2011-12-06 20:18:05 +0000122 float nan = inf * 0;
123
124 test_floatclass(reporter, 0, kFinite);
125 test_floatclass(reporter, max, kFinite);
126 test_floatclass(reporter, -max, kFinite);
127 test_floatclass(reporter, inf, kInfinite);
128 test_floatclass(reporter, -inf, kInfinite);
129 test_floatclass(reporter, nan, kNaN);
130 test_floatclass(reporter, -nan, kNaN);
reed@google.comd230e3e2011-12-05 20:49:37 +0000131
132 const Rec data[] = {
bungeman@google.comf8aa18c2012-03-19 21:04:52 +0000133 { 0, true },
134 { 1, true },
135 { -1, true },
136 { max * 0.75f, true },
137 { max, true },
138 { -max * 0.75f, true },
139 { -max, true },
140 { inf, false },
141 { -inf, false },
142 { nan, false },
reed@google.comd230e3e2011-12-05 20:49:37 +0000143 };
144
145 const IsFiniteProc1 gProc1[] = {
146 isFinite_int,
147 isFinite_float,
148 isFinite_mulzero
149 };
150 const IsFiniteProc2 gProc2[] = {
151 isFinite2_and,
152 isFinite2_mulzeroadd
153 };
154
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000155 size_t i, n = SK_ARRAY_COUNT(data);
reed@google.comd230e3e2011-12-05 20:49:37 +0000156
157 for (i = 0; i < n; ++i) {
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000158 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000159 const Rec& rec = data[i];
160 bool finite = gProc1[k](rec.fValue);
161 REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
162 }
163 }
164
165 for (i = 0; i < n; ++i) {
166 const Rec& rec0 = data[i];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000167 for (size_t j = 0; j < n; ++j) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000168 const Rec& rec1 = data[j];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000169 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000170 IsFiniteProc1 proc1 = gProc1[k];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000172 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000173 bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
174 bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
175 REPORTER_ASSERT(reporter, finite2 == finite);
176 }
177 }
178 }
179 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000180
reed@google.com30d90eb2012-05-15 14:17:36 +0000181 test_isRectFinite(reporter);
reed@google.comd230e3e2011-12-05 20:49:37 +0000182}
183
robertphillips@google.com706f6212012-05-14 17:51:23 +0000184#if defined _WIN32
185#pragma warning ( pop )
186#endif
187
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000188DEF_TEST(Scalar, reporter) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000189 test_isfinite(reporter);
190}