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 "SkArenaAlloc.h" 8 #include "SkFloatBits.h" 9 #include "SkOpCoincidence.h" 10 #include "SkPathOpsTypes.h" 11 12 static bool arguments_denormalized(float a, float b, int epsilon) { 13 float denormalizedCheck = FLT_EPSILON * epsilon / 2; 14 return fabsf(a) <= denormalizedCheck && fabsf(b) <= denormalizedCheck; 15 } 16 17 // from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ 18 // FIXME: move to SkFloatBits.h 19 static bool equal_ulps(float a, float b, int epsilon, int depsilon) { 20 if (arguments_denormalized(a, b, depsilon)) { 21 return true; 22 } 23 int aBits = SkFloatAs2sCompliment(a); 24 int bBits = SkFloatAs2sCompliment(b); 25 // Find the difference in ULPs. 26 return aBits < bBits + epsilon && bBits < aBits + epsilon; 27 } 28 29 static bool equal_ulps_no_normal_check(float a, float b, int epsilon, int depsilon) { 30 int aBits = SkFloatAs2sCompliment(a); 31 int bBits = SkFloatAs2sCompliment(b); 32 // Find the difference in ULPs. 33 return aBits < bBits + epsilon && bBits < aBits + epsilon; 34 } 35 36 static bool equal_ulps_pin(float a, float b, int epsilon, int depsilon) { 37 if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { 38 return false; 39 } 40 if (arguments_denormalized(a, b, depsilon)) { 41 return true; 42 } 43 int aBits = SkFloatAs2sCompliment(a); 44 int bBits = SkFloatAs2sCompliment(b); 45 // Find the difference in ULPs. 46 return aBits < bBits + epsilon && bBits < aBits + epsilon; 47 } 48 49 static bool d_equal_ulps(float a, float b, int epsilon) { 50 int aBits = SkFloatAs2sCompliment(a); 51 int bBits = SkFloatAs2sCompliment(b); 52 // Find the difference in ULPs. 53 return aBits < bBits + epsilon && bBits < aBits + epsilon; 54 } 55 56 static bool not_equal_ulps(float a, float b, int epsilon) { 57 if (arguments_denormalized(a, b, epsilon)) { 58 return false; 59 } 60 int aBits = SkFloatAs2sCompliment(a); 61 int bBits = SkFloatAs2sCompliment(b); 62 // Find the difference in ULPs. 63 return aBits >= bBits + epsilon || bBits >= aBits + epsilon; 64 } 65 66 static bool not_equal_ulps_pin(float a, float b, int epsilon) { 67 if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { 68 return false; 69 } 70 if (arguments_denormalized(a, b, epsilon)) { 71 return false; 72 } 73 int aBits = SkFloatAs2sCompliment(a); 74 int bBits = SkFloatAs2sCompliment(b); 75 // Find the difference in ULPs. 76 return aBits >= bBits + epsilon || bBits >= aBits + epsilon; 77 } 78 79 static bool d_not_equal_ulps(float a, float b, int epsilon) { 80 int aBits = SkFloatAs2sCompliment(a); 81 int bBits = SkFloatAs2sCompliment(b); 82 // Find the difference in ULPs. 83 return aBits >= bBits + epsilon || bBits >= aBits + epsilon; 84 } 85 86 static bool less_ulps(float a, float b, int epsilon) { 87 if (arguments_denormalized(a, b, epsilon)) { 88 return a <= b - FLT_EPSILON * epsilon; 89 } 90 int aBits = SkFloatAs2sCompliment(a); 91 int bBits = SkFloatAs2sCompliment(b); 92 // Find the difference in ULPs. 93 return aBits <= bBits - epsilon; 94 } 95 96 static bool less_or_equal_ulps(float a, float b, int epsilon) { 97 if (arguments_denormalized(a, b, epsilon)) { 98 return a < b + FLT_EPSILON * epsilon; 99 } 100 int aBits = SkFloatAs2sCompliment(a); 101 int bBits = SkFloatAs2sCompliment(b); 102 // Find the difference in ULPs. 103 return aBits < bBits + epsilon; 104 } 105 106 // equality using the same error term as between 107 bool AlmostBequalUlps(float a, float b) { 108 const int UlpsEpsilon = 2; 109 return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon); 110 } 111 112 bool AlmostPequalUlps(float a, float b) { 113 const int UlpsEpsilon = 8; 114 return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon); 115 } 116 117 bool AlmostDequalUlps(float a, float b) { 118 const int UlpsEpsilon = 16; 119 return d_equal_ulps(a, b, UlpsEpsilon); 120 } 121 122 bool AlmostDequalUlps(double a, double b) { 123 if (fabs(a) < SK_ScalarMax && fabs(b) < SK_ScalarMax) { 124 return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 125 } 126 return fabs(a - b) / SkTMax(fabs(a), fabs(b)) < FLT_EPSILON * 16; 127 } 128 129 bool AlmostEqualUlps(float a, float b) { 130 const int UlpsEpsilon = 16; 131 return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon); 132 } 133 134 bool AlmostEqualUlpsNoNormalCheck(float a, float b) { 135 const int UlpsEpsilon = 16; 136 return equal_ulps_no_normal_check(a, b, UlpsEpsilon, UlpsEpsilon); 137 } 138 139 bool AlmostEqualUlps_Pin(float a, float b) { 140 const int UlpsEpsilon = 16; 141 return equal_ulps_pin(a, b, UlpsEpsilon, UlpsEpsilon); 142 } 143 144 bool NotAlmostEqualUlps(float a, float b) { 145 const int UlpsEpsilon = 16; 146 return not_equal_ulps(a, b, UlpsEpsilon); 147 } 148 149 bool NotAlmostEqualUlps_Pin(float a, float b) { 150 const int UlpsEpsilon = 16; 151 return not_equal_ulps_pin(a, b, UlpsEpsilon); 152 } 153 154 bool NotAlmostDequalUlps(float a, float b) { 155 const int UlpsEpsilon = 16; 156 return d_not_equal_ulps(a, b, UlpsEpsilon); 157 } 158 159 bool RoughlyEqualUlps(float a, float b) { 160 const int UlpsEpsilon = 256; 161 const int DUlpsEpsilon = 1024; 162 return equal_ulps(a, b, UlpsEpsilon, DUlpsEpsilon); 163 } 164 165 bool AlmostBetweenUlps(float a, float b, float c) { 166 const int UlpsEpsilon = 2; 167 return a <= c ? less_or_equal_ulps(a, b, UlpsEpsilon) && less_or_equal_ulps(b, c, UlpsEpsilon) 168 : less_or_equal_ulps(b, a, UlpsEpsilon) && less_or_equal_ulps(c, b, UlpsEpsilon); 169 } 170 171 bool AlmostLessUlps(float a, float b) { 172 const int UlpsEpsilon = 16; 173 return less_ulps(a, b, UlpsEpsilon); 174 } 175 176 bool AlmostLessOrEqualUlps(float a, float b) { 177 const int UlpsEpsilon = 16; 178 return less_or_equal_ulps(a, b, UlpsEpsilon); 179 } 180 181 int UlpsDistance(float a, float b) { 182 SkFloatIntUnion floatIntA, floatIntB; 183 floatIntA.fFloat = a; 184 floatIntB.fFloat = b; 185 // Different signs means they do not match. 186 if ((floatIntA.fSignBitInt < 0) != (floatIntB.fSignBitInt < 0)) { 187 // Check for equality to make sure +0 == -0 188 return a == b ? 0 : SK_MaxS32; 189 } 190 // Find the difference in ULPs. 191 return SkTAbs(floatIntA.fSignBitInt - floatIntB.fSignBitInt); 192 } 193 194 // cube root approximation using bit hack for 64-bit float 195 // adapted from Kahan's cbrt 196 static double cbrt_5d(double d) { 197 const unsigned int B1 = 715094163; 198 double t = 0.0; 199 unsigned int* pt = (unsigned int*) &t; 200 unsigned int* px = (unsigned int*) &d; 201 pt[1] = px[1] / 3 + B1; 202 return t; 203 } 204 205 // iterative cube root approximation using Halley's method (double) 206 static double cbrta_halleyd(const double a, const double R) { 207 const double a3 = a * a * a; 208 const double b = a * (a3 + R + R) / (a3 + a3 + R); 209 return b; 210 } 211 212 // cube root approximation using 3 iterations of Halley's method (double) 213 static double halley_cbrt3d(double d) { 214 double a = cbrt_5d(d); 215 a = cbrta_halleyd(a, d); 216 a = cbrta_halleyd(a, d); 217 return cbrta_halleyd(a, d); 218 } 219 220 double SkDCubeRoot(double x) { 221 if (approximately_zero_cubed(x)) { 222 return 0; 223 } 224 double result = halley_cbrt3d(fabs(x)); 225 if (x < 0) { 226 result = -result; 227 } 228 return result; 229 } 230 231 SkOpGlobalState::SkOpGlobalState(SkOpContourHead* head, 232 SkArenaAlloc* allocator 233 SkDEBUGPARAMS(bool debugSkipAssert) 234 SkDEBUGPARAMS(const char* testName)) 235 : fAllocator(allocator) 236 , fCoincidence(nullptr) 237 , fContourHead(head) 238 , fNested(0) 239 , fWindingFailed(false) 240 , fPhase(SkOpPhase::kIntersecting) 241 SkDEBUGPARAMS(fDebugTestName(testName)) 242 SkDEBUGPARAMS(fAngleID(0)) 243 SkDEBUGPARAMS(fCoinID(0)) 244 SkDEBUGPARAMS(fContourID(0)) 245 SkDEBUGPARAMS(fPtTID(0)) 246 SkDEBUGPARAMS(fSegmentID(0)) 247 SkDEBUGPARAMS(fSpanID(0)) 248 SkDEBUGPARAMS(fDebugSkipAssert(debugSkipAssert)) { 249 #if DEBUG_T_SECT_LOOP_COUNT 250 debugResetLoopCounts(); 251 #endif 252 #if DEBUG_COIN 253 fPreviousFuncName = nullptr; 254 #endif 255 } 256