Skip to content

Commit 01c75d0

Browse files
Switches to using precomputed reciprocal math.
See issue #337 #337 for more info.
1 parent 507a7c1 commit 01c75d0

18 files changed

+321
-78
lines changed

PlayRho/Collision/AABB.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ AABB ComputeAABB(const DistanceProxy& proxy, const Transformation& xf) noexcept
4545
}
4646

4747
AABB ComputeAABB(const DistanceProxy& proxy,
48-
const Transformation& xfm0, const Transformation& xfm1) noexcept
48+
const Transformation& xfm0, const Transformation& xfm1) noexcept
4949
{
5050
assert(IsValid(xfm0));
5151
assert(IsValid(xfm1));

PlayRho/Collision/AABB.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ PLAYRHO_CONSTEXPR inline Vector<Length, N> GetDimensions(const AABB<N>& aabb) no
236236
template <std::size_t N>
237237
PLAYRHO_CONSTEXPR inline Vector<Length, N> GetExtents(const AABB<N>& aabb) noexcept
238238
{
239-
return GetDimensions(aabb) / 2;
239+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
240+
return GetDimensions(aabb) * RealInverseOfTwo;
240241
}
241242

242243
/// @brief Checks whether the first AABB fully contains the second AABB.

PlayRho/Collision/MassData.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,19 @@ MassData GetMassData(Length vertexRadius, NonNegative<AreaDensity> density,
145145

146146
const auto D = Cross(e1, e2);
147147

148-
const auto triangleArea = D / Real{2};
148+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfTwo = Real{1} / Real{2}; // .5
149+
const auto triangleArea = D * RealReciprocalOfTwo;
149150
area += triangleArea;
150151

151152
// Area weighted centroid
152-
center += StripUnit(triangleArea) * (e1 + e2) / Real{3};
153+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfThree = Real{1} / Real{3}; // .3333333...
154+
center += StripUnit(triangleArea) * (e1 + e2) * RealReciprocalOfThree;
153155

154156
const auto intx2 = Square(GetX(e1)) + GetX(e2) * GetX(e1) + Square(GetX(e2));
155157
const auto inty2 = Square(GetY(e1)) + GetY(e2) * GetY(e1) + Square(GetY(e2));
156158

157-
const auto triangleI = D * (intx2 + inty2) / Real{3 * 4};
159+
PLAYRHO_CONSTEXPR const auto RealReciprocalOfTwelve = Real{1} / Real{3 * 4}; // .083333..
160+
const auto triangleI = D * (intx2 + inty2) * RealReciprocalOfTwelve;
158161
I += triangleI;
159162
}
160163

PlayRho/Collision/RayCastOutput.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ RayCastOutput RayCast(const AABB& aabb, const RayCastInput& input) noexcept
9393
}
9494
else
9595
{
96-
auto t1 = Real{(range.GetMin() - p1i) / pdi};
97-
auto t2 = Real{(range.GetMax() - p1i) / pdi};
96+
const auto reciprocalOfPdi = Real{1} / pdi;
97+
auto t1 = Real{(range.GetMin() - p1i) * reciprocalOfPdi};
98+
auto t2 = Real{(range.GetMax() - p1i) * reciprocalOfPdi};
9899
auto s = -1; // Sign of the normal vector.
99100
if (t1 > t2)
100101
{
@@ -187,11 +188,13 @@ RayCastOutput RayCast(const DistanceProxy& proxy, const RayCastInput& input,
187188
const auto v0off = v0 + offset;
188189
const auto q_sub_p = v0off - ray0;
189190

191+
const auto reciprocalRayCrossEdge = Real{1} / ray_cross_edge;
192+
190193
// t = ((q - p) x s) / (r x s)
191-
const auto t = Cross(q_sub_p, edge) / ray_cross_edge;
194+
const auto t = Cross(q_sub_p, edge) * reciprocalRayCrossEdge;
192195

193196
// u = ((q - p) x r) / (r x s)
194-
const auto u = Cross(q_sub_p, ray) / ray_cross_edge;
197+
const auto u = Cross(q_sub_p, ray) * reciprocalRayCrossEdge;
195198

196199
if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1))
197200
{

PlayRho/Collision/Simplex.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1) noexcept
111111
}
112112

113113
// Must be in e12 region.
114-
const auto d12_sum = d12_1 + d12_2;
115-
return Simplex{{s0, s1}, {d12_1 / d12_sum, d12_2 / d12_sum}};
114+
const auto inv_sum = Real{1} / (d12_1 + d12_2);
115+
return Simplex{{s0, s1}, {d12_1 * inv_sum, d12_2 * inv_sum}};
116116
}
117117

118118
Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1, const SimplexEdge& s2) noexcept
@@ -179,31 +179,31 @@ Simplex Simplex::Get(const SimplexEdge& s0, const SimplexEdge& s1, const Simplex
179179
const auto d123_3 = n123 * cp_w1_w2;
180180
if ((d12_1 > 0_m2) && (d12_2 > 0_m2) && (d123_3 <= 0 * SquareMeter * SquareMeter))
181181
{
182-
const auto d12_sum = d12_1 + d12_2;
183-
return Simplex{{s0, s1}, {d12_1 / d12_sum, d12_2 / d12_sum}};
182+
const auto inv_sum = Real{1} / (d12_1 + d12_2);
183+
return Simplex{{s0, s1}, {d12_1 * inv_sum, d12_2 * inv_sum}};
184184
}
185185

186186
// e13
187187
const auto cp_w3_w1 = Cross(w3, w1);
188188
const auto d123_2 = n123 * cp_w3_w1;
189189
if ((d13_1 > 0_m2) && (d13_2 > 0_m2) && (d123_2 <= 0 * SquareMeter * SquareMeter))
190190
{
191-
const auto d13_sum = d13_1 + d13_2;
192-
return Simplex{{s0, s2}, {d13_1 / d13_sum, d13_2 / d13_sum}};
191+
const auto inv_sum = Real{1} / (d13_1 + d13_2);
192+
return Simplex{{s0, s2}, {d13_1 * inv_sum, d13_2 * inv_sum}};
193193
}
194194

195195
// e23
196196
const auto cp_w2_w3 = Cross(w2, w3);
197197
const auto d123_1 = n123 * cp_w2_w3;
198198
if ((d23_1 > 0_m2) && (d23_2 > 0_m2) && (d123_1 <= 0 * SquareMeter * SquareMeter))
199199
{
200-
const auto d23_sum = d23_1 + d23_2;
201-
return Simplex{{s2, s1}, {d23_2 / d23_sum, d23_1 / d23_sum}};
200+
const auto inv_sum = Real{1} / (d23_1 + d23_2);
201+
return Simplex{{s2, s1}, {d23_2 * inv_sum, d23_1 * inv_sum}};
202202
}
203203

204204
// Must be in triangle123
205-
const auto d123_sum = d123_1 + d123_2 + d123_3;
206-
return Simplex{{s0, s1, s2}, {d123_1 / d123_sum, d123_2 / d123_sum, d123_3 / d123_sum}};
205+
const auto inv_sum = Real{1} / (d123_1 + d123_2 + d123_3);
206+
return Simplex{{s0, s1, s2}, {d123_1 * inv_sum, d123_2 * inv_sum, d123_3 * inv_sum}};
207207
}
208208

209209
Simplex Simplex::Get(const SimplexEdges& edges) noexcept

PlayRho/Common/Acceleration.hpp

+2-11
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,8 @@ namespace d2 {
132132
/// @relatedalso Acceleration
133133
PLAYRHO_CONSTEXPR inline Acceleration operator/ (const Acceleration& lhs, const Real rhs)
134134
{
135-
/*
136-
* While it can be argued that division operations shouldn't be supported due to
137-
* hardware support for division typically being significantly slower than hardware
138-
* support for multiplication, it can also be argued that it shouldn't be the
139-
* software developer's role to attempt to optimize what the compiler should be
140-
* much better at knowing how to optimize. So here the code chooses the latter
141-
* strategy which allows the intention to be clearer, and just passes the division
142-
* on down to the Vec2 and Angle types (rather than manually rewriting the divisions
143-
* as multiplications).
144-
*/
145-
return Acceleration{lhs.linear / rhs, lhs.angular / rhs};
135+
const auto inverseRhs = Real{1} / rhs;
136+
return Acceleration{lhs.linear * inverseRhs, lhs.angular * inverseRhs};
146137
}
147138

148139
} // namespace d2

PlayRho/Common/Math.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@ Length2 ComputeCentroid(const Span<const Length2>& vertices)
6262
const auto e1 = p2 - p1;
6363
const auto e2 = p3 - p1;
6464

65-
const auto triangleArea = Area{Cross(e1, e2) / Real(2)};
65+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
66+
const auto triangleArea = Area{Cross(e1, e2) * RealInverseOfTwo};
6667
area += triangleArea;
6768

6869
// Area weighted centroid
69-
const auto aveP = (p1 + p2 + p3) / Real{3};
70+
PLAYRHO_CONSTEXPR const auto RealInverseOfThree = Real{1} / Real{3};
71+
const auto aveP = (p1 + p2 + p3) * RealInverseOfThree;
7072
c += triangleArea * aveP;
7173
}
7274

@@ -129,7 +131,8 @@ NonNegative<Area> GetAreaOfPolygon(Span<const Length2> vertices)
129131

130132
// Note that using the absolute value isn't necessary for vertices in counter-clockwise
131133
// ordering; only needed for clockwise ordering.
132-
return abs(sum) / Real{2};
134+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwo = Real{1} / Real{2};
135+
return abs(sum) * RealInverseOfTwo;
133136
}
134137

135138
SecondMomentOfArea GetPolarMoment(Span<const Length2> vertices)
@@ -161,7 +164,8 @@ SecondMomentOfArea GetPolarMoment(Span<const Length2> vertices)
161164
}
162165
const auto secondMomentOfAreaX = SecondMomentOfArea{sum_x};
163166
const auto secondMomentOfAreaY = SecondMomentOfArea{sum_y};
164-
return (secondMomentOfAreaX + secondMomentOfAreaY) / Real{12};
167+
PLAYRHO_CONSTEXPR const auto RealInverseOfTwelve = Real{1} / Real{12};
168+
return (secondMomentOfAreaX + secondMomentOfAreaY) * RealInverseOfTwelve;
165169
}
166170

167171
namespace d2 {

PlayRho/Common/Math.hpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,12 @@ template <typename T, typename U>
451451
PLAYRHO_CONSTEXPR inline auto Solve(const Matrix22<U> mat, const Vector2<T> b) noexcept
452452
{
453453
const auto cp = Cross(get<0>(mat), get<1>(mat));
454+
const auto inverseCp = Real{1} / cp;
454455
using OutType = decltype((U{} * T{}) / cp);
455456
return (!AlmostZero(StripUnit(cp)))?
456457
Vector2<OutType>{
457-
(get<1>(mat)[1] * b[0] - get<1>(mat)[0] * b[1]) / cp,
458-
(get<0>(mat)[0] * b[1] - get<0>(mat)[1] * b[0]) / cp
458+
(get<1>(mat)[1] * b[0] - get<1>(mat)[0] * b[1]) * inverseCp,
459+
(get<0>(mat)[0] * b[1] - get<0>(mat)[1] * b[0]) * inverseCp
459460
}: Vector2<OutType>{};
460461
}
461462

@@ -465,10 +466,11 @@ PLAYRHO_CONSTEXPR inline auto Invert(const Matrix22<IN_TYPE> value) noexcept
465466
{
466467
const auto cp = Cross(get<0>(value), get<1>(value));
467468
using OutType = decltype(get<0>(value)[0] / cp);
469+
const auto inverseCp = Real{1} / cp;
468470
return (!AlmostZero(StripUnit(cp)))?
469471
Matrix22<OutType>{
470-
Vector2<OutType>{ get<1>(get<1>(value)) / cp, -get<1>(get<0>(value)) / cp},
471-
Vector2<OutType>{-get<0>(get<1>(value)) / cp, get<0>(get<0>(value)) / cp}
472+
Vector2<OutType>{ get<1>(get<1>(value)) * inverseCp, -get<1>(get<0>(value)) * inverseCp},
473+
Vector2<OutType>{-get<0>(get<1>(value)) * inverseCp, get<0>(get<0>(value)) * inverseCp}
472474
}:
473475
Matrix22<OutType>{};
474476
}
@@ -478,7 +480,7 @@ PLAYRHO_CONSTEXPR inline auto Invert(const Matrix22<IN_TYPE> value) noexcept
478480
PLAYRHO_CONSTEXPR inline Vec3 Solve33(const Mat33& mat, const Vec3 b) noexcept
479481
{
480482
const auto dp = Dot(GetX(mat), Cross(GetY(mat), GetZ(mat)));
481-
const auto det = (dp != 0)? 1 / dp: dp;
483+
const auto det = (dp != 0)? Real{1} / dp: dp;
482484
const auto x = det * Dot(b, Cross(GetY(mat), GetZ(mat)));
483485
const auto y = det * Dot(GetX(mat), Cross(b, GetZ(mat)));
484486
const auto z = det * Dot(GetX(mat), Cross(GetY(mat), b));
@@ -492,7 +494,7 @@ template <typename T>
492494
PLAYRHO_CONSTEXPR inline T Solve22(const Mat33& mat, const T b) noexcept
493495
{
494496
const auto cp = GetX(GetX(mat)) * GetY(GetY(mat)) - GetX(GetY(mat)) * GetY(GetX(mat));
495-
const auto det = (cp != 0)? 1 / cp: cp;
497+
const auto det = (cp != 0)? Real{1} / cp: cp;
496498
const auto x = det * (GetY(GetY(mat)) * GetX(b) - GetX(GetY(mat)) * GetY(b));
497499
const auto y = det * (GetX(GetX(mat)) * GetY(b) - GetY(GetX(mat)) * GetX(b));
498500
return T{x, y};
@@ -623,7 +625,7 @@ inline Real Normalize(Vec2& vector)
623625
const auto length = GetMagnitude(vector);
624626
if (!AlmostZero(length))
625627
{
626-
const auto invLength = 1 / length;
628+
const auto invLength = Real{1} / length;
627629
vector[0] *= invLength;
628630
vector[1] *= invLength;
629631
return length;
@@ -734,7 +736,8 @@ PLAYRHO_CONSTEXPR inline Vector2<T> operator* (const UnitVec u, const T s) noexc
734736
/// @brief Division operator.
735737
PLAYRHO_CONSTEXPR inline Vec2 operator/ (const UnitVec u, const UnitVec::value_type s) noexcept
736738
{
737-
return Vec2{GetX(u) / s, GetY(u) / s};
739+
const auto inverseS = Real{1} / s;
740+
return Vec2{GetX(u) * inverseS, GetY(u) * inverseS};
738741
}
739742

740743
/// @brief Rotates a vector by a given angle.

0 commit comments

Comments
 (0)