Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ScalarTest.cpp
Go to the documentation of this file.
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
15#include "tests/Test.h"
16
17#include <array>
18#include <cmath>
19#include <cstddef>
20#include <cstdint>
21
23 SkScalar x = 0.49999997f;
24 int ix = SkScalarRoundToInt(x);
25 int badIx = (int) floorf(x + 0.5f);
26 // We should get 0, since x < 0.5, but we wouldn't if SkScalarRoundToInt uses the commonly
27 // recommended approach shown in 'badIx' due to float addition rounding up the low
28 // bit after adding 0.5.
29 REPORTER_ASSERT(reporter, 0 == ix);
30 REPORTER_ASSERT(reporter, 1 == badIx);
31
32 // Additionally, when the float value is between (2^23,2^24], it's precision is equal to
33 // 1 integral value. Adding 0.5f rounds up automatically *before* the floor, so naive
34 // rounding is also incorrect. Float values <= 2^23 and > 2^24 don't have this problem
35 // because either the sum can be represented sufficiently for floor() to do the right thing,
36 // or the sum will always round down to the integer multiple.
37 x = 8388609.f;
39 badIx = (int) floorf(x + 0.5f);
40 REPORTER_ASSERT(reporter, 8388609 == ix);
41 REPORTER_ASSERT(reporter, 8388610 == badIx);
42}
43
44struct PointSet {
45 const SkPoint* fPts;
46 size_t fCount;
48};
49
51 static const SkPoint gF0[] = {
52 { 0, 0 }, { 1, 1 }
53 };
54 static const SkPoint gF1[] = {
55 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }
56 };
57
58 static const SkPoint gI0[] = {
59 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarNaN, 3 }, { 2, 3 },
60 };
61 static const SkPoint gI1[] = {
62 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarNaN }, { 2, 3 },
63 };
64 static const SkPoint gI2[] = {
65 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarInfinity, 3 }, { 2, 3 },
66 };
67 static const SkPoint gI3[] = {
68 { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarInfinity }, { 2, 3 },
69 };
70
71 static const struct {
72 const SkPoint* fPts;
73 int fCount;
74 bool fIsFinite;
75 } gSets[] = {
76 { gF0, std::size(gF0), true },
77 { gF1, std::size(gF1), true },
78
79 { gI0, std::size(gI0), false },
80 { gI1, std::size(gI1), false },
81 { gI2, std::size(gI2), false },
82 { gI3, std::size(gI3), false },
83 };
84
85 for (size_t i = 0; i < std::size(gSets); ++i) {
86 SkRect r;
87 r.setBounds(gSets[i].fPts, gSets[i].fCount);
88 bool rectIsFinite = !r.isEmpty();
89 REPORTER_ASSERT(reporter, gSets[i].fIsFinite == rectIsFinite);
90 }
91}
92
93static bool isFinite_int(float x) {
94 uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
95 int exponent = bits << 1 >> 24;
96 return exponent != 0xFF;
97}
98
99static bool isFinite_float(float x) {
100 return SkToBool(SkIsFinite(x));
101}
102
103static bool isFinite_mulzero(float x) {
104 float y = x * 0;
105 return y == y;
106}
107
108// return true if the float is finite
109typedef bool (*IsFiniteProc1)(float);
110
111static bool isFinite2_and(float x, float y, IsFiniteProc1 proc) {
112 return proc(x) && proc(y);
113}
114
115static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc) {
116 return proc(x * 0 + y * 0);
117}
118
119// return true if both floats are finite
120typedef bool (*IsFiniteProc2)(float, float, IsFiniteProc1);
121
127
129 // our sk_float_is... function may return int instead of bool,
130 // hence the double ! to turn it into a bool
132 REPORTER_ASSERT(reporter, !!std::isinf(value) == (fc == kInfinite));
133 REPORTER_ASSERT(reporter, !!SkIsNaN(value) == (fc == kNaN));
134}
135
136#if defined _WIN32
137#pragma warning(push)
138// we are intentionally causing an overflow here
139// (warning C4756: overflow in constant arithmetic)
140#pragma warning(disable : 4756)
141#endif
142
144 struct Rec {
145 float fValue;
146 bool fIsFinite;
147 };
148
149 float max = 3.402823466e+38f;
150 float inf = max * max;
151 float nan = inf * 0;
152
160
161 const Rec data[] = {
162 { 0, true },
163 { 1, true },
164 { -1, true },
165 { max * 0.75f, true },
166 { max, true },
167 { -max * 0.75f, true },
168 { -max, true },
169 { inf, false },
170 { -inf, false },
171 { nan, false },
172 };
173
174 const IsFiniteProc1 gProc1[] = {
178 };
179 const IsFiniteProc2 gProc2[] = {
182 };
183
184 size_t i, n = std::size(data);
185
186 for (i = 0; i < n; ++i) {
187 for (size_t k = 0; k < std::size(gProc1); ++k) {
188 const Rec& rec = data[i];
189 bool finite = gProc1[k](rec.fValue);
190 REPORTER_ASSERT(reporter, rec.fIsFinite == finite);
191 }
192 }
193
194 for (i = 0; i < n; ++i) {
195 const Rec& rec0 = data[i];
196 for (size_t j = 0; j < n; ++j) {
197 const Rec& rec1 = data[j];
198 for (size_t k = 0; k < std::size(gProc1); ++k) {
199 IsFiniteProc1 proc1 = gProc1[k];
200
201 for (size_t m = 0; m < std::size(gProc2); ++m) {
202 bool finite = gProc2[m](rec0.fValue, rec1.fValue, proc1);
203 bool finite2 = rec0.fIsFinite && rec1.fIsFinite;
204 REPORTER_ASSERT(reporter, finite2 == finite);
205 }
206 }
207 }
208 }
209
211}
212
213#if defined _WIN32
214#pragma warning ( pop )
215#endif
216
SkPoint fPts[2]
reporter
static bool isFinite_mulzero(float x)
static bool isFinite2_and(float x, float y, IsFiniteProc1 proc)
bool(* IsFiniteProc2)(float, float, IsFiniteProc1)
static void test_isRectFinite(skiatest::Reporter *reporter)
static bool isFinite_int(float x)
static void test_floatclass(skiatest::Reporter *reporter, float value, FloatClass fc)
static void test_roundtoint(skiatest::Reporter *reporter)
FloatClass
@ kFinite
@ kInfinite
@ kNaN
static void test_isfinite(skiatest::Reporter *reporter)
static bool isFinite2_mulzeroadd(float x, float y, IsFiniteProc1 proc)
bool(* IsFiniteProc1)(float)
static bool isFinite_float(float x)
static uint32_t SkFloat2Bits(float value)
Definition SkFloatBits.h:41
static bool SkIsFinite(T x, Pack... values)
static bool SkIsNaN(T x)
#define SK_ScalarNaN
Definition SkScalar.h:28
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
#define SK_ScalarInfinity
Definition SkScalar.h:26
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
Type::kYUV Type::kRGBA() int(0.7 *637)
float SkScalar
Definition extension.cpp:12
uint8_t value
static float max(float r, float g, float b)
Definition hsl.cpp:49
double y
double x
const SkPoint * fPts
bool fIsFinite
size_t fCount
void setBounds(const SkPoint pts[], int count)
Definition SkRect.h:881
bool isEmpty() const
Definition SkRect.h:693