]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/performance/cpp_bin_float_conversion_performance.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / multiprecision / performance / cpp_bin_float_conversion_performance.cpp
1 #include <boost/multiprecision/cpp_bin_float.hpp>
2 #include <boost/math/special_functions.hpp>
3 #include <boost/chrono.hpp>
4 #include <boost/random/mersenne_twister.hpp>
5 #include <boost/random/uniform_int.hpp>
6
7 template <class Clock>
8 struct stopwatch
9 {
10 typedef typename Clock::duration duration;
11 stopwatch()
12 {
13 m_start = Clock::now();
14 }
15 duration elapsed()
16 {
17 return Clock::now() - m_start;
18 }
19 void reset()
20 {
21 m_start = Clock::now();
22 }
23
24 private:
25 typename Clock::time_point m_start;
26 };
27
28 template <class T>
29 T generate_random()
30 {
31 typedef int e_type;
32 static boost::random::mt19937 gen;
33 T val = gen();
34 T prev_val = -1;
35 while(val != prev_val)
36 {
37 val *= (gen.max)();
38 prev_val = val;
39 val += gen();
40 }
41 e_type e;
42 val = frexp(val, &e);
43
44 static boost::random::uniform_int_distribution<e_type> ui(-20, 20);
45 return ldexp(val, ui(gen));
46 }
47
48
49 template <typename T>
50 double my_convert_to_double(const T& x)
51 {
52 double ret = 0;
53 if(isfinite(x)) {
54 if(x.backend().exponent() >= -1023 - 52 && x != 0) {
55 if(x.backend().exponent() <= 1023) {
56 int e = x.backend().exponent();
57 T y = ldexp(abs(x), 55 - e);
58 T t = trunc(y);
59 int64_t ti = t.template convert_to<int64_t>();
60 if((ti & 1) == 0) {
61 if(t < y)
62 ti |= 1;
63 }
64 if(e >= -1023 + 1) {
65 ret = ldexp(double(ti), e - 55);
66 }
67 else {
68 // subnormal
69 typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<128, boost::multiprecision::backends::digit_base_2> > cpp_bin_float128_t;
70 cpp_bin_float128_t sx = ldexp(cpp_bin_float128_t(ti), e - 55);
71 sx += DBL_MIN;
72 e = -1023 + 1;
73 cpp_bin_float128_t sy = ldexp(sx, 55 - e);
74 cpp_bin_float128_t st = trunc(sy);
75 ti = st.convert_to<int64_t>();
76 if((ti & 1) == 0) {
77 if(st < sy)
78 ti |= 1;
79 }
80 ret = ldexp(double(ti), e - 55) - DBL_MIN;
81 }
82 }
83 else {
84 // overflow
85 ret = HUGE_VAL;
86 }
87 }
88 }
89 else {
90 if(isnan(x))
91 return nan("");
92 // inf
93 ret = HUGE_VAL;
94 }
95 return x.backend().sign() ? -ret : ret;
96 }
97
98
99 template <class T>
100 void test_conversion_time(const char* name)
101 {
102 std::cout << "Testing times for type: " << name << "\n";
103 std::vector<T> values;
104
105 for(unsigned i = 0; i < 10000000; ++i)
106 {
107 values.push_back(generate_random<T>());
108 }
109
110 boost::chrono::duration<double> time;
111 stopwatch<boost::chrono::high_resolution_clock> c;
112
113 double total = 0;
114
115 for(typename std::vector<T>::const_iterator i = values.begin(); i != values.end(); ++i)
116 {
117 total += my_convert_to_double(*i);
118 }
119
120 time = c.elapsed();
121 std::cout << std::setprecision(3) << std::fixed;
122 std::cout << "Reference time: " << std::setw(7) << std::right << time << " (total sum = " << total << ")" << std::endl;
123
124 c.reset();
125
126 total = 0;
127
128 for(typename std::vector<T>::const_iterator i = values.begin(); i != values.end(); ++i)
129 {
130 total += i->template convert_to<double>();
131 }
132
133 time = c.elapsed();
134 std::cout << "Boost time: " << std::setw(7) << std::right << time << " (total sum = " << total << ")" << std::endl;
135
136
137 }
138
139
140 int main()
141 {
142 using namespace boost::multiprecision;
143
144 test_conversion_time<cpp_bin_float_double>("cpp_bin_float_double");
145 test_conversion_time<cpp_bin_float_quad>("cpp_bin_float_quad");
146 test_conversion_time<cpp_bin_float_50>("cpp_bin_float_50");
147 test_conversion_time<cpp_bin_float_100>("cpp_bin_float_100");
148
149 return 0;
150 }
151