blob: d2c05aba6fb1c9e68d78c7fcb00e937e232b5efb [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) {
reed@google.com61873a52011-12-05 21:47:25 +000023 return 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
reed@google.comd230e3e2011-12-05 20:49:37 +000061static 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;
reed@google.com5ae777d2011-12-06 20:18:05 +000070 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);
reed@google.comd230e3e2011-12-05 20:49:37 +000079
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
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000103 size_t i, n = SK_ARRAY_COUNT(data);
reed@google.comd230e3e2011-12-05 20:49:37 +0000104
105 for (i = 0; i < n; ++i) {
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000106 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000107 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];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000115 for (size_t j = 0; j < n; ++j) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000116 const Rec& rec1 = data[j];
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000117 for (size_t k = 0; k < SK_ARRAY_COUNT(gProc1); ++k) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000118 IsFiniteProc1 proc1 = gProc1[k];
119
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000120 for (size_t m = 0; m < SK_ARRAY_COUNT(gProc2); ++m) {
reed@google.comd230e3e2011-12-05 20:49:37 +0000121 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
131static void TestScalar(skiatest::Reporter* reporter) {
132 test_isfinite(reporter);
133}
134
135#include "TestClassDef.h"
136DEFINE_TESTCLASS("Scalar", TestScalarClass, TestScalar)
137