blob: eb52b8adf3176f1e2e16f149f1a55c99e365c6df [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
8#include "Test.h"
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +00009#include "TestClassDef.h"
reed@google.comd230e3e2011-12-05 20:49:37 +000010#include "SkFloatingPoint.h"
11#include "SkMath.h"
12#include "SkPoint.h"
13#include "SkRandom.h"
reed@google.com30d90eb2012-05-15 14:17:36 +000014#include "SkRect.h"
reed@google.comd230e3e2011-12-05 20:49:37 +000015
reed@google.com30d90eb2012-05-15 14:17:36 +000016struct PointSet {
17 const SkPoint* fPts;
18 size_t fCount;
19 bool fIsFinite;
20};
21
22static void test_isRectFinite(skiatest::Reporter* reporter) {
23 static const SkPoint gF0[] = {
24 { 0, 0 }, { 1, 1 }
25 };
26 static const SkPoint gF1[] = {
27 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }
28 };
29
30 static const SkPoint gI0[] = {
31 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarNaN, 3 }, { 2, 3 },
32 };
33 static const SkPoint gI1[] = {
34 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarNaN }, { 2, 3 },
35 };
36 static const SkPoint gI2[] = {
37 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarInfinity, 3 }, { 2, 3 },
38 };
39 static const SkPoint gI3[] = {
40 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarInfinity }, { 2, 3 },
41 };
42
43 static const struct {
44 const SkPoint* fPts;
45 size_t fCount;
46 bool fIsFinite;
47 } gSets[] = {
48 { gF0, SK_ARRAY_COUNT(gF0), true },
49 { gF1, SK_ARRAY_COUNT(gF1), true },
50
51 { gI0, SK_ARRAY_COUNT(gI0), false },
52 { gI1, SK_ARRAY_COUNT(gI1), false },
53 { gI2, SK_ARRAY_COUNT(gI2), false },
54 { gI3, SK_ARRAY_COUNT(gI3), false },
55 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000056
reed@google.com30d90eb2012-05-15 14:17:36 +000057 for (size_t i = 0; i < SK_ARRAY_COUNT(gSets); ++i) {
58 SkRect r;
59 r.set(gSets[i].fPts, gSets[i].fCount);
60 bool rectIsFinite = !r.isEmpty();
61 REPORTER_ASSERT(reporter, gSets[i].fIsFinite == rectIsFinite);
62 }
63}
64
reed@google.comd230e3e2011-12-05 20:49:37 +000065static bool isFinite_int(float x) {
66 uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
67 int exponent = bits << 1 >> 24;
68 return exponent != 0xFF;
69}
70
71static bool isFinite_float(float x) {
robertphillips@google.com6853e802012-04-16 15:50:18 +000072 return SkToBool(sk_float_isfinite(x));
reed@google.comd230e3e2011-12-05 20:49:37 +000073}
74
75static bool isFinite_mulzero(float x) {
76 float y = x * 0;
77 return y == y;
78}
79
80// return true if the float is finite
81typedef bool (*IsFiniteProc1)(float);
82
83static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
84 return proc(x) && proc(y);
85}
86
87static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
88 return proc(x * 0 + y * 0);
89}
90
91// return true if both floats are finite
92typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
93
reed@google.com5ae777d2011-12-06 20:18:05 +000094enum FloatClass {
95 kFinite,
96 kInfinite,
97 kNaN
98};
99
100static void test_floatclass(skiatest::Reporter* reporter, float value, FloatClass fc) {
101 // our sk_float_is... function may return int instead of bool,
102 // hence the double ! to turn it into a bool
103 REPORTER_ASSERT(reporter, !!sk_float_isfinite(value) == (fc == kFinite));
104 REPORTER_ASSERT(reporter, !!sk_float_isinf(value) == (fc == kInfinite));
105 REPORTER_ASSERT(reporter, !!sk_float_isnan(value) == (fc == kNaN));
106}
107
robertphillips@google.com706f6212012-05-14 17:51:23 +0000108#if defined _WIN32
109#pragma warning ( push )
110// we are intentionally causing an overflow here
111// (warning C4756: overflow in constant arithmetic)
112#pragma warning ( disable : 4756 )
113#endif
114
reed@google.comd230e3e2011-12-05 20:49:37 +0000115static void test_isfinite(skiatest::Reporter* reporter) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000116 struct Rec {
117 float fValue;
118 bool fIsFinite;
119 };
rmistry@google.comd6176b02012-08-23 18:14:13 +0000120
reed@google.comd230e3e2011-12-05 20:49:37 +0000121 float max = 3.402823466e+38f;
122 float inf = max * max;
reed@google.com5ae777d2011-12-06 20:18:05 +0000123 float nan = inf * 0;
124
125 test_floatclass(reporter, 0, kFinite);
126 test_floatclass(reporter, max, kFinite);
127 test_floatclass(reporter, -max, kFinite);
128 test_floatclass(reporter, inf, kInfinite);
129 test_floatclass(reporter, -inf, kInfinite);
130 test_floatclass(reporter, nan, kNaN);
131 test_floatclass(reporter, -nan, kNaN);
reed@google.comd230e3e2011-12-05 20:49:37 +0000132
133 const Rec data[] = {
bungeman@google.comf8aa18c2012-03-19 21:04:52 +0000134 { 0, true },
135 { 1, true },
136 { -1, true },
137 { max * 0.75f, true },
138 { max, true },
139 { -max * 0.75f, true },
140 { -max, true },
141 { inf, false },
142 { -inf, false },
143 { nan, false },
reed@google.comd230e3e2011-12-05 20:49:37 +0000144 };
145
146 const IsFiniteProc1 gProc1[] = {
147 isFinite_int,
148 isFinite_float,
149 isFinite_mulzero
150 };
151 const IsFiniteProc2 gProc2[] = {
152 isFinite2_and,
153 isFinite2_mulzeroadd
154 };
155
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000156 size_t i, n = SK_ARRAY_COUNT(data);
reed@google.comd230e3e2011-12-05 20:49:37 +0000157
158 for (i = 0; i < n; ++i) {
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000159 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000160 const Rec& rec = data[i];
161 bool finite = gProc1[k](rec.fValue);
162 REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
163 }
164 }
165
166 for (i = 0; i < n; ++i) {
167 const Rec& rec0 = data[i];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000168 for (size_t j = 0; j < n; ++j) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000169 const Rec& rec1 = data[j];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000170 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000171 IsFiniteProc1 proc1 = gProc1[k];
rmistry@google.comd6176b02012-08-23 18:14:13 +0000172
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000173 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000174 bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
175 bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
176 REPORTER_ASSERT(reporter, finite2 == finite);
177 }
178 }
179 }
180 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181
reed@google.com30d90eb2012-05-15 14:17:36 +0000182 test_isRectFinite(reporter);
reed@google.comd230e3e2011-12-05 20:49:37 +0000183}
184
robertphillips@google.com706f6212012-05-14 17:51:23 +0000185#if defined _WIN32
186#pragma warning ( pop )
187#endif
188
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000189DEF_TEST(Scalar, reporter) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000190 test_isfinite(reporter);
191}