mimic++ v9.2.1
Loading...
Searching...
No Matches
FloatingPointMatchers.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_MATCHERS_FLOATING_POINT_MATCHERS_HPP
7#define MIMICPP_MATCHERS_FLOATING_POINT_MATCHERS_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
14
15#ifndef MIMICPP_DETAIL_IS_MODULE
16 #include <algorithm>
17 #include <cmath>
18 #include <concepts>
19 #include <limits>
20 #include <stdexcept>
21 #include <tuple>
22#endif
23
25{
31
35 [[nodiscard]]
36 consteval auto NaN() noexcept
37 {
38 return PredicateMatcher{
39 []<std::floating_point T>(const T target) noexcept {
40 return std::isnan(target);
41 },
42 "is not a number (NaN)",
43 "is a number"};
44 }
45
46 namespace detail
47 {
48 void check_fp_value(const std::floating_point auto value)
49 {
50 if (std::isnan(value)
51 || std::isinf(value))
52 {
53 throw std::runtime_error{"Value must be not NaN and not infinity."};
54 }
55 }
56
57 void check_fp_epsilon(const std::floating_point auto epsilon)
58 {
59 if (std::isnan(epsilon)
60 || std::isinf(epsilon)
61 || epsilon <= 0.)
62 {
63 throw std::runtime_error{"Epsilon must be not NaN, not infinity and not less or equal 0."};
64 }
65 }
66 }
67
76 [[nodiscard]]
77 constexpr auto approx_abs(
78 const std::floating_point auto value,
79 const std::floating_point auto epsilon)
80 {
81 detail::check_fp_value(value);
82 detail::check_fp_epsilon(epsilon);
83
84 return PredicateMatcher{
85 [](const std::floating_point auto target, const auto val, const auto eps) {
86 return std::abs(target - val) <= eps;
87 },
88 "is approximately {} +- {}",
89 "is not approximately {} +- {}",
90 std::make_tuple(value, epsilon)};
91 }
92
111 [[nodiscard]]
112 constexpr auto approx_rel(
113 const std::floating_point auto value,
114 const std::floating_point auto relEpsilon)
115 {
116 detail::check_fp_value(value);
117 detail::check_fp_epsilon(relEpsilon);
118
119 return PredicateMatcher{
120 [](const std::floating_point auto target, const auto val, const auto rel) {
121 // when target equals +-infinity, that leads to an inf epsilon, which is not very useful
122 if (!std::isinf(target))
123 {
124 const auto absDiff = std::abs(target - val);
125 const auto scaledEpsilon = rel * std::max(std::abs(target), std::abs(val));
126 return absDiff <= scaledEpsilon;
127 }
128
129 return false;
130 },
131 "is approximately {} +- ({} * max(|lhs|, |rhs|))",
132 "is not approximately {} +- ({} * max(|lhs|, |rhs|))",
133 std::make_tuple(value, relEpsilon)};
134 }
135
148 template <std::floating_point Float>
149 [[nodiscard]]
150 constexpr auto approx_rel(const Float value)
151 {
152 return matches::approx_rel(
153 value,
154 std::numeric_limits<Float>::epsilon() * Float{100});
155 }
156
160}
161
162#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Generic matcher and the basic building block of most of the built-in matchers.
Definition GeneralMatchers.hpp:75
consteval auto NaN() noexcept
Tests, whether the floating-point target is NaN.
Definition FloatingPointMatchers.hpp:36
constexpr auto approx_rel(const std::floating_point auto value, const std::floating_point auto relEpsilon)
Tests, whether the floating-point target is approximately equal to value.
Definition FloatingPointMatchers.hpp:112
constexpr auto approx_abs(const std::floating_point auto value, const std::floating_point auto epsilon)
Tests, whether the floating-point target is approximately equal to value.
Definition FloatingPointMatchers.hpp:77
Definition FloatingPointMatchers.hpp:25