Index: src/pathops/SkPathOpsTypes.cpp |
diff --git a/src/pathops/SkPathOpsTypes.cpp b/src/pathops/SkPathOpsTypes.cpp |
index dbed086fbd94d868d224eb97943f063599e0f562..fe24c2bceda4b62095255dcb30d4b50dd3a0dd3f 100644 |
--- a/src/pathops/SkPathOpsTypes.cpp |
+++ b/src/pathops/SkPathOpsTypes.cpp |
@@ -102,6 +102,13 @@ bool AlmostDequalUlps(float a, float b) { |
return d_equal_ulps(a, b, UlpsEpsilon); |
} |
+bool AlmostDequalUlps(double a, double b) { |
+ if (SkScalarIsFinite(a) || SkScalarIsFinite(b)) { |
+ return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); |
+ } |
+ return fabs(a - b) / SkTMax(fabs(a), fabs(b)) < FLT_EPSILON * 16; |
+} |
+ |
bool AlmostEqualUlps(float a, float b) { |
const int UlpsEpsilon = 16; |
return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon); |
@@ -191,3 +198,104 @@ double SkDCubeRoot(double x) { |
} |
return result; |
} |
+ |
+union SkDoubleLong { |
+ double fDouble; |
+ int64_t fLong; |
+}; |
+ |
+static inline int64_t SkSignBitTo2sCompliment(int64_t x) { |
+ if (x < 0) { |
+ x &= 0x7FFFFFFFFFFFFFFFL; |
+ x = -x; |
+ } |
+ return x; |
+} |
+ |
+ |
+static inline int64_t Sk2sComplimentToSignBit(int64_t x) { |
+ int64_t sign = x >> 63; |
+ // make x positive |
+ x = (x ^ sign) - sign; |
+ // set the sign bit as needed |
+ x |= sign << 63; |
+ return x; |
+} |
+ |
+static SkFloat128 SkFloat128AddMid(const SkFloat128& a, int64_t b) { |
+ uint64_t low = (uint64_t) b << 32; |
+ SkFloat128 result = a; |
+ result.fLow += low; |
+ if (a.fLow > result.fLow) { |
+ ++result.fHigh; |
+ } |
+ int64_t high = b >> 32; |
+ result.fHigh += high; |
+ // implementation incomplete |
+ return result; |
+} |
+ |
+double SkFloat128Sub(const SkFloat128& a, const SkFloat128& b) { |
+ SkFloat128 result = a; |
+ result.fLow -= b.fLow; |
+ if (a.fLow < result.fLow) { |
+ --result.fHigh; |
+ } |
+ result.fHigh -= b.fHigh; |
+ SkASSERT(result.fHigh == 0 || result.fHigh == -1L); |
+ SkASSERT(result.fHigh * result.fLow >= 0); // same sign |
+ if (result.fLow == 0) { |
+ return 0.; |
+ } |
+ int64_t uVal = abs((int64_t) result.fLow); |
+ while (uVal > 0) { |
+ uVal <<= 1; |
+ --result.fExp; |
+ } |
+ int64_t signBit = Sk2sComplimentToSignBit((int64_t) result.fLow); |
+ // implementation incomplete |
+ return (double) signBit; |
+} |
+ |
+// Helper to see a float as its bit pattern (w/o aliasing warnings) |
+SkFloat128 SkFloat128Mul(double a, double b) { |
+ SkFloat128 a128, b128; |
+ SkDoubleLong aMantissa, bMantissa; |
+ aMantissa.fDouble = frexp(a, &a128.fExp); |
+ a128.fLow = SkSignBitTo2sCompliment(aMantissa.fLong); |
+ a128.fHigh = a128.fLow < 0 ? (uint64_t) -1L : 0; |
+ bMantissa.fDouble = frexp(b, &b128.fExp); |
+ b128.fLow = SkSignBitTo2sCompliment(bMantissa.fLong); |
+ a128.fHigh = b128.fLow < 0 ? (uint64_t) -1L : 0; |
+ int expDiff = a128.fExp - b128.fExp; |
+ SkASSERT(abs(expDiff) < 12); |
+ SkFloat128 result; |
+ if (expDiff > 0) { |
+ b128.fLow <<= expDiff; |
+ result.fExp = a128.fExp; |
+ } else { |
+ a128.fLow <<= expDiff; |
+ result.fExp = b128.fExp; |
+ } |
+ uint64_t aLo = a128.fLow & 0xFFFFFFFF; |
+ int64_t aHi = a128.fLow >> 32; |
+ uint64_t bLo = b128.fLow & 0xFFFFFFFF; |
+ int64_t bHi = b128.fLow >> 32; |
+ result.fLow = aLo * bLo; |
+ int64_t mid = aLo * bHi; |
+ int64_t mid2 = aHi * bLo; |
+ result.fHigh = aHi * bHi; |
+ result = SkFloat128AddMid(result, mid); |
+ result = SkFloat128AddMid(result, mid2); |
+ return result; |
+} |
+ |
+SkFloat128 SkFloat128Mul(SkFloat128& a, double b) { |
+ |
+ int bExp; |
+ SkDoubleLong bMantissa; |
+ bMantissa.fDouble = frexp(b, &bExp); |
+ bMantissa.fLong = SkSignBitTo2sCompliment(bMantissa.fLong); |
+ // implementation incomplete |
+ return a; |
+} |