aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-12-16 12:28:35 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-12-16 12:28:35 -0800
commitb669300a9753893ef900207c38aeff2d467764e5 (patch)
treeedfcba83547eb0897237a2547468bb6e708448c8 /src/pathops
parent54c6fe8519f2927181a0847d22a61190529645e8 (diff)
only call scalar finite when necessary
Mike points that the the ulps compares rank high in path ops profiles. The check for finite scalars is rarely required. Call it less by: - specializing _pin version of compares - checking for 0 divides up front - handling failing cases before comparing - casting float to double before adding R=reed@google.com Review URL: https://codereview.chromium.org/1522183002
Diffstat (limited to 'src/pathops')
-rw-r--r--src/pathops/SkDLineIntersection.cpp2
-rw-r--r--src/pathops/SkOpSegment.cpp3
-rw-r--r--src/pathops/SkPathOpsLine.cpp5
-rw-r--r--src/pathops/SkPathOpsQuad.cpp3
-rw-r--r--src/pathops/SkPathOpsTSect.h8
-rw-r--r--src/pathops/SkPathOpsTypes.cpp50
-rw-r--r--src/pathops/SkPathOpsTypes.h10
-rw-r--r--src/pathops/SkReduceOrder.cpp4
8 files changed, 59 insertions, 26 deletions
diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp
index 6fbac978b6..71e2a064d5 100644
--- a/src/pathops/SkDLineIntersection.cpp
+++ b/src/pathops/SkDLineIntersection.cpp
@@ -108,7 +108,7 @@ int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) {
double ayBxLen = ayLen * bxLen;
// detect parallel lines the same way here and in SkOpAngle operator <
// so that non-parallel means they are also sortable
- bool unparallel = fAllowNear ? NotAlmostEqualUlps(axByLen, ayBxLen)
+ bool unparallel = fAllowNear ? NotAlmostEqualUlps_Pin(axByLen, ayBxLen)
: NotAlmostDequalUlps(axByLen, ayBxLen);
if (unparallel && fUsed == 0) {
double ab0y = a[0].fY - b[0].fY;
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index d066794cee..67f172e58a 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -1683,7 +1683,8 @@ bool SkOpSegment::testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT
coincident = false;
SkIntersections i;
SkVector dxdy = (*CurveSlopeAtT[fVerb])(this->pts(), this->weight(), midT);
- SkDLine ray = {{{midPt.fX, midPt.fY}, {midPt.fX + dxdy.fY, midPt.fY - dxdy.fX}}};
+ SkDLine ray = {{{midPt.fX, midPt.fY},
+ {(double) midPt.fX + dxdy.fY, (double) midPt.fY - dxdy.fX}}};
(*CurveIntersectRay[opp->verb()])(opp->pts(), opp->weight(), ray, &i);
// measure distance and see if it's small enough to denote coincidence
for (int index = 0; index < i.used(); ++index) {
diff --git a/src/pathops/SkPathOpsLine.cpp b/src/pathops/SkPathOpsLine.cpp
index cad54eb263..6fa091db8e 100644
--- a/src/pathops/SkPathOpsLine.cpp
+++ b/src/pathops/SkPathOpsLine.cpp
@@ -41,6 +41,9 @@ double SkDLine::nearPoint(const SkDPoint& xy, bool* unequal) const {
if (!between(0, numer, denom)) {
return -1;
}
+ if (!denom) {
+ return 0;
+ }
double t = numer / denom;
SkDPoint realPt = ptAtT(t);
double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ?
@@ -48,7 +51,7 @@ double SkDLine::nearPoint(const SkDPoint& xy, bool* unequal) const {
double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY);
double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY);
largest = SkTMax(largest, -tiniest);
- if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance?
+ if (!AlmostEqualUlps_Pin(largest, largest + dist)) { // is the dist within ULPS tolerance?
return -1;
}
if (unequal) {
diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp
index 12b9658ce7..3deab21133 100644
--- a/src/pathops/SkPathOpsQuad.cpp
+++ b/src/pathops/SkPathOpsQuad.cpp
@@ -119,7 +119,8 @@ and using the roots
int SkDQuad::RootsReal(const double A, const double B, const double C, double s[2]) {
const double p = B / (2 * A);
const double q = C / A;
- if (approximately_zero(A) && (approximately_zero_inverse(p) || approximately_zero_inverse(q))) {
+ if (!A || (approximately_zero(A) && (approximately_zero_inverse(p)
+ || approximately_zero_inverse(q)))) {
if (approximately_zero(B)) {
s[0] = 0;
return C == 0;
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
index bebdf40208..074fe37654 100644
--- a/src/pathops/SkPathOpsTSect.h
+++ b/src/pathops/SkPathOpsTSect.h
@@ -1467,11 +1467,17 @@ int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
workT += tStep;
workPt = fCurve.ptAtT(workT);
coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
+ if (coinW.perpT() < 0) {
+ continue;
+ }
SkDVector perpW = workPt - coinW.perpPt();
if ((perpS.dot(perpW) >= 0) == (tStep < 0)) {
tStep = -tStep;
}
- } while (!workPt.approximatelyEqual(coinW.perpPt()));
+ if (workPt.approximatelyEqual(coinW.perpPt())) {
+ break;
+ }
+ } while (true);
double oppTTest = coinW.perpT();
if (!opp->fHead->contains(oppTTest)) {
return 0;
diff --git a/src/pathops/SkPathOpsTypes.cpp b/src/pathops/SkPathOpsTypes.cpp
index ca84405aa7..1ed484afee 100644
--- a/src/pathops/SkPathOpsTypes.cpp
+++ b/src/pathops/SkPathOpsTypes.cpp
@@ -16,6 +16,16 @@ static bool arguments_denormalized(float a, float b, int epsilon) {
// 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, int depsilon) {
+ if (arguments_denormalized(a, b, depsilon)) {
+ return true;
+ }
+ int aBits = SkFloatAs2sCompliment(a);
+ int bBits = SkFloatAs2sCompliment(b);
+ // Find the difference in ULPs.
+ return aBits < bBits + epsilon && bBits < aBits + epsilon;
+}
+
+static bool equal_ulps_pin(float a, float b, int epsilon, int depsilon) {
if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
return false;
}
@@ -29,9 +39,6 @@ static bool equal_ulps(float a, float b, int epsilon, int depsilon) {
}
static bool d_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.
@@ -39,6 +46,16 @@ static bool d_equal_ulps(float a, float b, int epsilon) {
}
static bool not_equal_ulps(float a, float b, int epsilon) {
+ if (arguments_denormalized(a, b, epsilon)) {
+ return false;
+ }
+ int aBits = SkFloatAs2sCompliment(a);
+ int bBits = SkFloatAs2sCompliment(b);
+ // Find the difference in ULPs.
+ return aBits >= bBits + epsilon || bBits >= aBits + epsilon;
+}
+
+static bool not_equal_ulps_pin(float a, float b, int epsilon) {
if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
return false;
}
@@ -52,9 +69,6 @@ static bool not_equal_ulps(float a, float b, int epsilon) {
}
static bool d_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.
@@ -62,9 +76,6 @@ static bool d_not_equal_ulps(float a, float b, int epsilon) {
}
static bool less_ulps(float a, float b, int epsilon) {
- if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
- return false;
- }
if (arguments_denormalized(a, b, epsilon)) {
return a <= b - FLT_EPSILON * epsilon;
}
@@ -75,9 +86,6 @@ static bool less_ulps(float a, float b, int epsilon) {
}
static bool less_or_equal_ulps(float a, float b, int epsilon) {
- if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
- return false;
- }
if (arguments_denormalized(a, b, epsilon)) {
return a < b + FLT_EPSILON * epsilon;
}
@@ -104,10 +112,7 @@ bool AlmostDequalUlps(float a, float b) {
}
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;
+ return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
}
bool AlmostEqualUlps(float a, float b) {
@@ -115,11 +120,21 @@ bool AlmostEqualUlps(float a, float b) {
return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon);
}
+bool AlmostEqualUlps_Pin(float a, float b) {
+ const int UlpsEpsilon = 16;
+ return equal_ulps_pin(a, b, UlpsEpsilon, UlpsEpsilon);
+}
+
bool NotAlmostEqualUlps(float a, float b) {
const int UlpsEpsilon = 16;
return not_equal_ulps(a, b, UlpsEpsilon);
}
+bool NotAlmostEqualUlps_Pin(float a, float b) {
+ const int UlpsEpsilon = 16;
+ return not_equal_ulps_pin(a, b, UlpsEpsilon);
+}
+
bool NotAlmostDequalUlps(float a, float b) {
const int UlpsEpsilon = 16;
return d_not_equal_ulps(a, b, UlpsEpsilon);
@@ -148,9 +163,6 @@ bool AlmostLessOrEqualUlps(float a, float b) {
}
int UlpsDistance(float a, float b) {
- if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
- return SK_MaxS32;
- }
SkFloatIntUnion floatIntA, floatIntB;
floatIntA.fFloat = a;
floatIntB.fFloat = b;
diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h
index f85c6653eb..b35c97ef06 100644
--- a/src/pathops/SkPathOpsTypes.h
+++ b/src/pathops/SkPathOpsTypes.h
@@ -167,6 +167,11 @@ inline bool AlmostEqualUlps(double a, double b) {
return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
}
+bool AlmostEqualUlps_Pin(float a, float b);
+inline bool AlmostEqualUlps_Pin(double a, double b) {
+ return AlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
+}
+
// Use Almost Dequal when comparing should not special case denormalized values.
bool AlmostDequalUlps(float a, float b);
bool AlmostDequalUlps(double a, double b);
@@ -176,6 +181,11 @@ inline bool NotAlmostEqualUlps(double a, double b) {
return NotAlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
}
+bool NotAlmostEqualUlps_Pin(float a, float b);
+inline bool NotAlmostEqualUlps_Pin(double a, double b) {
+ return NotAlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
+}
+
bool NotAlmostDequalUlps(float a, float b);
inline bool NotAlmostDequalUlps(double a, double b) {
return NotAlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
diff --git a/src/pathops/SkReduceOrder.cpp b/src/pathops/SkReduceOrder.cpp
index 43a91901f7..52a19d6138 100644
--- a/src/pathops/SkReduceOrder.cpp
+++ b/src/pathops/SkReduceOrder.cpp
@@ -126,7 +126,7 @@ static int check_quadratic(const SkDCubic& cubic, SkDCubic& reduction) {
double sideAx = midX - cubic[3].fX;
double sideBx = dx23 * 3 / 2;
if (approximately_zero(sideAx) ? !approximately_equal(sideAx, sideBx)
- : !AlmostEqualUlps(sideAx, sideBx)) {
+ : !AlmostEqualUlps_Pin(sideAx, sideBx)) {
return 0;
}
double dy10 = cubic[1].fY - cubic[0].fY;
@@ -135,7 +135,7 @@ static int check_quadratic(const SkDCubic& cubic, SkDCubic& reduction) {
double sideAy = midY - cubic[3].fY;
double sideBy = dy23 * 3 / 2;
if (approximately_zero(sideAy) ? !approximately_equal(sideAy, sideBy)
- : !AlmostEqualUlps(sideAy, sideBy)) {
+ : !AlmostEqualUlps_Pin(sideAy, sideBy)) {
return 0;
}
reduction[0] = cubic[0];