blob: ef7db324c8b2cbf47724bff4cd5b07da6472f312 [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"
9#include "SkFloatingPoint.h"
10#include "SkMath.h"
11#include "SkPoint.h"
12#include "SkRandom.h"
13
14#ifdef SK_CAN_USE_FLOAT
15
16static 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
22static bool isFinite_float(float x) {
robertphillips@google.com6853e802012-04-16 15:50:18 +000023 return SkToBool(sk_float_isfinite(x));
reed@google.comd230e3e2011-12-05 20:49:37 +000024}
25
26static bool isFinite_mulzero(float x) {
27 float y = x * 0;
28 return y == y;
29}
30
31// return true if the float is finite
32typedef bool (*IsFiniteProc1)(float);
33
34static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
35 return proc(x) && proc(y);
36}
37
38static 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
43typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
44
45#endif
46
reed@google.com5ae777d2011-12-06 20:18:05 +000047enum FloatClass {
48 kFinite,
49 kInfinite,
50 kNaN
51};
52
53static 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
robertphillips@google.com706f6212012-05-14 17:51:23 +000061#if defined _WIN32
62#pragma warning ( push )
63// we are intentionally causing an overflow here
64// (warning C4756: overflow in constant arithmetic)
65#pragma warning ( disable : 4756 )
66#endif
67
reed@google.comd230e3e2011-12-05 20:49:37 +000068static void test_isfinite(skiatest::Reporter* reporter) {
69#ifdef SK_CAN_USE_FLOAT
70 struct Rec {
71 float fValue;
72 bool fIsFinite;
73 };
74
75 float max = 3.402823466e+38f;
76 float inf = max * max;
reed@google.com5ae777d2011-12-06 20:18:05 +000077 float nan = inf * 0;
78
79 test_floatclass(reporter, 0, kFinite);
80 test_floatclass(reporter, max, kFinite);
81 test_floatclass(reporter, -max, kFinite);
82 test_floatclass(reporter, inf, kInfinite);
83 test_floatclass(reporter, -inf, kInfinite);
84 test_floatclass(reporter, nan, kNaN);
85 test_floatclass(reporter, -nan, kNaN);
reed@google.comd230e3e2011-12-05 20:49:37 +000086
87 const Rec data[] = {
bungeman@google.comf8aa18c2012-03-19 21:04:52 +000088 { 0, true },
89 { 1, true },
90 { -1, true },
91 { max * 0.75f, true },
92 { max, true },
93 { -max * 0.75f, true },
94 { -max, true },
95 { inf, false },
96 { -inf, false },
97 { nan, false },
reed@google.comd230e3e2011-12-05 20:49:37 +000098 };
99
100 const IsFiniteProc1 gProc1[] = {
101 isFinite_int,
102 isFinite_float,
103 isFinite_mulzero
104 };
105 const IsFiniteProc2 gProc2[] = {
106 isFinite2_and,
107 isFinite2_mulzeroadd
108 };
109
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000110 size_t i, n = SK_ARRAY_COUNT(data);
reed@google.comd230e3e2011-12-05 20:49:37 +0000111
112 for (i = 0; i < n; ++i) {
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000113 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000114 const Rec& rec = data[i];
115 bool finite = gProc1[k](rec.fValue);
116 REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
117 }
118 }
119
120 for (i = 0; i < n; ++i) {
121 const Rec& rec0 = data[i];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000122 for (size_t j = 0; j < n; ++j) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000123 const Rec& rec1 = data[j];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000124 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000125 IsFiniteProc1 proc1 = gProc1[k];
126
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000127 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000128 bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
129 bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
130 REPORTER_ASSERT(reporter, finite2 == finite);
131 }
132 }
133 }
134 }
135#endif
136}
137
robertphillips@google.com706f6212012-05-14 17:51:23 +0000138#if defined _WIN32
139#pragma warning ( pop )
140#endif
141
reed@google.comd230e3e2011-12-05 20:49:37 +0000142static void TestScalar(skiatest::Reporter* reporter) {
143 test_isfinite(reporter);
144}
145
146#include "TestClassDef.h"
147DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
148