]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2012 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
92f5a8d4 | 4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt |
7c673cae FG |
5 | |
6 | #ifndef BOOST_MATH_LOGGED_ADAPTER_HPP | |
7 | #define BOOST_MATH_LOGGED_ADAPTER_HPP | |
8 | ||
1e59de90 | 9 | #include <boost/multiprecision/detail/standalone_config.hpp> |
7c673cae FG |
10 | #include <boost/multiprecision/traits/extract_exponent_type.hpp> |
11 | #include <boost/multiprecision/detail/integer_ops.hpp> | |
12 | ||
92f5a8d4 TL |
13 | namespace boost { |
14 | namespace multiprecision { | |
7c673cae FG |
15 | |
16 | template <class Backend> | |
17 | inline void log_postfix_event(const Backend&, const char* /*event_description*/) | |
18 | { | |
19 | } | |
20 | template <class Backend, class T> | |
21 | inline void log_postfix_event(const Backend&, const T&, const char* /*event_description*/) | |
22 | { | |
23 | } | |
24 | template <class Backend> | |
25 | inline void log_prefix_event(const Backend&, const char* /*event_description*/) | |
26 | { | |
27 | } | |
28 | template <class Backend, class T> | |
29 | inline void log_prefix_event(const Backend&, const T&, const char* /*event_description*/) | |
30 | { | |
31 | } | |
32 | template <class Backend, class T, class U> | |
33 | inline void log_prefix_event(const Backend&, const T&, const U&, const char* /*event_description*/) | |
34 | { | |
35 | } | |
36 | template <class Backend, class T, class U, class V> | |
37 | inline void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* /*event_description*/) | |
38 | { | |
39 | } | |
40 | ||
92f5a8d4 | 41 | namespace backends { |
7c673cae FG |
42 | |
43 | template <class Backend> | |
44 | struct logged_adaptor | |
45 | { | |
1e59de90 TL |
46 | using signed_types = typename Backend::signed_types ; |
47 | using unsigned_types = typename Backend::unsigned_types; | |
48 | using float_types = typename Backend::float_types ; | |
49 | using exponent_type = typename extract_exponent_type<Backend, number_category<Backend>::value>::type; | |
7c673cae | 50 | |
92f5a8d4 | 51 | private: |
7c673cae | 52 | Backend m_value; |
92f5a8d4 TL |
53 | |
54 | public: | |
7c673cae FG |
55 | logged_adaptor() |
56 | { | |
57 | log_postfix_event(m_value, "Default construct"); | |
58 | } | |
59 | logged_adaptor(const logged_adaptor& o) | |
60 | { | |
61 | log_prefix_event(m_value, o.value(), "Copy construct"); | |
62 | m_value = o.m_value; | |
63 | log_postfix_event(m_value, "Copy construct"); | |
64 | } | |
1e59de90 | 65 | // rvalue copy |
92f5a8d4 TL |
66 | logged_adaptor(logged_adaptor&& o) |
67 | { | |
68 | log_prefix_event(m_value, o.value(), "Move construct"); | |
69 | m_value = static_cast<Backend&&>(o.m_value); | |
70 | log_postfix_event(m_value, "Move construct"); | |
71 | } | |
72 | logged_adaptor& operator=(logged_adaptor&& o) | |
73 | { | |
74 | log_prefix_event(m_value, o.value(), "Move Assignment"); | |
75 | m_value = static_cast<Backend&&>(o.m_value); | |
76 | log_postfix_event(m_value, "Move construct"); | |
77 | return *this; | |
78 | } | |
92f5a8d4 | 79 | logged_adaptor& operator=(const logged_adaptor& o) |
7c673cae FG |
80 | { |
81 | log_prefix_event(m_value, o.value(), "Assignment"); | |
82 | m_value = o.m_value; | |
83 | log_postfix_event(m_value, "Copy construct"); | |
84 | return *this; | |
85 | } | |
86 | template <class T> | |
1e59de90 | 87 | logged_adaptor(const T& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = 0) |
92f5a8d4 TL |
88 | : m_value(i) |
89 | { | |
90 | log_postfix_event(m_value, "construct from arithmetic type"); | |
91 | } | |
92 | template <class T> | |
1e59de90 | 93 | logged_adaptor(const logged_adaptor<T>& i, const typename std::enable_if<std::is_convertible<T, Backend>::value>::type* = 0) |
92f5a8d4 | 94 | : m_value(i.value()) |
7c673cae FG |
95 | { |
96 | log_postfix_event(m_value, "construct from arithmetic type"); | |
97 | } | |
1e59de90 TL |
98 | template <class T, class U> |
99 | logged_adaptor(const T& i, const U& j, typename std::enable_if<std::is_constructible<Backend, const T&, const U&>::value>::type* = nullptr) | |
100 | : m_value(i, j) | |
101 | { | |
102 | log_postfix_event(m_value, "construct from a pair of arithmetic types"); | |
103 | } | |
104 | template <class D = Backend> | |
105 | logged_adaptor(const Backend& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr) | |
106 | : m_value(i, digits10) | |
107 | { | |
108 | log_postfix_event(m_value, "construct from arithmetic type and precision"); | |
109 | } | |
110 | template <class D = Backend> | |
111 | logged_adaptor(const logged_adaptor<Backend>& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr) | |
112 | : m_value(i.value(), digits10) | |
113 | { | |
114 | log_postfix_event(m_value, "construct from arithmetic type and precision"); | |
115 | } | |
7c673cae | 116 | template <class T> |
1e59de90 | 117 | typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value || std::is_assignable<Backend, T>::value, logged_adaptor&>::type operator=(const T& i) |
7c673cae FG |
118 | { |
119 | log_prefix_event(m_value, i, "Assignment from arithmetic type"); | |
120 | m_value = i; | |
121 | log_postfix_event(m_value, "Assignment from arithmetic type"); | |
122 | return *this; | |
123 | } | |
92f5a8d4 | 124 | logged_adaptor& operator=(const char* s) |
7c673cae FG |
125 | { |
126 | log_prefix_event(m_value, s, "Assignment from string type"); | |
127 | m_value = s; | |
128 | log_postfix_event(m_value, "Assignment from string type"); | |
129 | return *this; | |
130 | } | |
131 | void swap(logged_adaptor& o) | |
132 | { | |
133 | log_prefix_event(m_value, o.value(), "swap"); | |
134 | std::swap(m_value, o.value()); | |
135 | log_postfix_event(m_value, "swap"); | |
136 | } | |
92f5a8d4 | 137 | std::string str(std::streamsize digits, std::ios_base::fmtflags f) const |
7c673cae FG |
138 | { |
139 | log_prefix_event(m_value, "Conversion to string"); | |
140 | std::string s = m_value.str(digits, f); | |
141 | log_postfix_event(m_value, s, "Conversion to string"); | |
142 | return s; | |
143 | } | |
144 | void negate() | |
145 | { | |
146 | log_prefix_event(m_value, "negate"); | |
147 | m_value.negate(); | |
148 | log_postfix_event(m_value, "negate"); | |
149 | } | |
92f5a8d4 | 150 | int compare(const logged_adaptor& o) const |
7c673cae FG |
151 | { |
152 | log_prefix_event(m_value, o.value(), "compare"); | |
153 | int r = m_value.compare(o.value()); | |
154 | log_postfix_event(m_value, r, "compare"); | |
155 | return r; | |
156 | } | |
157 | template <class T> | |
92f5a8d4 | 158 | int compare(const T& i) const |
7c673cae FG |
159 | { |
160 | log_prefix_event(m_value, i, "compare"); | |
161 | int r = m_value.compare(i); | |
162 | log_postfix_event(m_value, r, "compare"); | |
163 | return r; | |
164 | } | |
165 | Backend& value() | |
166 | { | |
167 | return m_value; | |
168 | } | |
92f5a8d4 | 169 | const Backend& value() const |
7c673cae FG |
170 | { |
171 | return m_value; | |
172 | } | |
1e59de90 TL |
173 | |
174 | #ifndef BOOST_MP_STANDALONE | |
7c673cae FG |
175 | template <class Archive> |
176 | void serialize(Archive& ar, const unsigned int /*version*/) | |
177 | { | |
178 | log_prefix_event(m_value, "serialize"); | |
92f5a8d4 | 179 | ar& boost::make_nvp("value", m_value); |
7c673cae FG |
180 | log_postfix_event(m_value, "serialize"); |
181 | } | |
1e59de90 TL |
182 | #endif |
183 | ||
184 | static unsigned default_precision() noexcept | |
7c673cae FG |
185 | { |
186 | return Backend::default_precision(); | |
187 | } | |
1e59de90 | 188 | static void default_precision(unsigned v) noexcept |
7c673cae FG |
189 | { |
190 | Backend::default_precision(v); | |
191 | } | |
1e59de90 TL |
192 | static unsigned thread_default_precision() noexcept |
193 | { | |
194 | return Backend::thread_default_precision(); | |
195 | } | |
196 | static void thread_default_precision(unsigned v) noexcept | |
197 | { | |
198 | Backend::thread_default_precision(v); | |
199 | } | |
200 | unsigned precision() const noexcept | |
7c673cae FG |
201 | { |
202 | return value().precision(); | |
203 | } | |
1e59de90 | 204 | void precision(unsigned digits10) noexcept |
7c673cae FG |
205 | { |
206 | value().precision(digits10); | |
207 | } | |
1e59de90 TL |
208 | // |
209 | // Variable precision options: | |
210 | // | |
211 | static constexpr variable_precision_options default_variable_precision_options()noexcept | |
212 | { | |
213 | return Backend::default_variable_precision_options(); | |
214 | } | |
215 | static constexpr variable_precision_options thread_default_variable_precision_options()noexcept | |
216 | { | |
217 | return Backend::thread_default_variable_precision_options(); | |
218 | } | |
219 | static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts) | |
220 | { | |
221 | Backend::default_variable_precision_options(opts); | |
222 | } | |
223 | static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts) | |
224 | { | |
225 | Backend::thread_default_variable_precision_options(opts); | |
226 | } | |
7c673cae FG |
227 | }; |
228 | ||
229 | template <class T> | |
230 | inline const T& unwrap_logged_type(const T& a) { return a; } | |
231 | template <class Backend> | |
232 | inline const Backend& unwrap_logged_type(const logged_adaptor<Backend>& a) { return a.value(); } | |
233 | ||
92f5a8d4 TL |
234 | #define NON_MEMBER_OP1(name, str) \ |
235 | template <class Backend> \ | |
236 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result) \ | |
237 | { \ | |
238 | using default_ops::BOOST_JOIN(eval_, name); \ | |
239 | log_prefix_event(result.value(), str); \ | |
240 | BOOST_JOIN(eval_, name) \ | |
241 | (result.value()); \ | |
242 | log_postfix_event(result.value(), str); \ | |
7c673cae FG |
243 | } |
244 | ||
92f5a8d4 TL |
245 | #define NON_MEMBER_OP2(name, str) \ |
246 | template <class Backend, class T> \ | |
247 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a) \ | |
248 | { \ | |
249 | using default_ops::BOOST_JOIN(eval_, name); \ | |
250 | log_prefix_event(result.value(), unwrap_logged_type(a), str); \ | |
251 | BOOST_JOIN(eval_, name) \ | |
252 | (result.value(), unwrap_logged_type(a)); \ | |
253 | log_postfix_event(result.value(), str); \ | |
254 | } \ | |
255 | template <class Backend> \ | |
256 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a) \ | |
257 | { \ | |
258 | using default_ops::BOOST_JOIN(eval_, name); \ | |
259 | log_prefix_event(result.value(), unwrap_logged_type(a), str); \ | |
260 | BOOST_JOIN(eval_, name) \ | |
261 | (result.value(), unwrap_logged_type(a)); \ | |
262 | log_postfix_event(result.value(), str); \ | |
7c673cae FG |
263 | } |
264 | ||
92f5a8d4 TL |
265 | #define NON_MEMBER_OP3(name, str) \ |
266 | template <class Backend, class T, class U> \ | |
267 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b) \ | |
268 | { \ | |
269 | using default_ops::BOOST_JOIN(eval_, name); \ | |
270 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \ | |
271 | BOOST_JOIN(eval_, name) \ | |
272 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ | |
273 | log_postfix_event(result.value(), str); \ | |
274 | } \ | |
275 | template <class Backend, class T> \ | |
276 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b) \ | |
277 | { \ | |
278 | using default_ops::BOOST_JOIN(eval_, name); \ | |
279 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \ | |
280 | BOOST_JOIN(eval_, name) \ | |
281 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ | |
282 | log_postfix_event(result.value(), str); \ | |
283 | } \ | |
284 | template <class Backend, class T> \ | |
285 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b) \ | |
286 | { \ | |
287 | using default_ops::BOOST_JOIN(eval_, name); \ | |
288 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \ | |
289 | BOOST_JOIN(eval_, name) \ | |
290 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ | |
291 | log_postfix_event(result.value(), str); \ | |
292 | } \ | |
293 | template <class Backend> \ | |
294 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b) \ | |
295 | { \ | |
296 | using default_ops::BOOST_JOIN(eval_, name); \ | |
297 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), str); \ | |
298 | BOOST_JOIN(eval_, name) \ | |
299 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b)); \ | |
300 | log_postfix_event(result.value(), str); \ | |
7c673cae FG |
301 | } |
302 | ||
92f5a8d4 TL |
303 | #define NON_MEMBER_OP4(name, str) \ |
304 | template <class Backend, class T, class U, class V> \ | |
305 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const U& b, const V& c) \ | |
306 | { \ | |
307 | using default_ops::BOOST_JOIN(eval_, name); \ | |
308 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
309 | BOOST_JOIN(eval_, name) \ | |
310 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
311 | log_postfix_event(result.value(), str); \ | |
312 | } \ | |
313 | template <class Backend, class T> \ | |
314 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const T& c) \ | |
315 | { \ | |
316 | using default_ops::BOOST_JOIN(eval_, name); \ | |
317 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
318 | BOOST_JOIN(eval_, name) \ | |
319 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
320 | log_postfix_event(result.value(), str); \ | |
321 | } \ | |
322 | template <class Backend, class T> \ | |
323 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const logged_adaptor<Backend>& c) \ | |
324 | { \ | |
325 | using default_ops::BOOST_JOIN(eval_, name); \ | |
326 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
327 | BOOST_JOIN(eval_, name) \ | |
328 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
329 | log_postfix_event(result.value(), str); \ | |
330 | } \ | |
331 | template <class Backend, class T> \ | |
332 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const T& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \ | |
333 | { \ | |
334 | using default_ops::BOOST_JOIN(eval_, name); \ | |
335 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
336 | BOOST_JOIN(eval_, name) \ | |
337 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
338 | log_postfix_event(result.value(), str); \ | |
339 | } \ | |
340 | template <class Backend> \ | |
341 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const logged_adaptor<Backend>& b, const logged_adaptor<Backend>& c) \ | |
342 | { \ | |
343 | using default_ops::BOOST_JOIN(eval_, name); \ | |
344 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
345 | BOOST_JOIN(eval_, name) \ | |
346 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
347 | log_postfix_event(result.value(), str); \ | |
348 | } \ | |
349 | template <class Backend, class T, class U> \ | |
350 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<Backend> & result, const logged_adaptor<Backend>& a, const T& b, const U& c) \ | |
351 | { \ | |
352 | using default_ops::BOOST_JOIN(eval_, name); \ | |
353 | log_prefix_event(result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c), str); \ | |
354 | BOOST_JOIN(eval_, name) \ | |
355 | (result.value(), unwrap_logged_type(a), unwrap_logged_type(b), unwrap_logged_type(c)); \ | |
356 | log_postfix_event(result.value(), str); \ | |
357 | } | |
7c673cae | 358 | |
11fdf7f2 TL |
359 | NON_MEMBER_OP2(add, "+=") |
360 | NON_MEMBER_OP2(subtract, "-=") | |
361 | NON_MEMBER_OP2(multiply, "*=") | |
362 | NON_MEMBER_OP2(divide, "/=") | |
7c673cae FG |
363 | |
364 | template <class Backend, class R> | |
365 | inline void eval_convert_to(R* result, const logged_adaptor<Backend>& val) | |
366 | { | |
367 | using default_ops::eval_convert_to; | |
368 | log_prefix_event(val.value(), "convert_to"); | |
369 | eval_convert_to(result, val.value()); | |
370 | log_postfix_event(val.value(), *result, "convert_to"); | |
371 | } | |
372 | ||
1e59de90 TL |
373 | template <class Backend, class R> |
374 | inline void eval_convert_to(logged_adaptor<R>* result, const logged_adaptor<Backend>& val) | |
375 | { | |
376 | using default_ops::eval_convert_to; | |
377 | log_prefix_event(val.value(), "convert_to"); | |
378 | eval_convert_to(&result->value(), val.value()); | |
379 | log_postfix_event(val.value(), &result->value(), "convert_to"); | |
380 | } | |
381 | template <class Backend, class R> | |
382 | inline void eval_convert_to(logged_adaptor<R>* result, const Backend& val) | |
383 | { | |
384 | using default_ops::eval_convert_to; | |
385 | log_prefix_event(val, "convert_to"); | |
386 | eval_convert_to(&result->value(), val); | |
387 | log_postfix_event(val, &result->value(), "convert_to"); | |
388 | } | |
389 | ||
390 | template <class Backend> | |
391 | inline void eval_convert_to(std::complex<float>* result, const logged_adaptor<Backend>& val) | |
392 | { | |
393 | using default_ops::eval_convert_to; | |
394 | log_prefix_event(val.value(), "convert_to"); | |
395 | eval_convert_to(result, val.value()); | |
396 | log_postfix_event(val.value(), *result, "convert_to"); | |
397 | } | |
398 | template <class Backend> | |
399 | inline void eval_convert_to(std::complex<double>* result, const logged_adaptor<Backend>& val) | |
400 | { | |
401 | using default_ops::eval_convert_to; | |
402 | log_prefix_event(val.value(), "convert_to"); | |
403 | eval_convert_to(result, val.value()); | |
404 | log_postfix_event(val.value(), *result, "convert_to"); | |
405 | } | |
406 | template <class Backend> | |
407 | inline void eval_convert_to(std::complex<long double>* result, const logged_adaptor<Backend>& val) | |
408 | { | |
409 | using default_ops::eval_convert_to; | |
410 | log_prefix_event(val.value(), "convert_to"); | |
411 | eval_convert_to(result, val.value()); | |
412 | log_postfix_event(val.value(), *result, "convert_to"); | |
413 | } | |
414 | ||
415 | ||
7c673cae FG |
416 | template <class Backend, class Exp> |
417 | inline void eval_frexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp* exp) | |
418 | { | |
419 | log_prefix_event(arg.value(), "frexp"); | |
420 | eval_frexp(result.value(), arg.value(), exp); | |
421 | log_postfix_event(result.value(), *exp, "frexp"); | |
422 | } | |
423 | ||
424 | template <class Backend, class Exp> | |
425 | inline void eval_ldexp(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp) | |
426 | { | |
427 | log_prefix_event(arg.value(), "ldexp"); | |
428 | eval_ldexp(result.value(), arg.value(), exp); | |
429 | log_postfix_event(result.value(), exp, "ldexp"); | |
430 | } | |
431 | ||
432 | template <class Backend, class Exp> | |
433 | inline void eval_scalbn(logged_adaptor<Backend>& result, const logged_adaptor<Backend>& arg, Exp exp) | |
434 | { | |
1e59de90 | 435 | using default_ops::eval_scalbn; |
7c673cae FG |
436 | log_prefix_event(arg.value(), "scalbn"); |
437 | eval_scalbn(result.value(), arg.value(), exp); | |
438 | log_postfix_event(result.value(), exp, "scalbn"); | |
439 | } | |
440 | ||
441 | template <class Backend> | |
442 | inline typename Backend::exponent_type eval_ilogb(const logged_adaptor<Backend>& arg) | |
443 | { | |
1e59de90 | 444 | using default_ops::eval_ilogb; |
7c673cae FG |
445 | log_prefix_event(arg.value(), "ilogb"); |
446 | typename Backend::exponent_type r = eval_ilogb(arg.value()); | |
447 | log_postfix_event(arg.value(), "ilogb"); | |
448 | return r; | |
449 | } | |
450 | ||
11fdf7f2 TL |
451 | NON_MEMBER_OP2(floor, "floor") |
452 | NON_MEMBER_OP2(ceil, "ceil") | |
453 | NON_MEMBER_OP2(sqrt, "sqrt") | |
7c673cae FG |
454 | |
455 | template <class Backend> | |
456 | inline int eval_fpclassify(const logged_adaptor<Backend>& arg) | |
457 | { | |
458 | using default_ops::eval_fpclassify; | |
459 | log_prefix_event(arg.value(), "fpclassify"); | |
460 | int r = eval_fpclassify(arg.value()); | |
461 | log_postfix_event(arg.value(), r, "fpclassify"); | |
462 | return r; | |
463 | } | |
464 | ||
465 | /********************************************************************* | |
466 | * | |
467 | * Optional arithmetic operations come next: | |
468 | * | |
469 | *********************************************************************/ | |
470 | ||
11fdf7f2 TL |
471 | NON_MEMBER_OP3(add, "+") |
472 | NON_MEMBER_OP3(subtract, "-") | |
473 | NON_MEMBER_OP3(multiply, "*") | |
474 | NON_MEMBER_OP3(divide, "/") | |
475 | NON_MEMBER_OP3(multiply_add, "fused-multiply-add") | |
476 | NON_MEMBER_OP3(multiply_subtract, "fused-multiply-subtract") | |
477 | NON_MEMBER_OP4(multiply_add, "fused-multiply-add") | |
478 | NON_MEMBER_OP4(multiply_subtract, "fused-multiply-subtract") | |
7c673cae | 479 | |
11fdf7f2 TL |
480 | NON_MEMBER_OP1(increment, "increment") |
481 | NON_MEMBER_OP1(decrement, "decrement") | |
7c673cae FG |
482 | |
483 | /********************************************************************* | |
484 | * | |
485 | * Optional integer operations come next: | |
486 | * | |
487 | *********************************************************************/ | |
488 | ||
11fdf7f2 TL |
489 | NON_MEMBER_OP2(modulus, "%=") |
490 | NON_MEMBER_OP3(modulus, "%") | |
491 | NON_MEMBER_OP2(bitwise_or, "|=") | |
492 | NON_MEMBER_OP3(bitwise_or, "|") | |
493 | NON_MEMBER_OP2(bitwise_and, "&=") | |
494 | NON_MEMBER_OP3(bitwise_and, "&") | |
495 | NON_MEMBER_OP2(bitwise_xor, "^=") | |
496 | NON_MEMBER_OP3(bitwise_xor, "^") | |
497 | NON_MEMBER_OP4(qr, "quotient-and-remainder") | |
498 | NON_MEMBER_OP2(complement, "~") | |
7c673cae FG |
499 | |
500 | template <class Backend> | |
11fdf7f2 | 501 | inline void eval_left_shift(logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
502 | { |
503 | using default_ops::eval_left_shift; | |
504 | log_prefix_event(arg.value(), a, "<<="); | |
505 | eval_left_shift(arg.value(), a); | |
506 | log_postfix_event(arg.value(), "<<="); | |
507 | } | |
508 | template <class Backend> | |
11fdf7f2 | 509 | inline void eval_left_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b) |
7c673cae FG |
510 | { |
511 | using default_ops::eval_left_shift; | |
512 | log_prefix_event(arg.value(), a, b, "<<"); | |
513 | eval_left_shift(arg.value(), a.value(), b); | |
514 | log_postfix_event(arg.value(), "<<"); | |
515 | } | |
516 | template <class Backend> | |
11fdf7f2 | 517 | inline void eval_right_shift(logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
518 | { |
519 | using default_ops::eval_right_shift; | |
520 | log_prefix_event(arg.value(), a, ">>="); | |
521 | eval_right_shift(arg.value(), a); | |
522 | log_postfix_event(arg.value(), ">>="); | |
523 | } | |
524 | template <class Backend> | |
11fdf7f2 | 525 | inline void eval_right_shift(logged_adaptor<Backend>& arg, const logged_adaptor<Backend>& a, std::size_t b) |
7c673cae FG |
526 | { |
527 | using default_ops::eval_right_shift; | |
528 | log_prefix_event(arg.value(), a, b, ">>"); | |
529 | eval_right_shift(arg.value(), a.value(), b); | |
530 | log_postfix_event(arg.value(), ">>"); | |
531 | } | |
532 | ||
533 | template <class Backend, class T> | |
1e59de90 | 534 | inline T eval_integer_modulus(const logged_adaptor<Backend>& arg, const T& a) |
7c673cae FG |
535 | { |
536 | using default_ops::eval_integer_modulus; | |
537 | log_prefix_event(arg.value(), a, "integer-modulus"); | |
1e59de90 | 538 | T r = eval_integer_modulus(arg.value(), a); |
7c673cae FG |
539 | log_postfix_event(arg.value(), r, "integer-modulus"); |
540 | return r; | |
541 | } | |
542 | ||
543 | template <class Backend> | |
1e59de90 | 544 | inline std::size_t eval_lsb(const logged_adaptor<Backend>& arg) |
7c673cae FG |
545 | { |
546 | using default_ops::eval_lsb; | |
547 | log_prefix_event(arg.value(), "least-significant-bit"); | |
1e59de90 | 548 | std::size_t r = eval_lsb(arg.value()); |
7c673cae FG |
549 | log_postfix_event(arg.value(), r, "least-significant-bit"); |
550 | return r; | |
551 | } | |
552 | ||
553 | template <class Backend> | |
1e59de90 | 554 | inline std::size_t eval_msb(const logged_adaptor<Backend>& arg) |
7c673cae FG |
555 | { |
556 | using default_ops::eval_msb; | |
557 | log_prefix_event(arg.value(), "most-significant-bit"); | |
1e59de90 | 558 | std::size_t r = eval_msb(arg.value()); |
7c673cae FG |
559 | log_postfix_event(arg.value(), r, "most-significant-bit"); |
560 | return r; | |
561 | } | |
562 | ||
563 | template <class Backend> | |
1e59de90 | 564 | inline bool eval_bit_test(const logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
565 | { |
566 | using default_ops::eval_bit_test; | |
567 | log_prefix_event(arg.value(), a, "bit-test"); | |
568 | bool r = eval_bit_test(arg.value(), a); | |
569 | log_postfix_event(arg.value(), r, "bit-test"); | |
570 | return r; | |
571 | } | |
572 | ||
573 | template <class Backend> | |
1e59de90 | 574 | inline void eval_bit_set(const logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
575 | { |
576 | using default_ops::eval_bit_set; | |
577 | log_prefix_event(arg.value(), a, "bit-set"); | |
578 | eval_bit_set(arg.value(), a); | |
579 | log_postfix_event(arg.value(), arg, "bit-set"); | |
580 | } | |
581 | template <class Backend> | |
1e59de90 | 582 | inline void eval_bit_unset(const logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
583 | { |
584 | using default_ops::eval_bit_unset; | |
585 | log_prefix_event(arg.value(), a, "bit-unset"); | |
586 | eval_bit_unset(arg.value(), a); | |
587 | log_postfix_event(arg.value(), arg, "bit-unset"); | |
588 | } | |
589 | template <class Backend> | |
1e59de90 | 590 | inline void eval_bit_flip(const logged_adaptor<Backend>& arg, std::size_t a) |
7c673cae FG |
591 | { |
592 | using default_ops::eval_bit_flip; | |
593 | log_prefix_event(arg.value(), a, "bit-flip"); | |
594 | eval_bit_flip(arg.value(), a); | |
595 | log_postfix_event(arg.value(), arg, "bit-flip"); | |
596 | } | |
597 | ||
11fdf7f2 TL |
598 | NON_MEMBER_OP3(gcd, "gcd") |
599 | NON_MEMBER_OP3(lcm, "lcm") | |
600 | NON_MEMBER_OP4(powm, "powm") | |
7c673cae FG |
601 | |
602 | /********************************************************************* | |
603 | * | |
604 | * abs/fabs: | |
605 | * | |
606 | *********************************************************************/ | |
607 | ||
11fdf7f2 TL |
608 | NON_MEMBER_OP2(abs, "abs") |
609 | NON_MEMBER_OP2(fabs, "fabs") | |
7c673cae FG |
610 | |
611 | /********************************************************************* | |
612 | * | |
613 | * Floating point functions: | |
614 | * | |
615 | *********************************************************************/ | |
616 | ||
11fdf7f2 TL |
617 | NON_MEMBER_OP2(trunc, "trunc") |
618 | NON_MEMBER_OP2(round, "round") | |
619 | NON_MEMBER_OP2(exp, "exp") | |
620 | NON_MEMBER_OP2(log, "log") | |
621 | NON_MEMBER_OP2(log10, "log10") | |
622 | NON_MEMBER_OP2(sin, "sin") | |
623 | NON_MEMBER_OP2(cos, "cos") | |
624 | NON_MEMBER_OP2(tan, "tan") | |
625 | NON_MEMBER_OP2(asin, "asin") | |
626 | NON_MEMBER_OP2(acos, "acos") | |
627 | NON_MEMBER_OP2(atan, "atan") | |
628 | NON_MEMBER_OP2(sinh, "sinh") | |
629 | NON_MEMBER_OP2(cosh, "cosh") | |
630 | NON_MEMBER_OP2(tanh, "tanh") | |
631 | NON_MEMBER_OP2(logb, "logb") | |
632 | NON_MEMBER_OP3(fmod, "fmod") | |
633 | NON_MEMBER_OP3(pow, "pow") | |
634 | NON_MEMBER_OP3(atan2, "atan2") | |
1e59de90 TL |
635 | NON_MEMBER_OP2(asinh, "asinh") |
636 | NON_MEMBER_OP2(acosh, "acosh") | |
637 | NON_MEMBER_OP2(atanh, "atanh") | |
638 | NON_MEMBER_OP2(conj, "conj") | |
7c673cae | 639 | |
b32b8144 FG |
640 | template <class Backend> |
641 | int eval_signbit(const logged_adaptor<Backend>& val) | |
642 | { | |
643 | using default_ops::eval_signbit; | |
644 | return eval_signbit(val.value()); | |
645 | } | |
646 | ||
7c673cae FG |
647 | template <class Backend> |
648 | std::size_t hash_value(const logged_adaptor<Backend>& val) | |
649 | { | |
650 | return hash_value(val.value()); | |
651 | } | |
652 | ||
1e59de90 TL |
653 | template <class Backend, expression_template_option ExpressionTemplates> |
654 | inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type | |
655 | numerator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg) | |
656 | { | |
657 | number<Backend, ExpressionTemplates> t(arg.backend().value()); | |
658 | return numerator(t).backend(); | |
659 | } | |
660 | template <class Backend, expression_template_option ExpressionTemplates> | |
661 | inline typename std::enable_if<number_category<Backend>::value == number_kind_rational, typename number<logged_adaptor<Backend>, ExpressionTemplates>::value_type>::type | |
662 | denominator(const number<logged_adaptor<Backend>, ExpressionTemplates>& arg) | |
663 | { | |
664 | number<Backend, ExpressionTemplates> t(arg.backend().value()); | |
665 | return denominator(t).backend(); | |
666 | } | |
667 | ||
668 | template <class To, class From> | |
669 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(To& to, const logged_adaptor<From>& from) | |
670 | { | |
671 | using default_ops::eval_set_real; | |
672 | log_prefix_event(to, from.value(), "Set real part"); | |
673 | eval_set_real(to, from.value()); | |
674 | log_postfix_event(to, from.value(), "Set real part"); | |
675 | } | |
676 | template <class To, class From> | |
677 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const logged_adaptor<From>& from) | |
678 | { | |
679 | using default_ops::eval_set_real; | |
680 | log_prefix_event(to.value(), from.value(), "Set real part"); | |
681 | eval_set_real(to.value(), from.value()); | |
682 | log_postfix_event(to.value(), from.value(), "Set real part"); | |
683 | } | |
684 | template <class To, class From> | |
685 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(logged_adaptor<To>& to, const From& from) | |
686 | { | |
687 | using default_ops::eval_set_real; | |
688 | log_prefix_event(to.value(), from, "Set real part"); | |
689 | eval_set_real(to.value(), from); | |
690 | log_postfix_event(to.value(), from, "Set real part"); | |
691 | } | |
692 | ||
693 | template <class To, class From> | |
694 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const logged_adaptor<From>& from) | |
695 | { | |
696 | using default_ops::eval_set_imag; | |
697 | log_prefix_event(to, from.value(), "Set imag part"); | |
698 | eval_set_imag(to, from.value()); | |
699 | log_postfix_event(to, from.value(), "Set imag part"); | |
700 | } | |
701 | template <class To, class From> | |
702 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const logged_adaptor<From>& from) | |
703 | { | |
704 | using default_ops::eval_set_imag; | |
705 | log_prefix_event(to.value(), from.value(), "Set imag part"); | |
706 | eval_set_imag(to.value(), from.value()); | |
707 | log_postfix_event(to.value(), from.value(), "Set imag part"); | |
708 | } | |
709 | template <class To, class From> | |
710 | inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(logged_adaptor<To>& to, const From& from) | |
711 | { | |
712 | using default_ops::eval_set_imag; | |
713 | log_prefix_event(to.value(), from, "Set imag part"); | |
714 | eval_set_imag(to.value(), from); | |
715 | log_postfix_event(to.value(), from, "Set imag part"); | |
716 | } | |
717 | ||
718 | ||
92f5a8d4 TL |
719 | #define NON_MEMBER_COMPLEX_TO_REAL(name, str) \ |
720 | template <class B1, class B2> \ | |
721 | inline void BOOST_JOIN(eval_, name)(logged_adaptor<B1> & result, const logged_adaptor<B2>& a) \ | |
722 | { \ | |
723 | using default_ops::BOOST_JOIN(eval_, name); \ | |
724 | log_prefix_event(a.value(), a.value(), str); \ | |
725 | BOOST_JOIN(eval_, name) \ | |
726 | (result.value(), a.value()); \ | |
727 | log_postfix_event(result.value(), str); \ | |
728 | } \ | |
729 | template <class B1, class B2> \ | |
730 | inline void BOOST_JOIN(eval_, name)(B1 & result, const logged_adaptor<B2>& a) \ | |
731 | { \ | |
732 | using default_ops::BOOST_JOIN(eval_, name); \ | |
733 | log_prefix_event(a.value(), a.value(), str); \ | |
734 | BOOST_JOIN(eval_, name) \ | |
735 | (result, a.value()); \ | |
736 | log_postfix_event(result, str); \ | |
737 | } | |
738 | ||
739 | NON_MEMBER_COMPLEX_TO_REAL(real, "real") | |
740 | NON_MEMBER_COMPLEX_TO_REAL(imag, "imag") | |
741 | ||
742 | template <class T, class V, class U> | |
743 | inline void assign_components(logged_adaptor<T>& result, const V& v1, const U& v2) | |
744 | { | |
1e59de90 TL |
745 | using default_ops::assign_components; |
746 | assign_components(result.value(), unwrap_logged_type(v1), unwrap_logged_type(v2)); | |
92f5a8d4 TL |
747 | } |
748 | ||
7c673cae FG |
749 | } // namespace backends |
750 | ||
751 | using backends::logged_adaptor; | |
752 | ||
1e59de90 TL |
753 | namespace detail { |
754 | template <class Backend> | |
755 | struct is_variable_precision<logged_adaptor<Backend> > : public is_variable_precision<Backend> | |
756 | {}; | |
757 | #ifdef BOOST_HAS_INT128 | |
758 | template <class Backend> | |
759 | struct is_convertible_arithmetic<int128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<int128_type, Backend> | |
760 | {}; | |
761 | template <class Backend> | |
762 | struct is_convertible_arithmetic<uint128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<uint128_type, Backend> | |
763 | {}; | |
764 | #endif | |
765 | #ifdef BOOST_HAS_FLOAT128 | |
766 | template <class Backend> | |
767 | struct is_convertible_arithmetic<float128_type, logged_adaptor<Backend> > : public is_convertible_arithmetic<float128_type, Backend> | |
768 | {}; | |
769 | #endif | |
770 | } // namespace detail | |
771 | ||
92f5a8d4 TL |
772 | template <class Backend> |
773 | struct number_category<backends::logged_adaptor<Backend> > : public number_category<Backend> | |
774 | {}; | |
7c673cae | 775 | |
1e59de90 TL |
776 | template <class Number> |
777 | using logged_adaptor_t = number<logged_adaptor<typename Number::backend_type>, Number::et>; | |
778 | ||
779 | template <class Backend, expression_template_option ExpressionTemplates> | |
780 | struct component_type<number<logged_adaptor<Backend>, ExpressionTemplates>> | |
781 | { | |
782 | // | |
783 | // We'll make the component_type also a logged_adaptor: | |
784 | // | |
785 | using base_component_type = typename component_type<number<Backend, ExpressionTemplates>>::type; | |
786 | using base_component_backend = typename base_component_type::backend_type; | |
787 | using type = number<logged_adaptor<base_component_backend>, ExpressionTemplates>; | |
788 | }; | |
789 | ||
790 | template <class Backend> | |
791 | struct is_interval_number<backends::logged_adaptor<Backend> > : public is_interval_number<Backend> {}; | |
792 | ||
92f5a8d4 | 793 | }} // namespace boost::multiprecision |
7c673cae | 794 | |
92f5a8d4 | 795 | namespace std { |
7c673cae FG |
796 | |
797 | template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates> | |
798 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates> > | |
92f5a8d4 | 799 | : public std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > |
7c673cae | 800 | { |
1e59de90 TL |
801 | using base_type = std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> > ; |
802 | using number_type = boost::multiprecision::number<boost::multiprecision::backends::logged_adaptor<Backend>, ExpressionTemplates>; | |
92f5a8d4 TL |
803 | |
804 | public: | |
1e59de90 TL |
805 | static number_type(min)() noexcept { return (base_type::min)(); } |
806 | static number_type(max)() noexcept { return (base_type::max)(); } | |
807 | static number_type lowest() noexcept { return -(max)(); } | |
808 | static number_type epsilon() noexcept { return base_type::epsilon(); } | |
809 | static number_type round_error() noexcept { return epsilon() / 2; } | |
810 | static number_type infinity() noexcept { return base_type::infinity(); } | |
811 | static number_type quiet_NaN() noexcept { return base_type::quiet_NaN(); } | |
812 | static number_type signaling_NaN() noexcept { return base_type::signaling_NaN(); } | |
813 | static number_type denorm_min() noexcept { return base_type::denorm_min(); } | |
7c673cae FG |
814 | }; |
815 | ||
816 | } // namespace std | |
817 | ||
1e59de90 | 818 | #ifdef BOOST_MP_MATH_AVAILABLE |
92f5a8d4 TL |
819 | namespace boost { |
820 | namespace math { | |
7c673cae | 821 | |
92f5a8d4 | 822 | namespace policies { |
7c673cae FG |
823 | |
824 | template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates, class Policy> | |
92f5a8d4 TL |
825 | struct precision<boost::multiprecision::number<boost::multiprecision::logged_adaptor<Backend>, ExpressionTemplates>, Policy> |
826 | : public precision<boost::multiprecision::number<Backend, ExpressionTemplates>, Policy> | |
7c673cae FG |
827 | {}; |
828 | ||
92f5a8d4 | 829 | } |
7c673cae | 830 | |
92f5a8d4 | 831 | }} // namespace boost::math::policies |
1e59de90 | 832 | #endif // BOOST_MP_MATH_AVAILABLE |
7c673cae FG |
833 | |
834 | #undef NON_MEMBER_OP1 | |
835 | #undef NON_MEMBER_OP2 | |
836 | #undef NON_MEMBER_OP3 | |
837 | #undef NON_MEMBER_OP4 | |
838 | ||
839 | #endif |