-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathexample007_catalan_series.cpp
157 lines (121 loc) · 4.61 KB
/
example007_catalan_series.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
///////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2020 - 2022. //
// Distributed under the Boost Software License, //
// Version 1.0. (See accompanying file LICENSE_1_0.txt //
// or copy at http://www.boost.org/LICENSE_1_0.txt) //
///////////////////////////////////////////////////////////////////
#include <cmath>
#include <cstdint>
#include <math/softfloat/soft_double.h>
#include <math/softfloat/soft_double_examples.h>
static_assert(sizeof(double) == 8U, // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
"Error: This example requires 8 byte built-in double for verification");
namespace local { namespace detail {
using float64_t = math::softfloat::soft_double;
template<typename FloatingPointType>
constexpr auto pi() -> FloatingPointType
{
return FloatingPointType(3.1415926535897932384626433832795029L); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
}
template<>
constexpr auto pi() -> float64_t
{
return float64_t::my_value_pi();
}
template<typename FloatingPointType>
constexpr auto log_two_plus_sqrt_three() -> FloatingPointType
{
using std::log;
using std::sqrt;
return log(2U + sqrt(FloatingPointType(3U)));
}
template<>
constexpr auto log_two_plus_sqrt_three() -> float64_t
{
return
float64_t
{
static_cast<std::uint64_t>(UINT64_C(0x3FF5124271980435)), // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
math::softfloat::detail::nothing()
};
}
} // namespace detail
template<typename FloatingPointType>
constexpr auto catalan() -> FloatingPointType
{
using floating_point_type = FloatingPointType;
// Adapted from Boost.Math.Constants (see file calculate_constants.hpp).
// See also http://www.mpfr.org/algorithms.pdf
auto k_fact = static_cast<floating_point_type>(1U);
auto tk_fact = static_cast<floating_point_type>(2U);
auto sum = static_cast<floating_point_type>(static_cast<floating_point_type>(19U) / 18U); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
const floating_point_type lim = std::numeric_limits<floating_point_type>::epsilon();
for(auto k = static_cast<std::uint_fast32_t>(UINT32_C(2));
k < static_cast<std::uint_fast32_t>(UINT32_C(10000000));
++k)
{
const auto tk = static_cast<std::uint32_t>(2U * k);
const auto tk_plus_one = static_cast<std::uint32_t>(tk + 1U);
const auto tk_plus_one_squared = static_cast<std::uint64_t>(static_cast<std::uint64_t>(tk_plus_one) * tk_plus_one);
k_fact *= k;
tk_fact *= static_cast<std::uint64_t>(static_cast<std::uint64_t>(tk) * (tk - 1U));
floating_point_type term = (k_fact * k_fact) / (tk_fact * tk_plus_one_squared);
sum += term;
if(term < lim)
{
break;
}
}
const auto result =
static_cast<floating_point_type>
(
static_cast<floating_point_type>
(
(
detail::pi<floating_point_type>()
* detail::log_two_plus_sqrt_three<floating_point_type>()
)
+ static_cast<floating_point_type>(sum * 3U)
) / 8U
);
return result; // NOLINT(performance-no-automatic-move)
}
} // namespace local
auto math::softfloat::example007_catalan_series() -> bool
{
#if (defined(_MSC_VER) && (_MSC_VER < 1920))
#pragma warning(push)
#pragma warning(disable : 4307)
#endif
constexpr auto c = local::catalan<float64_t>();
#if (defined(_MSC_VER) && (_MSC_VER < 1920))
#pragma warning(pop)
#endif
using local_representation_type = typename float64_t::representation_type;
// N[Catalan, 41]
// 0.9159655941772190150546035149323841107741
constexpr float64_t
control
{
static_cast<local_representation_type>(UINT64_C(0x3FED4F9713E8135D)),
math::softfloat::detail::nothing()
};
using std::fabs;
constexpr float64_t closeness = fabs(1 - fabs(c / control));
constexpr auto tol = static_cast<float64_t>(std::numeric_limits<float64_t>::epsilon() * 10);
constexpr auto result_is_ok = (closeness < tol);
#if (defined(SOFT_DOUBLE_CONSTEXPR_IS_COMPILE_TIME_CONST) && (SOFT_DOUBLE_CONSTEXPR_IS_COMPILE_TIME_CONST != 0))
static_assert(result_is_ok, "Error: example007_catalan_series not OK!");
#endif
return result_is_ok;
}
// Enable this if you would like to activate this main() as a standalone example.
#if 0
#include <iomanip>
#include <iostream>
int main()
{
const bool result_is_ok = math::softfloat::example007_catalan_series();
std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl;
}
#endif