| 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;
|
| +}
|
|
|