@micro-os-plus/micro-test-plus 2.1.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +349 -72
- package/CMakeLists.txt +15 -26
- package/LICENSE-Boost +23 -0
- package/README.md +1036 -256
- package/include/micro-os-plus/detail.h +733 -0
- package/include/micro-os-plus/inlines.h +161 -0
- package/include/micro-os-plus/literals.h +285 -0
- package/include/micro-os-plus/math.h +205 -0
- package/include/micro-os-plus/micro-test-plus.h +490 -103
- package/include/micro-os-plus/reflection.h +134 -0
- package/include/micro-os-plus/test-reporter-inlines.h +231 -0
- package/include/micro-os-plus/test-reporter.h +347 -0
- package/include/micro-os-plus/test-runner.h +132 -0
- package/include/micro-os-plus/test-suite.h +241 -0
- package/include/micro-os-plus/type-traits.h +346 -0
- package/meson.build +35 -11
- package/package.json +243 -147
- package/src/micro-test-plus.cpp +105 -188
- package/src/test-reporter.cpp +423 -0
- package/src/test-runner.cpp +186 -0
- package/src/test-suite.cpp +133 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the µOS++ distribution.
|
|
3
|
+
* (https://github.com/micro-os-plus/)
|
|
4
|
+
* Copyright (c) 2021 Liviu Ionescu.
|
|
5
|
+
*
|
|
6
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
7
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
8
|
+
*
|
|
9
|
+
* If a copy of the license was not distributed with this file, it can
|
|
10
|
+
* be obtained from <https://opensource.org/licenses/MIT/>.
|
|
11
|
+
*
|
|
12
|
+
* Major parts of the code are inspired from v1.1.8 of the Boost UT project,
|
|
13
|
+
* released under the terms of the Boost Version 1.0 Software License,
|
|
14
|
+
* which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#ifndef MICRO_TEST_PLUS_INLINES_H_
|
|
18
|
+
#define MICRO_TEST_PLUS_INLINES_H_
|
|
19
|
+
|
|
20
|
+
// ----------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
#ifdef __cplusplus
|
|
23
|
+
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
#if defined(__GNUC__)
|
|
27
|
+
#pragma GCC diagnostic push
|
|
28
|
+
#pragma GCC diagnostic ignored "-Waggregate-return"
|
|
29
|
+
#pragma GCC diagnostic ignored "-Wpadded"
|
|
30
|
+
#if defined(__clang__)
|
|
31
|
+
#pragma clang diagnostic ignored "-Wc++98-compat"
|
|
32
|
+
#pragma clang diagnostic ignored "-Wc++98-c++11-c++14-c++17-compat-pedantic"
|
|
33
|
+
#endif
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
namespace micro_os_plus::micro_test_plus
|
|
37
|
+
{
|
|
38
|
+
// --------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
template <typename Callable_T, typename... Args_T>
|
|
41
|
+
test_suite::test_suite (const char* name, Callable_T&& callable,
|
|
42
|
+
Args_T&&... arguments)
|
|
43
|
+
: test_suite_base{ name }, callable_{ std::bind (callable,
|
|
44
|
+
arguments...) }
|
|
45
|
+
{
|
|
46
|
+
#if defined(MICRO_TEST_PLUS_TRACE)
|
|
47
|
+
printf ("%s\n", __PRETTY_FUNCTION__);
|
|
48
|
+
#endif // MICRO_TEST_PLUS_TRACE
|
|
49
|
+
|
|
50
|
+
runner.register_test_suite (this);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// --------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
template <typename Callable_T, typename... Args_T>
|
|
56
|
+
void
|
|
57
|
+
test_case (const char* name, Callable_T&& func, Args_T&&... arguments)
|
|
58
|
+
{
|
|
59
|
+
#if 0 // defined(MICRO_TEST_PLUS_TRACE)
|
|
60
|
+
printf ("%s\n", __PRETTY_FUNCTION__);
|
|
61
|
+
#endif // MICRO_TEST_PLUS_TRACE
|
|
62
|
+
|
|
63
|
+
current_test_suite->begin_test_case (name);
|
|
64
|
+
std::invoke (std::forward<Callable_T> (func),
|
|
65
|
+
std::forward<Args_T> (arguments)...);
|
|
66
|
+
current_test_suite->end_test_case ();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// --------------------------------------------------------------------------
|
|
70
|
+
namespace detail
|
|
71
|
+
{
|
|
72
|
+
// ------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
template <class T>
|
|
75
|
+
auto&
|
|
76
|
+
deferred_reporter_base::operator<< (const T& msg)
|
|
77
|
+
{
|
|
78
|
+
if constexpr (std::is_arithmetic_v<T>)
|
|
79
|
+
{
|
|
80
|
+
message_.append (std::to_string (msg));
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
{
|
|
84
|
+
message_.append (msg);
|
|
85
|
+
}
|
|
86
|
+
return *this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
template <class Expr_T>
|
|
92
|
+
constexpr deferred_reporter<Expr_T>::deferred_reporter (
|
|
93
|
+
const Expr_T& expr, bool abort,
|
|
94
|
+
const reflection::source_location& location)
|
|
95
|
+
: deferred_reporter_base{ static_cast<bool> (expr), location }, expr_{
|
|
96
|
+
expr
|
|
97
|
+
}
|
|
98
|
+
{
|
|
99
|
+
#if 0 // defined(MICRO_TEST_PLUS_TRACE)
|
|
100
|
+
printf ("%s\n", __PRETTY_FUNCTION__);
|
|
101
|
+
#endif // MICRO_TEST_PLUS_TRACE
|
|
102
|
+
abort_ = abort;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
template <class Expr_T>
|
|
106
|
+
deferred_reporter<Expr_T>::~deferred_reporter ()
|
|
107
|
+
{
|
|
108
|
+
if (value_)
|
|
109
|
+
{
|
|
110
|
+
reporter.pass (expr_, message_);
|
|
111
|
+
}
|
|
112
|
+
else
|
|
113
|
+
{
|
|
114
|
+
reporter.fail (expr_, abort_, message_, location_);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ------------------------------------------------------------------------
|
|
119
|
+
} // namespace detail
|
|
120
|
+
|
|
121
|
+
// --------------------------------------------------------------------------
|
|
122
|
+
namespace utility
|
|
123
|
+
{
|
|
124
|
+
template <class T = std::string_view, class Delim_T>
|
|
125
|
+
[[nodiscard]] auto
|
|
126
|
+
split (T input, Delim_T delim) -> std::vector<T>
|
|
127
|
+
{
|
|
128
|
+
std::vector<T> output{};
|
|
129
|
+
std::size_t first{};
|
|
130
|
+
while (first < std::size (input))
|
|
131
|
+
{
|
|
132
|
+
const auto second = input.find_first_of (delim, first);
|
|
133
|
+
if (first != second)
|
|
134
|
+
{
|
|
135
|
+
output.emplace_back (input.substr (first, second - first));
|
|
136
|
+
}
|
|
137
|
+
if (second == T::npos)
|
|
138
|
+
{
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
first = second + 1;
|
|
142
|
+
}
|
|
143
|
+
return output;
|
|
144
|
+
}
|
|
145
|
+
} // namespace utility
|
|
146
|
+
|
|
147
|
+
} // namespace micro_os_plus::micro_test_plus
|
|
148
|
+
|
|
149
|
+
#if defined(__GNUC__)
|
|
150
|
+
#pragma GCC diagnostic pop
|
|
151
|
+
#endif
|
|
152
|
+
|
|
153
|
+
// ----------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
#endif // __cplusplus
|
|
156
|
+
|
|
157
|
+
// ----------------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
#endif // MICRO_TEST_PLUS_INLINES_H_
|
|
160
|
+
|
|
161
|
+
// ----------------------------------------------------------------------------
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the µOS++ distribution.
|
|
3
|
+
* (https://github.com/micro-os-plus/)
|
|
4
|
+
* Copyright (c) 2021 Liviu Ionescu.
|
|
5
|
+
*
|
|
6
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
7
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
8
|
+
*
|
|
9
|
+
* If a copy of the license was not distributed with this file, it can
|
|
10
|
+
* be obtained from <https://opensource.org/licenses/MIT/>.
|
|
11
|
+
*
|
|
12
|
+
* Major parts of the code are inspired from v1.1.8 of the Boost UT project,
|
|
13
|
+
* released under the terms of the Boost Version 1.0 Software License,
|
|
14
|
+
* which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#ifndef MICRO_TEST_PLUS_LITERALS_H_
|
|
18
|
+
#define MICRO_TEST_PLUS_LITERALS_H_
|
|
19
|
+
|
|
20
|
+
// ----------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
#ifdef __cplusplus
|
|
23
|
+
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
#include "type-traits.h"
|
|
27
|
+
#include "math.h"
|
|
28
|
+
|
|
29
|
+
// ----------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
#if defined(__GNUC__)
|
|
32
|
+
#pragma GCC diagnostic push
|
|
33
|
+
#pragma GCC diagnostic ignored "-Waggregate-return"
|
|
34
|
+
#if defined(__clang__)
|
|
35
|
+
#pragma clang diagnostic ignored "-Wc++98-compat"
|
|
36
|
+
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
|
37
|
+
#endif
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
namespace micro_os_plus::micro_test_plus
|
|
41
|
+
{
|
|
42
|
+
// --------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @brief User Defined Literals (UDL). Use them to suffix
|
|
46
|
+
* constants and obtain specific explicit types, like `1_i`.
|
|
47
|
+
*/
|
|
48
|
+
namespace literals
|
|
49
|
+
{
|
|
50
|
+
template <char... Cs>
|
|
51
|
+
[[nodiscard]] constexpr auto operator""_i ()
|
|
52
|
+
{
|
|
53
|
+
return type_traits::integral_constant<math::num<int, Cs...> ()>{};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
template <char... Cs>
|
|
57
|
+
[[nodiscard]] constexpr auto operator""_s ()
|
|
58
|
+
{
|
|
59
|
+
return type_traits::integral_constant<math::num<short, Cs...> ()>{};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
template <char... Cs>
|
|
63
|
+
[[nodiscard]] constexpr auto operator""_c ()
|
|
64
|
+
{
|
|
65
|
+
return type_traits::integral_constant<math::num<char, Cs...> ()>{};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
template <char... Cs>
|
|
69
|
+
[[nodiscard]] constexpr auto operator""_sc ()
|
|
70
|
+
{
|
|
71
|
+
return type_traits::integral_constant<
|
|
72
|
+
math::num<signed char, Cs...> ()>{};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
template <char... Cs>
|
|
76
|
+
[[nodiscard]] constexpr auto operator""_l ()
|
|
77
|
+
{
|
|
78
|
+
return type_traits::integral_constant<math::num<long, Cs...> ()>{};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
template <char... Cs>
|
|
82
|
+
[[nodiscard]] constexpr auto operator""_ll ()
|
|
83
|
+
{
|
|
84
|
+
return type_traits::integral_constant<math::num<long long, Cs...> ()>{};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
template <char... Cs>
|
|
88
|
+
[[nodiscard]] constexpr auto operator""_u ()
|
|
89
|
+
{
|
|
90
|
+
return type_traits::integral_constant<math::num<unsigned, Cs...> ()>{};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
template <char... Cs>
|
|
94
|
+
[[nodiscard]] constexpr auto operator""_uc ()
|
|
95
|
+
{
|
|
96
|
+
return type_traits::integral_constant<
|
|
97
|
+
math::num<unsigned char, Cs...> ()>{};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
template <char... Cs>
|
|
101
|
+
[[nodiscard]] constexpr auto operator""_us ()
|
|
102
|
+
{
|
|
103
|
+
return type_traits::integral_constant<
|
|
104
|
+
math::num<unsigned short, Cs...> ()>{};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
template <char... Cs>
|
|
108
|
+
[[nodiscard]] constexpr auto operator""_ul ()
|
|
109
|
+
{
|
|
110
|
+
return type_traits::integral_constant<
|
|
111
|
+
math::num<unsigned long, Cs...> ()>{};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
template <char... Cs>
|
|
115
|
+
[[nodiscard]] constexpr auto operator""_ull ()
|
|
116
|
+
{
|
|
117
|
+
return type_traits::integral_constant<
|
|
118
|
+
math::num<unsigned long long, Cs...> ()>{};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
template <char... Cs>
|
|
122
|
+
[[nodiscard]] constexpr auto operator""_i8 ()
|
|
123
|
+
{
|
|
124
|
+
return type_traits::integral_constant<
|
|
125
|
+
math::num<std::int8_t, Cs...> ()>{};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
template <char... Cs>
|
|
129
|
+
[[nodiscard]] constexpr auto operator""_i16 ()
|
|
130
|
+
{
|
|
131
|
+
return type_traits::integral_constant<
|
|
132
|
+
math::num<std::int16_t, Cs...> ()>{};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
template <char... Cs>
|
|
136
|
+
[[nodiscard]] constexpr auto operator""_i32 ()
|
|
137
|
+
{
|
|
138
|
+
return type_traits::integral_constant<
|
|
139
|
+
math::num<std::int32_t, Cs...> ()>{};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
template <char... Cs>
|
|
143
|
+
[[nodiscard]] constexpr auto operator""_i64 ()
|
|
144
|
+
{
|
|
145
|
+
return type_traits::integral_constant<
|
|
146
|
+
math::num<std::int64_t, Cs...> ()>{};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
template <char... Cs>
|
|
150
|
+
[[nodiscard]] constexpr auto operator""_u8 ()
|
|
151
|
+
{
|
|
152
|
+
return type_traits::integral_constant<
|
|
153
|
+
math::num<std::uint8_t, Cs...> ()>{};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
template <char... Cs>
|
|
157
|
+
[[nodiscard]] constexpr auto operator""_u16 ()
|
|
158
|
+
{
|
|
159
|
+
return type_traits::integral_constant<
|
|
160
|
+
math::num<std::uint16_t, Cs...> ()>{};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
template <char... Cs>
|
|
164
|
+
[[nodiscard]] constexpr auto operator""_u32 ()
|
|
165
|
+
{
|
|
166
|
+
return type_traits::integral_constant<
|
|
167
|
+
math::num<std::uint32_t, Cs...> ()>{};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
template <char... Cs>
|
|
171
|
+
[[nodiscard]] constexpr auto operator""_u64 ()
|
|
172
|
+
{
|
|
173
|
+
return type_traits::integral_constant<
|
|
174
|
+
math::num<std::uint64_t, Cs...> ()>{};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
template <char... Cs>
|
|
178
|
+
[[nodiscard]] constexpr auto operator""_f ()
|
|
179
|
+
{
|
|
180
|
+
return type_traits::floating_point_constant<
|
|
181
|
+
float, math::num<unsigned long, Cs...> (),
|
|
182
|
+
math::den<unsigned long, Cs...> (),
|
|
183
|
+
math::den_size<unsigned long, Cs...> ()>{};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
template <char... Cs>
|
|
187
|
+
[[nodiscard]] constexpr auto operator""_d ()
|
|
188
|
+
{
|
|
189
|
+
return type_traits::floating_point_constant<
|
|
190
|
+
double, math::num<unsigned long, Cs...> (),
|
|
191
|
+
math::den<unsigned long, Cs...> (),
|
|
192
|
+
math::den_size<unsigned long, Cs...> ()>{};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
template <char... Cs>
|
|
196
|
+
[[nodiscard]] constexpr auto operator""_ld ()
|
|
197
|
+
{
|
|
198
|
+
return type_traits::floating_point_constant<
|
|
199
|
+
long double, math::num<unsigned long long, Cs...> (),
|
|
200
|
+
math::den<unsigned long long, Cs...> (),
|
|
201
|
+
math::den_size<unsigned long long, Cs...> ()>{};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
constexpr auto operator""_b (const char* name, decltype (sizeof ("")) size)
|
|
205
|
+
{
|
|
206
|
+
struct named : std::string_view, type_traits::op
|
|
207
|
+
{
|
|
208
|
+
using value_type = bool;
|
|
209
|
+
[[nodiscard]] constexpr operator value_type () const
|
|
210
|
+
{
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
[[nodiscard]] constexpr auto
|
|
215
|
+
operator== (const named&) const
|
|
216
|
+
{
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
[[nodiscard]] constexpr auto
|
|
221
|
+
operator== (const bool other) const
|
|
222
|
+
{
|
|
223
|
+
return other;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return named{ { name, size }, {} };
|
|
228
|
+
}
|
|
229
|
+
} // namespace literals
|
|
230
|
+
|
|
231
|
+
// --------------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
// Wrappers that can be used to convert dynamic values to specific types
|
|
234
|
+
// that are recognised by the comparators.
|
|
235
|
+
// The syntax is similar to function calls, like `_i(expression)`, but the
|
|
236
|
+
// results have custom types expected by comparators.
|
|
237
|
+
using _b = type_traits::value<bool>;
|
|
238
|
+
using _c = type_traits::value<char>;
|
|
239
|
+
using _sc = type_traits::value<signed char>;
|
|
240
|
+
using _s = type_traits::value<short>;
|
|
241
|
+
using _i = type_traits::value<int>;
|
|
242
|
+
using _l = type_traits::value<long>;
|
|
243
|
+
using _ll = type_traits::value<long long>;
|
|
244
|
+
using _u = type_traits::value<unsigned>;
|
|
245
|
+
using _uc = type_traits::value<unsigned char>;
|
|
246
|
+
using _us = type_traits::value<unsigned short>;
|
|
247
|
+
using _ul = type_traits::value<unsigned long>;
|
|
248
|
+
using _ull = type_traits::value<unsigned long long>;
|
|
249
|
+
using _i8 = type_traits::value<std::int8_t>;
|
|
250
|
+
using _i16 = type_traits::value<std::int16_t>;
|
|
251
|
+
using _i32 = type_traits::value<std::int32_t>;
|
|
252
|
+
using _i64 = type_traits::value<std::int64_t>;
|
|
253
|
+
using _u8 = type_traits::value<std::uint8_t>;
|
|
254
|
+
using _u16 = type_traits::value<std::uint16_t>;
|
|
255
|
+
using _u32 = type_traits::value<std::uint32_t>;
|
|
256
|
+
using _u64 = type_traits::value<std::uint64_t>;
|
|
257
|
+
using _f = type_traits::value<float>;
|
|
258
|
+
using _d = type_traits::value<double>;
|
|
259
|
+
using _ld = type_traits::value<long double>;
|
|
260
|
+
|
|
261
|
+
// Template for wrapping any other type.
|
|
262
|
+
template <class T>
|
|
263
|
+
struct _t : type_traits::value<T>
|
|
264
|
+
{
|
|
265
|
+
constexpr explicit _t (const T& t) : type_traits::value<T>{ t }
|
|
266
|
+
{
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// --------------------------------------------------------------------------
|
|
271
|
+
} // namespace micro_os_plus::micro_test_plus
|
|
272
|
+
|
|
273
|
+
#if defined(__GNUC__)
|
|
274
|
+
#pragma GCC diagnostic pop
|
|
275
|
+
#endif
|
|
276
|
+
|
|
277
|
+
// ----------------------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
#endif // __cplusplus
|
|
280
|
+
|
|
281
|
+
// ----------------------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
#endif // MICRO_TEST_PLUS_LITERALS_H_
|
|
284
|
+
|
|
285
|
+
// ----------------------------------------------------------------------------
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the µOS++ distribution.
|
|
3
|
+
* (https://github.com/micro-os-plus/)
|
|
4
|
+
* Copyright (c) 2021 Liviu Ionescu.
|
|
5
|
+
*
|
|
6
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
7
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
8
|
+
*
|
|
9
|
+
* If a copy of the license was not distributed with this file, it can
|
|
10
|
+
* be obtained from <https://opensource.org/licenses/MIT/>.
|
|
11
|
+
*
|
|
12
|
+
* Major parts of the code are inspired from v1.1.8 of the Boost UT project,
|
|
13
|
+
* released under the terms of the Boost Version 1.0 Software License,
|
|
14
|
+
* which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#ifndef MICRO_TEST_PLUS_MATH_H_
|
|
18
|
+
#define MICRO_TEST_PLUS_MATH_H_
|
|
19
|
+
|
|
20
|
+
// ----------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
#ifdef __cplusplus
|
|
23
|
+
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
#include <array>
|
|
27
|
+
|
|
28
|
+
// ----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
#if defined(__GNUC__)
|
|
31
|
+
#pragma GCC diagnostic push
|
|
32
|
+
#pragma GCC diagnostic ignored "-Wconversion"
|
|
33
|
+
#if defined(__clang__)
|
|
34
|
+
#pragma clang diagnostic ignored "-Wc++98-compat"
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
namespace micro_os_plus::micro_test_plus
|
|
39
|
+
{
|
|
40
|
+
// --------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @brief Local mathematical functions.
|
|
44
|
+
*
|
|
45
|
+
* Some may have equivalents in the standard library, but may be
|
|
46
|
+
* more complicated to use, or have only floating point variants, or
|
|
47
|
+
* not be constexpr.
|
|
48
|
+
*/
|
|
49
|
+
namespace math
|
|
50
|
+
{
|
|
51
|
+
/**
|
|
52
|
+
* @brief Generic absolute of any value.
|
|
53
|
+
*/
|
|
54
|
+
template <class T>
|
|
55
|
+
[[nodiscard]] constexpr auto
|
|
56
|
+
abs (const T t) -> T
|
|
57
|
+
{
|
|
58
|
+
return t < T{} ? -t : t;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @brief Generic minimum of two values.
|
|
63
|
+
*/
|
|
64
|
+
template <class T>
|
|
65
|
+
[[nodiscard]] constexpr auto
|
|
66
|
+
min_value (const T& lhs, const T& rhs) -> const T&
|
|
67
|
+
{
|
|
68
|
+
return (rhs < lhs) ? rhs : lhs;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @brief Generic 'power of', to raise base to exponent (base ^ exp).
|
|
73
|
+
*/
|
|
74
|
+
template <class T, class Exp_T>
|
|
75
|
+
[[nodiscard]] constexpr auto
|
|
76
|
+
pow (const T base, const Exp_T exp) -> T
|
|
77
|
+
{
|
|
78
|
+
// If the exponent is 0, return 1, otherwise recurse.
|
|
79
|
+
return exp ? T (base * pow (base, exp - Exp_T (1))) : T (1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @brief Compute the integral value of a number represented as
|
|
84
|
+
* an array of characters.
|
|
85
|
+
*/
|
|
86
|
+
template <class T, char... Cs>
|
|
87
|
+
[[nodiscard]] constexpr auto
|
|
88
|
+
num () -> T
|
|
89
|
+
{
|
|
90
|
+
// Assume all are digits or dot or apostrophe.
|
|
91
|
+
static_assert (
|
|
92
|
+
((Cs == '.' or Cs == '\'' or (Cs >= '0' and Cs <= '9')) and ...));
|
|
93
|
+
T result{};
|
|
94
|
+
for (const char c : { Cs... })
|
|
95
|
+
{
|
|
96
|
+
if (c == '.')
|
|
97
|
+
{
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
if (c >= '0' and c <= '9')
|
|
101
|
+
{
|
|
102
|
+
result = result * T (10) + T (c - '0');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @brief Compute the decimals of a number represented as
|
|
110
|
+
* an array of characters.
|
|
111
|
+
*/
|
|
112
|
+
template <class T, char... Cs>
|
|
113
|
+
[[nodiscard]] constexpr auto
|
|
114
|
+
den () -> T
|
|
115
|
+
{
|
|
116
|
+
constexpr const std::array cs{ Cs... };
|
|
117
|
+
T result{};
|
|
118
|
+
auto i = 0u;
|
|
119
|
+
while (cs[i++] != '.')
|
|
120
|
+
{
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (auto j = i; j < sizeof...(Cs); ++j)
|
|
124
|
+
{
|
|
125
|
+
result += pow (T (10), sizeof...(Cs) - j) * T (cs[j] - '0');
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @brief Compute the number of decimal places of a number represented as
|
|
132
|
+
* an array of characters.
|
|
133
|
+
*/
|
|
134
|
+
template <class T, char... Cs>
|
|
135
|
+
[[nodiscard]] constexpr auto
|
|
136
|
+
den_size () -> T
|
|
137
|
+
{
|
|
138
|
+
constexpr const std::array cs{ Cs... };
|
|
139
|
+
T i{};
|
|
140
|
+
#if defined(__GNUC__)
|
|
141
|
+
#pragma GCC diagnostic push
|
|
142
|
+
#pragma GCC diagnostic ignored "-Wconversion"
|
|
143
|
+
#endif
|
|
144
|
+
while (cs[i++] != '.')
|
|
145
|
+
#if defined(__GNUC__)
|
|
146
|
+
#pragma GCC diagnostic pop
|
|
147
|
+
#endif
|
|
148
|
+
{
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return T (sizeof...(Cs)) - i + T (1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @brief Compute the number of decimal places of a value,
|
|
156
|
+
* up to 7 digits.
|
|
157
|
+
*/
|
|
158
|
+
template <class T, class Value_T>
|
|
159
|
+
[[nodiscard]] constexpr auto
|
|
160
|
+
den_size (Value_T value) -> T
|
|
161
|
+
{
|
|
162
|
+
constexpr auto precision = Value_T (1e-7);
|
|
163
|
+
T result{};
|
|
164
|
+
Value_T tmp{};
|
|
165
|
+
do
|
|
166
|
+
{
|
|
167
|
+
value *= 10;
|
|
168
|
+
#if defined(__GNUC__)
|
|
169
|
+
#pragma GCC diagnostic push
|
|
170
|
+
#if !defined(__clang__) // GCC only
|
|
171
|
+
#pragma GCC diagnostic ignored "-Warith-conversion"
|
|
172
|
+
#endif
|
|
173
|
+
#if defined(__clang__)
|
|
174
|
+
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
|
|
175
|
+
#endif
|
|
176
|
+
#endif
|
|
177
|
+
tmp = value - T (value);
|
|
178
|
+
#if defined(__GNUC__)
|
|
179
|
+
#pragma GCC diagnostic pop
|
|
180
|
+
#endif
|
|
181
|
+
++result;
|
|
182
|
+
}
|
|
183
|
+
while (tmp > precision);
|
|
184
|
+
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
} // namespace math
|
|
189
|
+
|
|
190
|
+
// --------------------------------------------------------------------------
|
|
191
|
+
} // namespace micro_os_plus::micro_test_plus
|
|
192
|
+
|
|
193
|
+
#if defined(__GNUC__)
|
|
194
|
+
#pragma GCC diagnostic pop
|
|
195
|
+
#endif
|
|
196
|
+
|
|
197
|
+
// ----------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
#endif // __cplusplus
|
|
200
|
+
|
|
201
|
+
// ----------------------------------------------------------------------------
|
|
202
|
+
|
|
203
|
+
#endif // MICRO_TEST_PLUS_MATH_H_
|
|
204
|
+
|
|
205
|
+
// ----------------------------------------------------------------------------
|