diff options
Diffstat (limited to 'src/pathops/SkPathOpsTypes.cpp')
-rw-r--r-- | src/pathops/SkPathOpsTypes.cpp | 78 |
1 files changed, 57 insertions, 21 deletions
diff --git a/src/pathops/SkPathOpsTypes.cpp b/src/pathops/SkPathOpsTypes.cpp index 8135c57025..2d7388b882 100644 --- a/src/pathops/SkPathOpsTypes.cpp +++ b/src/pathops/SkPathOpsTypes.cpp @@ -7,34 +7,52 @@ #include "SkFloatBits.h" #include "SkPathOpsTypes.h" - - // from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ // FIXME: move to SkFloatBits.h static bool equal_ulps(float a, float b, int epsilon) { - SkFloatIntUnion floatIntA, floatIntB; - floatIntA.fFloat = a; - floatIntB.fFloat = b; - // Different signs means they do not match. - if ((floatIntA.fSignBitInt < 0) != (floatIntB.fSignBitInt < 0)) { - // Check for equality to make sure +0 == -0 - return a == b; + if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { + return false; } + int aBits = SkFloatAs2sCompliment(a); + int bBits = SkFloatAs2sCompliment(b); // Find the difference in ULPs. - int ulpsDiff = abs(floatIntA.fSignBitInt - floatIntB.fSignBitInt); - return ulpsDiff <= epsilon; + return aBits < bBits + epsilon && bBits < aBits + epsilon; +} + +static bool not_equal_ulps(float a, float b, int epsilon) { + if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { + return false; + } + int aBits = SkFloatAs2sCompliment(a); + int bBits = SkFloatAs2sCompliment(b); + // Find the difference in ULPs. + return aBits >= bBits + epsilon || bBits >= aBits + epsilon; } static bool less_ulps(float a, float b, int epsilon) { - SkFloatIntUnion floatIntA, floatIntB; - floatIntA.fFloat = a; - floatIntB.fFloat = b; - // Check different signs with float epsilon since we only care if they're both close to 0. - if ((floatIntA.fSignBitInt < 0) != (floatIntB.fSignBitInt < 0)) { - return a <= b + FLT_EPSILON * epsilon; + if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { + return false; } + int aBits = SkFloatAs2sCompliment(a); + int bBits = SkFloatAs2sCompliment(b); // Find the difference in ULPs. - return floatIntA.fSignBitInt <= floatIntB.fSignBitInt + epsilon; + return aBits <= bBits - epsilon; +} + +static bool less_or_equal_ulps(float a, float b, int epsilon) { + if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { + return false; + } + int aBits = SkFloatAs2sCompliment(a); + int bBits = SkFloatAs2sCompliment(b); + // Find the difference in ULPs. + return aBits < bBits + epsilon; +} + +// equality using the same error term as between +bool AlmostBequalUlps(float a, float b) { + const int UlpsEpsilon = 2; + return equal_ulps(a, b, UlpsEpsilon); } bool AlmostEqualUlps(float a, float b) { @@ -42,18 +60,36 @@ bool AlmostEqualUlps(float a, float b) { return equal_ulps(a, b, UlpsEpsilon); } +bool NotAlmostEqualUlps(float a, float b) { + const int UlpsEpsilon = 16; + return not_equal_ulps(a, b, UlpsEpsilon); +} + bool RoughlyEqualUlps(float a, float b) { const int UlpsEpsilon = 256; return equal_ulps(a, b, UlpsEpsilon); } bool AlmostBetweenUlps(float a, float b, float c) { - const int UlpsEpsilon = 1; - return a <= c ? less_ulps(a, b, UlpsEpsilon) && less_ulps(b, c, UlpsEpsilon) - : less_ulps(b, a, UlpsEpsilon) && less_ulps(c, b, UlpsEpsilon); + const int UlpsEpsilon = 2; + return a <= c ? less_or_equal_ulps(a, b, UlpsEpsilon) && less_or_equal_ulps(b, c, UlpsEpsilon) + : less_or_equal_ulps(b, a, UlpsEpsilon) && less_or_equal_ulps(c, b, UlpsEpsilon); +} + +bool AlmostLessUlps(float a, float b) { + const int UlpsEpsilon = 16; + return less_ulps(a, b, UlpsEpsilon); +} + +bool AlmostLessOrEqualUlps(float a, float b) { + const int UlpsEpsilon = 16; + return less_or_equal_ulps(a, b, UlpsEpsilon); } int UlpsDistance(float a, float b) { + if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) { + return SK_MaxS32; + } SkFloatIntUnion floatIntA, floatIntB; floatIntA.fFloat = a; floatIntB.fFloat = b; |