mimic++ v6
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"
13
14#include <algorithm>
15#include <cmath>
16#include <concepts>
17#include <limits>
18#include <stdexcept>
19#include <tuple>
20
22{
28
32 [[nodiscard]]
33 consteval auto NaN() noexcept
34 {
35 return PredicateMatcher{
36 []<std::floating_point T>(const T target) noexcept {
37 return std::isnan(target);
38 },
39 "is not a number (NaN)",
40 "is a number"};
41 }
42
43 namespace detail
44 {
45 void check_fp_value(const std::floating_point auto value)
46 {
47 if (std::isnan(value)
48 || std::isinf(value))
49 {
50 throw std::runtime_error{"Value must be not NaN and not infinity."};
51 }
52 }
53
54 void check_fp_epsilon(const std::floating_point auto epsilon)
55 {
56 if (std::isnan(epsilon)
57 || std::isinf(epsilon)
58 || epsilon <= 0.)
59 {
60 throw std::runtime_error{"Epsilon must be not NaN, not infinity and not less or equal 0."};
61 }
62 }
63 }
64
73 [[nodiscard]]
74 constexpr auto approx_abs(
75 const std::floating_point auto value,
76 const std::floating_point auto epsilon)
77 {
78 detail::check_fp_value(value);
79 detail::check_fp_epsilon(epsilon);
80
81 return PredicateMatcher{
82 [](const std::floating_point auto target, const auto val, const auto eps) {
83 return std::abs(target - val) <= eps;
84 },
85 "is approximately {} +- {}",
86 "is not approximately {} +- {}",
87 std::make_tuple(value, epsilon)};
88 }
89
108 [[nodiscard]]
109 constexpr auto approx_rel(
110 const std::floating_point auto value,
111 const std::floating_point auto relEpsilon)
112 {
113 detail::check_fp_value(value);
114 detail::check_fp_epsilon(relEpsilon);
115
116 return PredicateMatcher{
117 [](const std::floating_point auto target, const auto val, const auto rel) {
118 // when target equals +-infinity, that leads to an inf epsilon, which is not very useful
119 if (!std::isinf(target))
120 {
121 const auto absDiff = std::abs(target - val);
122 const auto scaledEpsilon = rel * std::max(std::abs(target), std::abs(val));
123 return absDiff <= scaledEpsilon;
124 }
125
126 return false;
127 },
128 "is approximately {} +- ({} * max(|lhs|, |rhs|))",
129 "is not approximately {} +- ({} * max(|lhs|, |rhs|))",
130 std::make_tuple(value, relEpsilon)};
131 }
132
145 template <std::floating_point Float>
146 [[nodiscard]]
147 constexpr auto approx_rel(const Float value)
148 {
149 return matches::approx_rel(
150 value,
151 std::numeric_limits<Float>::epsilon() * Float{100});
152 }
153
157}
158
159#endif
Generic matcher and the basic building block of most of the built-in matchers.
Definition GeneralMatchers.hpp:68
consteval auto NaN() noexcept
Tests, whether the floating-point target is NaN.
Definition FloatingPointMatchers.hpp:33
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:109
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:74
Definition FloatingPointMatchers.hpp:22