From 8faa0592272fa054e8c233210b775fd0d280db1a Mon Sep 17 00:00:00 2001 From: Michael Doube Date: Wed, 12 Jul 2023 18:59:59 +0800 Subject: [PATCH] Use dedicated 3-way sort (#339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use dedicated 3-way sort Arrays.sort carries overhead because it's generalised. But we know precisely the case here, which is always a 3-element array. Profiling shows that while assigning ellipsoid IDs most (98% !) of the time is spent in getSortedRadii(). This dedicated 3-way sort is about 2× faster than Arrays.sort in a basic performance test. * Reduce slow methods a bit more * getSortedRadii() and Math.max() are similar speed But the result is needed twice (for min and max) so getSortedRadii() is better here. * formatting --- .../EllipsoidOptimisationStrategy.java | 18 +++---- .../bonej/ops/ellipsoid/QuickEllipsoid.java | 52 +++++++++++++------ .../ops/ellipsoid/QuickEllipsoidTest.java | 18 +++++++ 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/EllipsoidOptimisationStrategy.java b/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/EllipsoidOptimisationStrategy.java index 1ac6b219..993a7a1a 100644 --- a/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/EllipsoidOptimisationStrategy.java +++ b/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/EllipsoidOptimisationStrategy.java @@ -91,16 +91,14 @@ private static double[][] findContactUnitVectors(final QuickEllipsoid ellipsoid, for (int i = 0; i < contactPoints.size(); i++) { final double[] p = contactPoints.get(i); - final double px = p[0]; - final double py = p[1]; - final double pz = p[2]; - - Vector3d distance = new Vector3d(px, py, pz); - distance.sub(new Vector3d(cx, cy, cz)); - final double l = distance.length(); - final double x = (px - cx) / l; - final double y = (py - cy) / l; - final double z = (pz - cz) / l; + final double px = p[0] - cx; + final double py = p[1] - cy; + final double pz = p[2] - cz; + + final double l = Math.sqrt(px * px + py * py + pz * pz); + final double x = px / l; + final double y = py / l; + final double z = pz / l; final double[] u = {x, y, z}; unitVectors[i] = u; } diff --git a/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/QuickEllipsoid.java b/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/QuickEllipsoid.java index 71ffd817..8f373b4d 100644 --- a/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/QuickEllipsoid.java +++ b/Modern/ops/src/main/java/org/bonej/ops/ellipsoid/QuickEllipsoid.java @@ -202,7 +202,8 @@ public boolean contains(final double x, final double y, final double z) { // if length closer than minor semiaxis length // must be inside - if (length <= radii[0]) + final double minRadius = radii[0]; + if (length <= minRadius) return true; final double[][] h = getEllipsoidTensor(); @@ -316,8 +317,29 @@ public void setRotation(final double[][] rotation) { * @return radii in ascending order */ public double[] getSortedRadii() { - final double[] sortedRadii = {ra, rb, rc}; - Arrays.sort(sortedRadii); + double a = this.ra; + double b = this.rb; + double c = this.rc; + double temp = 0; + + if (a > b) { + temp = a; + a = b; + b = temp; + } + if (b > c) { + temp = b; + b = c; + c = temp; + } + if (a > b) { + temp = a; + a = b; + b = temp; + } + + final double[] sortedRadii = { a, b, c }; + return sortedRadii; } @@ -345,15 +367,15 @@ public double[][] getAxisAlignRandomlyDistributedSurfacePoints(int n) { refreshRandomNumbersIfNeeded(); final double[] sortedRadii = getSortedRadii(); - final double muMax = sortedRadii[1]* sortedRadii[2]; + final double muMax = sortedRadii[1] * sortedRadii[2]; final double[][] surfacePoints = new double[n][3]; int surfacePointsFound = 0; int attemptCounter = 0; - while (surfacePointsFound