Skip to content

Commit

Permalink
Various changes...
Browse files Browse the repository at this point in the history
- Removes GetInvalid.
- Enables compiling w/ realnumb external fixed point support.
- Updates AlmostEqual to be more generic.
- Updates AlmostEqual to use nextafter instead of epsilon.
- Explicitly states in code more of the requirements on Real.

Tested with:
CC=/opt/homebrew/opt/llvm/bin/clang \
CXX=/opt/homebrew/opt/llvm/bin/clang++ \
LDFLAGS='-L/opt/homebrew/opt/llvm/lib/c++' \
cmake -S PlayRho -B PlayRhoBuild \
	-DPLAYRHO_BUILD_UNIT_TESTS=ON \
	-DPLAYRHO_BUILD_BENCHMARK=ON \
	-DPLAYRHO_BUILD_TESTBED=ON \
	-DPLAYRHO_BUILD_HELLOWORLD=ON \
	-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
	-DPLAYRHO_BUILD_DOC=ON \
	-DPLAYRHO_ENABLE_BOOST_UNITS=ON \
	-DPLAYRHO_REAL_TYPE='::realnumb::fixed64' \
	-DPLAYRHO_REAL_INCLUDE='#include <realnumb/fixed.hpp>;#include <realnumb/fixed_math.hpp>;#include <realnumb/fixed_limits.hpp>' \
	-DPLAYRHO_REAL_FETCH=realnumb \
	-DPLAYRHO_REAL_GIT_REPOSITORY=https://github.com/louis-langholtz/realnumb.git \
	-DPLAYRHO_REAL_GIT_TAG=main  \
	-DPLAYRHO_INSTALL=ON \
	-DREALNUMB_INSTALL=ON
  • Loading branch information
louis-langholtz committed Oct 24, 2023
1 parent 2b4a299 commit 7d3e379
Show file tree
Hide file tree
Showing 45 changed files with 253 additions and 445 deletions.
17 changes: 11 additions & 6 deletions Benchmark/BenchmarkMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

#include <benchmark/benchmark.h>

#include <tuple>
#include <utility>
#include <cstdlib>
Expand Down Expand Up @@ -85,6 +86,10 @@
#include <box2d/box2d.h>
#endif // BENCHMARK_BOX2D

using playrho::isnormal;
using playrho::sqrt;
using playrho::hypot;

template <typename T>
static T Rand(T lo, T hi)
{
Expand Down Expand Up @@ -1077,8 +1082,8 @@ static void UnitVectorFromVector(benchmark::State& state)
static playrho::Vec2 GetUnitVec1(playrho::Vec2 vec, playrho::Vec2 fallback)
{
const auto magSquared = playrho::Square(vec[0]) + playrho::Square(vec[1]);
if (playrho::isnormal(magSquared)) {
const auto mag = playrho::sqrt(magSquared);
if (isnormal(magSquared)) {
const auto mag = sqrt(magSquared);
return playrho::Vec2{vec[0] / mag, vec[1] / mag};
}
return fallback;
Expand All @@ -1087,12 +1092,12 @@ static playrho::Vec2 GetUnitVec1(playrho::Vec2 vec, playrho::Vec2 fallback)
static playrho::Vec2 GetUnitVec2(playrho::Vec2 vec, playrho::Vec2 fallback)
{
const auto magSquared = playrho::Square(vec[0]) + playrho::Square(vec[1]);
if (playrho::isnormal(magSquared)) {
const auto mag = playrho::sqrt(magSquared);
if (isnormal(magSquared)) {
const auto mag = sqrt(magSquared);
return playrho::Vec2{vec[0] / mag, vec[1] / mag};
}
const auto mag = playrho::hypot(vec[0], vec[1]);
if (playrho::isnormal(mag)) {
const auto mag = hypot(vec[0], vec[1]);
if (isnormal(mag)) {
return playrho::Vec2{vec[0] / mag, vec[1] / mag};
}
return fallback;
Expand Down
10 changes: 1 addition & 9 deletions Library/include/playrho/BodyID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,12 @@ using BodyID = detail::IndexingNamedType<BodyCounter, struct BodyIdentifier>;
/// @see BodyID.
constexpr auto InvalidBodyID = static_cast<BodyID>(static_cast<BodyID::underlying_type>(-1));

/// @brief Gets an invalid value for the BodyID type.
/// @see BodyID.
template <>
constexpr BodyID GetInvalid() noexcept
{
return InvalidBodyID;
}

/// @brief Determines if the given value is valid.
/// @see BodyID.
template <>
constexpr bool IsValid(const BodyID& value) noexcept
{
return value != GetInvalid<BodyID>();
return value != InvalidBodyID;
}

} // namespace playrho
Expand Down
9 changes: 1 addition & 8 deletions Library/include/playrho/ContactID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,11 @@ using ContactID = detail::IndexingNamedType<ContactCounter, struct ContactIdenti
constexpr auto InvalidContactID =
static_cast<ContactID>(static_cast<ContactID::underlying_type>(-1));

/// @brief Gets an invalid value for the ContactID type.
template <>
constexpr ContactID GetInvalid() noexcept
{
return InvalidContactID;
}

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const ContactID& value) noexcept
{
return value != GetInvalid<ContactID>();
return value != InvalidContactID;
}

} // namespace playrho
Expand Down
9 changes: 1 addition & 8 deletions Library/include/playrho/JointID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,11 @@ using JointID = detail::IndexingNamedType<JointCounter, struct JointIdentifier>;
/// @brief Invalid joint ID value.
constexpr auto InvalidJointID = static_cast<JointID>(static_cast<JointID::underlying_type>(-1));

/// @brief Gets an invalid value for the JointID type.
template <>
constexpr JointID GetInvalid() noexcept
{
return InvalidJointID;
}

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const JointID& value) noexcept
{
return value != GetInvalid<JointID>();
return value != InvalidJointID;
}

} // namespace playrho
Expand Down
19 changes: 15 additions & 4 deletions Library/include/playrho/Math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
/// @brief Conventional and custom math related code.

#include <cmath>
#include <limits> // for std::numeric_limits
#include <numeric>
#include <type_traits> // for std::decay_t
#include <vector>
Expand Down Expand Up @@ -171,18 +172,28 @@ constexpr auto AlmostZero(const T& value) -> decltype(abs(value) < std::numeric_
}

/// @brief Determines whether the given two values are "almost equal".
/// @note A default ULP of 4 is what googletest uses in its @c kMaxUlps setting for its
/// @c AlmostEquals function found in its @c gtest/internal/gtest-internal.h file.
/// @see https://github.com/google/googletest/blob/main/googletest/include/gtest/internal/gtest-internal.h
template <typename T>
constexpr auto AlmostEqual(const T& x, const T& y, int ulp = 2)
-> std::enable_if_t<std::is_floating_point_v<T>, bool>
constexpr auto AlmostEqual(T a, T b, int ulp = 4)
-> std::enable_if_t<IsArithmeticV<T>, bool>
{
#if 0
// From http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon :
// "the machine epsilon has to be scaled to the magnitude of the values used
// and multiplied by the desired precision in ULPs (units in the last place)
// unless the result is subnormal".
// Where "subnormal" means almost zero.
//
return (abs(x - y) < (std::numeric_limits<T>::epsilon() * abs(x + y) * static_cast<T>(ulp))) ||
AlmostZero(x - y);
return (abs(a - b) < (std::numeric_limits<T>::epsilon() * abs(a + b) * static_cast<T>(ulp))) ||
AlmostZero(a - b);
#else
for (; (a != b) && (ulp > 0); --ulp) {
a = nextafter(a, b);
}
return a == b;
#endif
}

/// @brief Constant expression enhanced truncate function.
Expand Down
7 changes: 0 additions & 7 deletions Library/include/playrho/Matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,6 @@ constexpr bool IsValid(const Mat22& value) noexcept
return IsValid(get<0>(value)) && IsValid(get<1>(value));
}

/// @brief Gets an invalid value for a <code>Mat22</code>.
template <>
constexpr Mat22 GetInvalid() noexcept
{
return Mat22{GetInvalid<Vec2>(), GetInvalid<Vec2>()};
}

} // namespace playrho

#endif // PLAYRHO_MATRIX_HPP
2 changes: 2 additions & 0 deletions Library/include/playrho/Positive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
/// @file
/// @brief Definition of the @c Positive value checked types and related code.

#include <limits> // for std::numeric_limits

#include <playrho/detail/Checked.hpp>
#include <playrho/detail/PositiveChecker.hpp>

Expand Down
8 changes: 8 additions & 0 deletions Library/include/playrho/Real.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
* @brief Real number definition file.
*/

#include <limits> // for std::numeric_limits

#include <playrho/Templates.hpp> // for IsArithmeticV

// Any header(s) for a user defined arithmetic type for Real go here...
Expand Down Expand Up @@ -64,6 +66,12 @@ using Real = float;

static_assert(IsArithmeticV<Real>);

// Requirements on Real per std::numeric_limits...
static_assert(!std::numeric_limits<Real>::is_integer);
static_assert(std::numeric_limits<Real>::is_signed);
static_assert(std::numeric_limits<Real>::has_infinity);
static_assert(std::numeric_limits<Real>::has_signaling_NaN || std::numeric_limits<Real>::has_quiet_NaN);

} // namespace playrho

#endif // PLAYRHO_REAL_HPP
8 changes: 8 additions & 0 deletions Library/include/playrho/Real.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
* @note This file was generated from the Real.hpp.in file.
*/

#include <limits> // for std::numeric_limits

#include <playrho/Templates.hpp> // for IsArithmeticV

// Any header(s) for a user defined arithmetic type for Real go here...
Expand Down Expand Up @@ -66,6 +68,12 @@ using Real = @PLAYRHO_REAL_TYPE@;

static_assert(IsArithmeticV<Real>);

// Requirements on Real per std::numeric_limits...
static_assert(!std::numeric_limits<Real>::is_integer);
static_assert(std::numeric_limits<Real>::is_signed);
static_assert(std::numeric_limits<Real>::has_infinity);
static_assert(std::numeric_limits<Real>::has_signaling_NaN || std::numeric_limits<Real>::has_quiet_NaN);

} // namespace playrho

#endif // PLAYRHO_REAL_HPP
10 changes: 9 additions & 1 deletion Library/include/playrho/Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@
#ifndef PLAYRHO_SETTINGS_HPP
#define PLAYRHO_SETTINGS_HPP

#include <algorithm>
#include <cstddef>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <cstdint>
#include <algorithm>
#include <limits> // for std::numeric_limits

#include <playrho/RealConstants.hpp>
#include <playrho/Templates.hpp>
Expand Down Expand Up @@ -228,6 +229,13 @@ constexpr auto DefaultAngularSleepTolerance = Real((Pi * 2) / 180) * RadianPerSe
/// biased normal collisions.
constexpr auto DefaultCirclesRatio = Real(10);

/// @brief Invalid value of the template's instantiated numeric type
template <class T, std::enable_if_t<
std::numeric_limits<T>::has_signaling_NaN || std::numeric_limits<T>::has_quiet_NaN, int> = 0>
constexpr auto Invalid = std::numeric_limits<T>::has_signaling_NaN
? std::numeric_limits<T>::signaling_NaN()
: std::numeric_limits<T>::quiet_NaN();

} // namespace playrho

#endif // PLAYRHO_SETTINGS_HPP
10 changes: 9 additions & 1 deletion Library/include/playrho/Settings.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@
#ifndef PLAYRHO_SETTINGS_HPP
#define PLAYRHO_SETTINGS_HPP

#include <algorithm>
#include <cstddef>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <cstdint>
#include <algorithm>
#include <limits> // for std::numeric_limits

#include <playrho/RealConstants.hpp>
#include <playrho/Templates.hpp>
Expand Down Expand Up @@ -229,6 +230,13 @@ constexpr auto DefaultAngularSleepTolerance = Real((Pi * 2) / 180) * RadianPerSe
/// biased normal collisions.
constexpr auto DefaultCirclesRatio = Real(10);

/// @brief Invalid value of the template's instantiated numeric type
template <class T, std::enable_if_t<
std::numeric_limits<T>::has_signaling_NaN || std::numeric_limits<T>::has_quiet_NaN, int> = 0>
constexpr auto Invalid = std::numeric_limits<T>::has_signaling_NaN
? std::numeric_limits<T>::signaling_NaN()
: std::numeric_limits<T>::quiet_NaN();

} // namespace playrho

#endif // PLAYRHO_SETTINGS_HPP
9 changes: 1 addition & 8 deletions Library/include/playrho/ShapeID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,11 @@ using ShapeID = detail::IndexingNamedType<ShapeCounter, struct ShapeIdentifier>;
/// @brief Invalid fixture ID value.
constexpr auto InvalidShapeID = static_cast<ShapeID>(static_cast<ShapeID::underlying_type>(-1));

/// @brief Gets an invalid value for the ShapeID type.
template <>
constexpr ShapeID GetInvalid() noexcept
{
return InvalidShapeID;
}

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const ShapeID& value) noexcept
{
return value != GetInvalid<ShapeID>();
return value != InvalidShapeID;
}

} // namespace playrho
Expand Down
43 changes: 1 addition & 42 deletions Library/include/playrho/Templates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,7 @@

namespace playrho {

/// @brief Gets an invalid value for the type.
/// @tparam T Type to get an invalid value for.
/// @note Specialize this function for the types which have an invalid value concept.
/// @see IsValid.
template <typename T>
constexpr T GetInvalid() noexcept
{
static_assert(sizeof(T) == 0, "No available specialization");
}

/// @brief Determines if the given value is valid.
/// @see GetInvalid.
template <typename T>
constexpr bool IsValid(const T& value) noexcept
{
Expand All @@ -56,43 +45,13 @@ constexpr bool IsValid(const T& value) noexcept
return value == value; // NOLINT(misc-redundant-expression)
}

// GetInvalid template specializations.

/// @brief Gets an invalid value for the float type.
template <>
constexpr float GetInvalid() noexcept
{
return std::numeric_limits<float>::signaling_NaN();
}

/// @brief Gets an invalid value for the double type.
template <>
constexpr double GetInvalid() noexcept
{
return std::numeric_limits<double>::signaling_NaN();
}

/// @brief Gets an invalid value for the long double type.
template <>
constexpr long double GetInvalid() noexcept
{
return std::numeric_limits<long double>::signaling_NaN();
}

/// @brief Gets an invalid value for the std::size_t type.
template <>
constexpr std::size_t GetInvalid() noexcept
{
return static_cast<std::size_t>(-1);
}

// IsValid template specializations.

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const std::size_t& value) noexcept
{
return value != GetInvalid<std::size_t>();
return value != static_cast<std::size_t>(-1);
}

// Other templates.
Expand Down
Loading

0 comments on commit 7d3e379

Please sign in to comment.