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