Use Ozaki et al.'s error bound and single-branch evaluation in orientation index filter. #1184
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR is separated out of #1162 . It contains two changes to the orientation predicate.
The first change changes the relative error bound from currently 1e-15 to ~3.33e-16, which is proven to be sufficient in https://doi.org/10.1007/s10543-015-0574-9 by Ozaki et al. A tighter error bound can reduce the calls to the expensive exact computation in some degenerate cases (Edit: Here is a gist demonstrating this for a sequence of 100k generated near-collinear inputs https://gist.github.com/tinko92/ce44f93d8d4e4d5909310c00cf19b391 ) and has no disadvantages.
The second changes is also motivated by https://doi.org/10.1007/s10543-015-0574-9 and reduces the number of branches and instructions in the evaluation. This is more concise and may result in faster evaluation (benchmarks are in the referenced paper) but I am not currently aware of any geos-benchmarks, beside the Orientation Index micro benchmark, for which the orientation predicate is the bottle neck. The original logic that is replaced is from the function body of
REAL orient2d(pa, pb, pc)
https://www.cs.cmu.edu/afs/cs/project/quake/public/code/predicates.c , where the early returns make use of the branching in the fabs-computation, discussed in the comment preceding#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
. This reasoning is obsolete because modern compilers with enabled optimizations will compile fabs to a branchless masking of the sign bit.Edit: I did not remove the
orientation(double x)
function, which seems unused now, because I don't know if that would be considered an API change (it's not in a namespace called detail or internal or sth. like that and I don't know the geos conventions). But I can edit the commit if it is no longer needed.Edit2: Sorry for only now reading more about the jts-geos-relationship/-process. I will propose the same change to JTS, when I find time. Having said that, since patched and unpatched always return the correct orientation by deferring filter misses to the exact computation for inputs that do not go near overflow/underflow, this would not change observable behavior between JTS/Geos for the same inputs, except in computation time, so I think it classifies as an implementation detail/optimization.