• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 #include "src/pathops/SkPathOpsTypes.h"
8 
9 #include "include/private/base/SkFloatingPoint.h"
10 #include "include/private/base/SkTemplates.h"
11 #include "include/private/base/SkFloatBits.h"
12 #include "include/private/base/SkMath.h"
13 
14 #include <algorithm>
15 #include <cstdint>
16 
arguments_denormalized(float a,float b,int epsilon)17 static bool arguments_denormalized(float a, float b, int epsilon) {
18     float denormalizedCheck = FLT_EPSILON * epsilon / 2;
19     return fabsf(a) <= denormalizedCheck && fabsf(b) <= denormalizedCheck;
20 }
21 
22 // from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
23 // FIXME: move to SkFloatBits.h
equal_ulps(float a,float b,int epsilon,int depsilon)24 static bool equal_ulps(float a, float b, int epsilon, int depsilon) {
25     if (arguments_denormalized(a, b, depsilon)) {
26         return true;
27     }
28     int aBits = SkFloatAs2sCompliment(a);
29     int bBits = SkFloatAs2sCompliment(b);
30     // Find the difference in ULPs.
31     return aBits < bBits + epsilon && bBits < aBits + epsilon;
32 }
33 
equal_ulps_no_normal_check(float a,float b,int epsilon,int depsilon)34 static bool equal_ulps_no_normal_check(float a, float b, int epsilon, int depsilon) {
35     int aBits = SkFloatAs2sCompliment(a);
36     int bBits = SkFloatAs2sCompliment(b);
37     // Find the difference in ULPs.
38     return aBits < bBits + epsilon && bBits < aBits + epsilon;
39 }
40 
equal_ulps_pin(float a,float b,int epsilon,int depsilon)41 static bool equal_ulps_pin(float a, float b, int epsilon, int depsilon) {
42     if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
43         return false;
44     }
45     if (arguments_denormalized(a, b, depsilon)) {
46         return true;
47     }
48     int aBits = SkFloatAs2sCompliment(a);
49     int bBits = SkFloatAs2sCompliment(b);
50     // Find the difference in ULPs.
51     return aBits < bBits + epsilon && bBits < aBits + epsilon;
52 }
53 
d_equal_ulps(float a,float b,int epsilon)54 static bool d_equal_ulps(float a, float b, int epsilon) {
55     int aBits = SkFloatAs2sCompliment(a);
56     int bBits = SkFloatAs2sCompliment(b);
57     // Find the difference in ULPs.
58     return aBits < bBits + epsilon && bBits < aBits + epsilon;
59 }
60 
not_equal_ulps(float a,float b,int epsilon)61 static bool not_equal_ulps(float a, float b, int epsilon) {
62     if (arguments_denormalized(a, b, epsilon)) {
63         return false;
64     }
65     int aBits = SkFloatAs2sCompliment(a);
66     int bBits = SkFloatAs2sCompliment(b);
67     // Find the difference in ULPs.
68     return aBits >= bBits + epsilon || bBits >= aBits + epsilon;
69 }
70 
not_equal_ulps_pin(float a,float b,int epsilon)71 static bool not_equal_ulps_pin(float a, float b, int epsilon) {
72     if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
73         return false;
74     }
75     if (arguments_denormalized(a, b, epsilon)) {
76         return false;
77     }
78     int aBits = SkFloatAs2sCompliment(a);
79     int bBits = SkFloatAs2sCompliment(b);
80     // Find the difference in ULPs.
81     return aBits >= bBits + epsilon || bBits >= aBits + epsilon;
82 }
83 
d_not_equal_ulps(float a,float b,int epsilon)84 static bool d_not_equal_ulps(float a, float b, int epsilon) {
85     int aBits = SkFloatAs2sCompliment(a);
86     int bBits = SkFloatAs2sCompliment(b);
87     // Find the difference in ULPs.
88     return aBits >= bBits + epsilon || bBits >= aBits + epsilon;
89 }
90 
less_ulps(float a,float b,int epsilon)91 static bool less_ulps(float a, float b, int epsilon) {
92     if (arguments_denormalized(a, b, epsilon)) {
93         return a <= b - FLT_EPSILON * epsilon;
94     }
95     int aBits = SkFloatAs2sCompliment(a);
96     int bBits = SkFloatAs2sCompliment(b);
97     // Find the difference in ULPs.
98     return aBits <= bBits - epsilon;
99 }
100 
less_or_equal_ulps(float a,float b,int epsilon)101 static bool less_or_equal_ulps(float a, float b, int epsilon) {
102     if (arguments_denormalized(a, b, epsilon)) {
103         return a < b + FLT_EPSILON * epsilon;
104     }
105     int aBits = SkFloatAs2sCompliment(a);
106     int bBits = SkFloatAs2sCompliment(b);
107     // Find the difference in ULPs.
108     return aBits < bBits + epsilon;
109 }
110 
111 // equality using the same error term as between
AlmostBequalUlps(float a,float b)112 bool AlmostBequalUlps(float a, float b) {
113     const int UlpsEpsilon = 2;
114     return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon);
115 }
116 
AlmostPequalUlps(float a,float b)117 bool AlmostPequalUlps(float a, float b) {
118     const int UlpsEpsilon = 8;
119     return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon);
120 }
121 
AlmostDequalUlps(float a,float b)122 bool AlmostDequalUlps(float a, float b) {
123     const int UlpsEpsilon = 16;
124     return d_equal_ulps(a, b, UlpsEpsilon);
125 }
126 
AlmostDequalUlps(double a,double b)127 bool AlmostDequalUlps(double a, double b) {
128     if (fabs(a) < SK_ScalarMax && fabs(b) < SK_ScalarMax) {
129         return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
130     }
131     // We allow divide-by-zero here. It only happens if one of a,b is zero, and the other is NaN.
132     // (Otherwise, we'd hit the condition above). Thus, if std::max returns 0, we compute NaN / 0,
133     // which will produce NaN. The comparison will return false, which is the correct answer.
134     return sk_ieee_double_divide(fabs(a - b), std::max(fabs(a), fabs(b))) < FLT_EPSILON * 16;
135 }
136 
AlmostEqualUlps(float a,float b)137 bool AlmostEqualUlps(float a, float b) {
138     const int UlpsEpsilon = 16;
139     return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon);
140 }
141 
AlmostEqualUlpsNoNormalCheck(float a,float b)142 bool AlmostEqualUlpsNoNormalCheck(float a, float b) {
143     const int UlpsEpsilon = 16;
144     return equal_ulps_no_normal_check(a, b, UlpsEpsilon, UlpsEpsilon);
145 }
146 
AlmostEqualUlps_Pin(float a,float b)147 bool AlmostEqualUlps_Pin(float a, float b) {
148     const int UlpsEpsilon = 16;
149     return equal_ulps_pin(a, b, UlpsEpsilon, UlpsEpsilon);
150 }
151 
NotAlmostEqualUlps(float a,float b)152 bool NotAlmostEqualUlps(float a, float b) {
153     const int UlpsEpsilon = 16;
154     return not_equal_ulps(a, b, UlpsEpsilon);
155 }
156 
NotAlmostEqualUlps_Pin(float a,float b)157 bool NotAlmostEqualUlps_Pin(float a, float b) {
158     const int UlpsEpsilon = 16;
159     return not_equal_ulps_pin(a, b, UlpsEpsilon);
160 }
161 
NotAlmostDequalUlps(float a,float b)162 bool NotAlmostDequalUlps(float a, float b) {
163     const int UlpsEpsilon = 16;
164     return d_not_equal_ulps(a, b, UlpsEpsilon);
165 }
166 
RoughlyEqualUlps(float a,float b)167 bool RoughlyEqualUlps(float a, float b) {
168     const int UlpsEpsilon = 256;
169     const int DUlpsEpsilon = 1024;
170     return equal_ulps(a, b, UlpsEpsilon, DUlpsEpsilon);
171 }
172 
AlmostBetweenUlps(float a,float b,float c)173 bool AlmostBetweenUlps(float a, float b, float c) {
174     const int UlpsEpsilon = 2;
175     return a <= c ? less_or_equal_ulps(a, b, UlpsEpsilon) && less_or_equal_ulps(b, c, UlpsEpsilon)
176         : less_or_equal_ulps(b, a, UlpsEpsilon) && less_or_equal_ulps(c, b, UlpsEpsilon);
177 }
178 
AlmostLessUlps(float a,float b)179 bool AlmostLessUlps(float a, float b) {
180     const int UlpsEpsilon = 16;
181     return less_ulps(a, b, UlpsEpsilon);
182 }
183 
AlmostLessOrEqualUlps(float a,float b)184 bool AlmostLessOrEqualUlps(float a, float b) {
185     const int UlpsEpsilon = 16;
186     return less_or_equal_ulps(a, b, UlpsEpsilon);
187 }
188 
UlpsDistance(float a,float b)189 int UlpsDistance(float a, float b) {
190     SkFloatIntUnion floatIntA, floatIntB;
191     floatIntA.fFloat = a;
192     floatIntB.fFloat = b;
193     // Different signs means they do not match.
194     if ((floatIntA.fSignBitInt < 0) != (floatIntB.fSignBitInt < 0)) {
195         // Check for equality to make sure +0 == -0
196         return a == b ? 0 : SK_MaxS32;
197     }
198     // Find the difference in ULPs.
199     return SkTAbs(floatIntA.fSignBitInt - floatIntB.fSignBitInt);
200 }
201 
SkOpGlobalState(SkOpContourHead * head,SkArenaAlloc * allocator SkDEBUGPARAMS (bool debugSkipAssert)SkDEBUGPARAMS (const char * testName))202 SkOpGlobalState::SkOpGlobalState(SkOpContourHead* head,
203                                  SkArenaAlloc* allocator
204                                  SkDEBUGPARAMS(bool debugSkipAssert)
205                                  SkDEBUGPARAMS(const char* testName))
206     : fAllocator(allocator)
207     , fCoincidence(nullptr)
208     , fContourHead(head)
209     , fNested(0)
210     , fWindingFailed(false)
211     , fPhase(SkOpPhase::kIntersecting)
212     SkDEBUGPARAMS(fDebugTestName(testName))
213     SkDEBUGPARAMS(fAngleID(0))
214     SkDEBUGPARAMS(fCoinID(0))
215     SkDEBUGPARAMS(fContourID(0))
216     SkDEBUGPARAMS(fPtTID(0))
217     SkDEBUGPARAMS(fSegmentID(0))
218     SkDEBUGPARAMS(fSpanID(0))
219     SkDEBUGPARAMS(fDebugSkipAssert(debugSkipAssert)) {
220 #if DEBUG_T_SECT_LOOP_COUNT
221     debugResetLoopCounts();
222 #endif
223 #if DEBUG_COIN
224     fPreviousFuncName = nullptr;
225 #endif
226 }
227