1010#include < array>
1111#include < random>
1212
13+ enum class ops
14+ {
15+ add,
16+ sub,
17+ mul,
18+ div
19+ };
20+
1321static std::mt19937_64 rng{42 };
1422static std::uniform_int_distribution<unsigned > dist{5 , 100 };
1523
@@ -50,6 +58,67 @@ void test_qnan_preservation(const T lhs, const T rhs, Func op, U payload)
5058 }
5159}
5260
61+ template <typename T, std::enable_if_t <detail::is_decimal_floating_point_v<T>, bool > = true >
62+ bool test_signaling (const T x)
63+ {
64+ return issignaling (x);
65+ }
66+
67+ template <typename T, std::enable_if_t <!detail::is_decimal_floating_point_v<T>, bool > = true >
68+ bool test_signaling (const T)
69+ {
70+ return false ;
71+ }
72+
73+ template <typename T, std::enable_if_t <detail::is_decimal_floating_point_v<T>, bool > = true >
74+ bool test_nan (const T x)
75+ {
76+ return issignaling (x);
77+ }
78+
79+ template <typename T, std::enable_if_t <!detail::is_decimal_floating_point_v<T>, bool > = true >
80+ bool test_nan (const T)
81+ {
82+ return false ;
83+ }
84+
85+ template <typename T1, typename T2, typename U>
86+ void test_mixed_arithmetic (const T1 lhs, const T2 rhs, ops op, U payload)
87+ {
88+ using decimal_type = std::conditional_t <detail::is_decimal_floating_point_v<T1>, T1, T2>;
89+ static_assert (detail::is_decimal_floating_point_v<decimal_type>, " " );
90+
91+ BOOST_TEST (test_signaling (lhs) || test_signaling (rhs));
92+ BOOST_TEST (test_nan (lhs) || test_nan (rhs));
93+
94+ decimal_type res;
95+
96+ switch (op)
97+ {
98+ case ops::add:
99+ res = lhs + rhs;
100+ break ;
101+ case ops::sub:
102+ res = lhs - rhs;
103+ break ;
104+ case ops::mul:
105+ res = lhs * rhs;
106+ break ;
107+ case ops::div:
108+ res = lhs / rhs;
109+ break ;
110+ }
111+
112+ BOOST_TEST (isnan (res));
113+ BOOST_TEST (!issignaling (res));
114+
115+ if (payload > 0U )
116+ {
117+ const auto result_payload {read_payload (res)};
118+ BOOST_TEST_EQ (result_payload, payload);
119+ }
120+ }
121+
53122template <typename T>
54123void generate_tests ()
55124{
@@ -76,7 +145,6 @@ void generate_tests()
76145 test (value2, value1, std::divides<>(), current_payload);
77146 test (value2, value1, std::modulus<>(), current_payload);
78147 }
79-
80148}
81149
82150template <typename T>
@@ -105,7 +173,32 @@ void generate_qnan_tests()
105173 test_qnan_preservation (value2, value1, std::divides<>(), current_payload);
106174 test_qnan_preservation (value2, value1, std::modulus<>(), current_payload);
107175 }
176+ }
177+
178+ template <typename T>
179+ void generate_mixed_tests ()
180+ {
181+ constexpr std::size_t N {5 };
108182
183+ const std::array<unsigned , N> payloads {0 , 0 , 1 , 2 , 3 };
184+ const std::array<const char *, N> nans {" sNaN" , " SNAN" , " snan1" , " SnAn2" , " SNAN3" };
185+
186+ for (std::size_t i = 0 ; i < N; ++i)
187+ {
188+ const T value1 {nans[i]};
189+ const auto value2 {dist (rng)};
190+ const auto current_payload {payloads[i]};
191+
192+ test_mixed_arithmetic (value1, value2, ops::add, current_payload);
193+ test_mixed_arithmetic (value1, value2, ops::sub, current_payload);
194+ test_mixed_arithmetic (value1, value2, ops::mul, current_payload);
195+ test_mixed_arithmetic (value1, value2, ops::div, current_payload);
196+
197+ test_mixed_arithmetic (value2, value1, ops::add, current_payload);
198+ test_mixed_arithmetic (value2, value1, ops::sub, current_payload);
199+ test_mixed_arithmetic (value2, value1, ops::mul, current_payload);
200+ test_mixed_arithmetic (value2, value1, ops::div, current_payload);
201+ }
109202}
110203
111204int main ()
@@ -126,5 +219,13 @@ int main()
126219 generate_qnan_tests<decimal_fast64_t >();
127220 generate_qnan_tests<decimal_fast128_t >();
128221
222+ generate_mixed_tests<decimal32_t >();
223+ generate_mixed_tests<decimal64_t >();
224+ generate_mixed_tests<decimal128_t >();
225+
226+ generate_mixed_tests<decimal_fast32_t >();
227+ generate_mixed_tests<decimal_fast64_t >();
228+ generate_mixed_tests<decimal_fast128_t >();
229+
129230 return boost::report_errors ();
130231}
0 commit comments