Skip to content

Commit

Permalink
Make Box2d::contains and Box2d intersects faster (#526)
Browse files Browse the repository at this point in the history
* Make Box2d::contains and Box2d intersects faster

Chaining simple && conditions produces branch instructions in some cases. Replacing the logical and with bitwise & to ensure the compiler does not produce branches makes a big performance difference.

* Speed up Box2d::contains_box the same way

* Give box3d the same treatment
  • Loading branch information
nical authored May 20, 2024
1 parent 1c2c12a commit 3a3e57f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 28 deletions.
23 changes: 13 additions & 10 deletions src/box2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,25 +161,28 @@ where
/// Returns `true` if the two boxes intersect.
#[inline]
pub fn intersects(&self, other: &Self) -> bool {
self.min.x < other.max.x
&& self.max.x > other.min.x
&& self.min.y < other.max.y
&& self.max.y > other.min.y
// Use bitwise and instead of && to avoid emitting branches.
(self.min.x < other.max.x)
& (self.max.x > other.min.x)
& (self.min.y < other.max.y)
& (self.max.y > other.min.y)
}

/// Returns `true` if this box2d contains the point `p`. A point is considered
/// in the box2d if it lies on the left or top edges, but outside if it lies
/// on the right or bottom edges.
#[inline]
pub fn contains(&self, p: Point2D<T, U>) -> bool {
self.min.x <= p.x && p.x < self.max.x && self.min.y <= p.y && p.y < self.max.y
// Use bitwise and instead of && to avoid emitting branches.
(self.min.x <= p.x) & (p.x < self.max.x) & (self.min.y <= p.y) & (p.y < self.max.y)
}

/// Returns `true` if this box contains the point `p`. A point is considered
/// in the box2d if it lies on any edge of the box2d.
#[inline]
pub fn contains_inclusive(&self, p: Point2D<T, U>) -> bool {
self.min.x <= p.x && p.x <= self.max.x && self.min.y <= p.y && p.y <= self.max.y
// Use bitwise and instead of && to avoid emitting branches.
(self.min.x <= p.x) & (p.x <= self.max.x) & (self.min.y <= p.y) & (p.y <= self.max.y)
}

/// Returns `true` if this box contains the interior of the other box. Always
Expand All @@ -188,10 +191,10 @@ where
#[inline]
pub fn contains_box(&self, other: &Self) -> bool {
other.is_empty()
|| (self.min.x <= other.min.x
&& other.max.x <= self.max.x
&& self.min.y <= other.min.y
&& other.max.y <= self.max.y)
|| ((self.min.x <= other.min.x)
& (other.max.x <= self.max.x)
& (self.min.y <= other.min.y)
& (other.max.y <= self.max.y))
}
}

Expand Down
36 changes: 18 additions & 18 deletions src/box3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,24 +147,24 @@ where
/// on the back, right or bottom faces.
#[inline]
pub fn contains(&self, other: Point3D<T, U>) -> bool {
self.min.x <= other.x
&& other.x < self.max.x
&& self.min.y <= other.y
&& other.y < self.max.y
&& self.min.z <= other.z
&& other.z < self.max.z
(self.min.x <= other.x)
& (other.x < self.max.x)
& (self.min.y <= other.y)
& (other.y < self.max.y)
& (self.min.z <= other.z)
& (other.z < self.max.z)
}

/// Returns `true` if this box3d contains the point `p`. A point is considered
/// in the box3d if it lies on any face of the box3d.
#[inline]
pub fn contains_inclusive(&self, other: Point3D<T, U>) -> bool {
self.min.x <= other.x
&& other.x <= self.max.x
&& self.min.y <= other.y
&& other.y <= self.max.y
&& self.min.z <= other.z
&& other.z <= self.max.z
(self.min.x <= other.x)
& (other.x <= self.max.x)
& (self.min.y <= other.y)
& (other.y <= self.max.y)
& (self.min.z <= other.z)
& (other.z <= self.max.z)
}

/// Returns `true` if this box3d contains the interior of the other box3d. Always
Expand All @@ -173,12 +173,12 @@ where
#[inline]
pub fn contains_box(&self, other: &Self) -> bool {
other.is_empty()
|| (self.min.x <= other.min.x
&& other.max.x <= self.max.x
&& self.min.y <= other.min.y
&& other.max.y <= self.max.y
&& self.min.z <= other.min.z
&& other.max.z <= self.max.z)
|| ((self.min.x <= other.min.x)
& (other.max.x <= self.max.x)
& (self.min.y <= other.min.y)
& (other.max.y <= self.max.y)
& (self.min.z <= other.min.z)
& (other.max.z <= self.max.z))
}
}

Expand Down

0 comments on commit 3a3e57f

Please sign in to comment.