Skip to content

Commit

Permalink
update floating point context docs
Browse files Browse the repository at this point in the history
Also make the tolerance values non-atomic, since there is no real benefit anyway.
  • Loading branch information
KRM7 committed Sep 24, 2023
1 parent eb9f50b commit c9f0812
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 16 deletions.
5 changes: 5 additions & 0 deletions docs/miscellaneous.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ Exact comparisons can be used by setting both tolerance values to 0.
math::ScopedTolerances _(0.0, 0.0);
```

Note that the tolerance values are global variables which will be used for
the comparisons on every thread, so they should not be modified on multiple
threads concurrently. This means that instances of the `ScopedTolerances`
class should not exist on multiple threads at once.


## Random number generation

Expand Down
2 changes: 1 addition & 1 deletion src/core/ga_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace gapp
*
* The following gene types are reserved for the GAs already implemented in the library
* and can't be used as the gene type of new encodings:
* - std::int8_t
* - std::uint8_t
* - std::size_t
* - int
* - double
Expand Down
30 changes: 16 additions & 14 deletions src/utility/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#ifndef GA_UTILITY_MATH_HPP
#define GA_UTILITY_MATH_HPP

#include "bounded_value.hpp"
#include "utility.hpp"
#include <vector>
#include <span>
#include <atomic>
#include <compare>
#include <concepts>
#include <limits>
Expand Down Expand Up @@ -44,15 +44,15 @@ namespace gapp::math

/** @returns The current absolute tolerance used for floating-point comparisons. */
template<std::floating_point T = double>
static T abs() noexcept { return T(absolute_tolerance.load(std::memory_order_acquire)); }
static T abs() noexcept { return T(absolute_tolerance); }

/** @returns The current relative tolerance used for floating-point comparisons around @p at. */
template<std::floating_point T = double>
static T rel(T at) noexcept { return relative_tolerance.load(std::memory_order_acquire) * at; }
static T rel(T at) noexcept { return relative_tolerance * at; }

private:
GAPP_API inline constinit static std::atomic<double> absolute_tolerance = 1E-12;
GAPP_API inline constinit static std::atomic<double> relative_tolerance = 10 * eps<double>;
GAPP_API inline constinit static double absolute_tolerance = 1E-12;
GAPP_API inline constinit static double relative_tolerance = 10 * eps<double>;

friend class ScopedTolerances;
};
Expand All @@ -65,6 +65,11 @@ namespace gapp::math
* values specified by the parameters of the constructor, and these new tolerance
* values will be used for floating-point comparisons until the instance of the class is destroyed.
* The tolerances are reset to their old values when the instance is destroyed.
*
* @warning
* Creating an instance of this class modifies the global floating point tolerance
* values. This means that this class shouldn't be instantiated on multiple threads
* at once.
*/
class [[nodiscard]] ScopedTolerances
{
Expand All @@ -76,19 +81,16 @@ namespace gapp::math
* @param abs The absolute tolerance value that will be used for the comparisons. Can't be negative.
* @param rel The relative tolerance value around 1.0 that will be used for the comparisons. Can't be negative.
*/
ScopedTolerances(double abs, double rel) noexcept :
old_absolute_tolerance(Tolerances::absolute_tolerance.exchange(abs, std::memory_order_acq_rel)),
old_relative_tolerance(Tolerances::relative_tolerance.exchange(rel, std::memory_order_acq_rel))
{
GAPP_ASSERT(abs >= 0.0, "The absolute tolerance value can't be negative.");
GAPP_ASSERT(rel >= 0.0, "The relative tolerance value can't be negative.");
}
ScopedTolerances(NonNegative<double> abs, NonNegative<double> rel) noexcept :
old_absolute_tolerance(std::exchange(Tolerances::absolute_tolerance, abs)),
old_relative_tolerance(std::exchange(Tolerances::relative_tolerance, rel))
{}

/** Reset the tolerances to their previous values. */
~ScopedTolerances() noexcept
{
Tolerances::absolute_tolerance.store(old_absolute_tolerance, std::memory_order_release);
Tolerances::relative_tolerance.store(old_relative_tolerance, std::memory_order_release);
Tolerances::absolute_tolerance = old_absolute_tolerance;
Tolerances::relative_tolerance = old_relative_tolerance;
}

ScopedTolerances(const ScopedTolerances&) = delete;
Expand Down
1 change: 0 additions & 1 deletion test/unit/pareto_sets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ TEST_CASE("merge_pareto_sets", "[pareto_front]")
{ 3.0, 8.0 }, //
{ 2.0, 11.0 }, //
{ 1.0, 12.0 }, //
{ -1.0, 10.0 },
};

FitnessMatrix front2 = {
Expand Down

0 comments on commit c9f0812

Please sign in to comment.