Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 // Copyright 2011 John Maddock. Distributed under the Boost
|
Chris@16
|
3 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
|
Chris@16
|
7 #define BOOST_MATH_BIG_NUM_DEF_OPS
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/math/policies/error_handling.hpp>
|
Chris@16
|
10 #include <boost/multiprecision/detail/number_base.hpp>
|
Chris@16
|
11 #include <boost/math/special_functions/fpclassify.hpp>
|
Chris@16
|
12 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
13 #include <boost/mpl/front.hpp>
|
Chris@16
|
14 #include <boost/mpl/fold.hpp>
|
Chris@16
|
15 #include <boost/cstdint.hpp>
|
Chris@16
|
16 #include <boost/type_traits/make_unsigned.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 #ifndef INSTRUMENT_BACKEND
|
Chris@16
|
19 #ifndef BOOST_MP_INSTRUMENT
|
Chris@16
|
20 #define INSTRUMENT_BACKEND(x)
|
Chris@16
|
21 #else
|
Chris@16
|
22 #define INSTRUMENT_BACKEND(x)\
|
Chris@16
|
23 std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
|
Chris@16
|
24 #endif
|
Chris@16
|
25 #endif
|
Chris@16
|
26
|
Chris@16
|
27
|
Chris@16
|
28 namespace boost{ namespace multiprecision{ namespace default_ops{
|
Chris@16
|
29
|
Chris@16
|
30 #ifdef BOOST_MSVC
|
Chris@16
|
31 // warning C4127: conditional expression is constant
|
Chris@16
|
32 #pragma warning(push)
|
Chris@16
|
33 #pragma warning(disable:4127)
|
Chris@16
|
34 #endif
|
Chris@16
|
35 //
|
Chris@16
|
36 // Default versions of mixed arithmetic, these just construct a temporary
|
Chris@16
|
37 // from the arithmetic value and then do the arithmetic on that, two versions
|
Chris@16
|
38 // of each depending on whether the backend can be directly constructed from type V.
|
Chris@16
|
39 //
|
Chris@16
|
40 // Note that we have to provide *all* the template parameters to class number when used in
|
Chris@16
|
41 // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
|
Chris@16
|
42 // Since the result of the test doesn't depend on whether expression templates are on or off
|
Chris@16
|
43 // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
|
Chris@16
|
44 // code even more....
|
Chris@16
|
45 //
|
Chris@16
|
46 template <class T, class V>
|
Chris@16
|
47 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value >::type
|
Chris@16
|
48 eval_add(T& result, V const& v)
|
Chris@16
|
49 {
|
Chris@16
|
50 T t;
|
Chris@16
|
51 t = v;
|
Chris@16
|
52 eval_add(result, t);
|
Chris@16
|
53 }
|
Chris@16
|
54 template <class T, class V>
|
Chris@16
|
55 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value >::type
|
Chris@16
|
56 eval_add(T& result, V const& v)
|
Chris@16
|
57 {
|
Chris@16
|
58 T t(v);
|
Chris@16
|
59 eval_add(result, t);
|
Chris@16
|
60 }
|
Chris@16
|
61 template <class T, class V>
|
Chris@16
|
62 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
63 eval_subtract(T& result, V const& v)
|
Chris@16
|
64 {
|
Chris@16
|
65 T t;
|
Chris@16
|
66 t = v;
|
Chris@16
|
67 eval_subtract(result, t);
|
Chris@16
|
68 }
|
Chris@16
|
69 template <class T, class V>
|
Chris@16
|
70 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
71 eval_subtract(T& result, V const& v)
|
Chris@16
|
72 {
|
Chris@16
|
73 T t(v);
|
Chris@16
|
74 eval_subtract(result, t);
|
Chris@16
|
75 }
|
Chris@16
|
76 template <class T, class V>
|
Chris@16
|
77 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
78 eval_multiply(T& result, V const& v)
|
Chris@16
|
79 {
|
Chris@16
|
80 T t;
|
Chris@16
|
81 t = v;
|
Chris@16
|
82 eval_multiply(result, t);
|
Chris@16
|
83 }
|
Chris@16
|
84 template <class T, class V>
|
Chris@16
|
85 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
86 eval_multiply(T& result, V const& v)
|
Chris@16
|
87 {
|
Chris@16
|
88 T t(v);
|
Chris@16
|
89 eval_multiply(result, t);
|
Chris@16
|
90 }
|
Chris@16
|
91
|
Chris@16
|
92 template <class T, class U, class V>
|
Chris@16
|
93 void eval_multiply(T& t, const U& u, const V& v);
|
Chris@16
|
94
|
Chris@16
|
95 template <class T, class U, class V>
|
Chris@16
|
96 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
|
Chris@16
|
97 {
|
Chris@16
|
98 T z;
|
Chris@16
|
99 eval_multiply(z, u, v);
|
Chris@16
|
100 eval_add(t, z);
|
Chris@16
|
101 }
|
Chris@16
|
102 template <class T, class U, class V>
|
Chris@16
|
103 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
|
Chris@16
|
104 {
|
Chris@16
|
105 eval_multiply_add(t, v, u);
|
Chris@16
|
106 }
|
Chris@16
|
107 template <class T, class U, class V>
|
Chris@16
|
108 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
|
Chris@16
|
109 {
|
Chris@16
|
110 T z;
|
Chris@16
|
111 eval_multiply(z, u, v);
|
Chris@16
|
112 eval_subtract(t, z);
|
Chris@16
|
113 }
|
Chris@16
|
114 template <class T, class U, class V>
|
Chris@16
|
115 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
|
Chris@16
|
116 {
|
Chris@16
|
117 eval_multiply_subtract(t, v, u);
|
Chris@16
|
118 }
|
Chris@16
|
119 template <class T, class V>
|
Chris@16
|
120 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
121 eval_divide(T& result, V const& v)
|
Chris@16
|
122 {
|
Chris@16
|
123 T t;
|
Chris@16
|
124 t = v;
|
Chris@16
|
125 eval_divide(result, t);
|
Chris@16
|
126 }
|
Chris@16
|
127 template <class T, class V>
|
Chris@16
|
128 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
129 eval_divide(T& result, V const& v)
|
Chris@16
|
130 {
|
Chris@16
|
131 T t(v);
|
Chris@16
|
132 eval_divide(result, t);
|
Chris@16
|
133 }
|
Chris@16
|
134 template <class T, class V>
|
Chris@16
|
135 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
136 eval_modulus(T& result, V const& v)
|
Chris@16
|
137 {
|
Chris@16
|
138 T t;
|
Chris@16
|
139 t = v;
|
Chris@16
|
140 eval_modulus(result, t);
|
Chris@16
|
141 }
|
Chris@16
|
142 template <class T, class V>
|
Chris@16
|
143 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value&& is_convertible<V, T>::value>::type
|
Chris@16
|
144 eval_modulus(T& result, V const& v)
|
Chris@16
|
145 {
|
Chris@16
|
146 T t(v);
|
Chris@16
|
147 eval_modulus(result, t);
|
Chris@16
|
148 }
|
Chris@16
|
149 template <class T, class V>
|
Chris@16
|
150 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
151 eval_bitwise_and(T& result, V const& v)
|
Chris@16
|
152 {
|
Chris@16
|
153 T t;
|
Chris@16
|
154 t = v;
|
Chris@16
|
155 eval_bitwise_and(result, t);
|
Chris@16
|
156 }
|
Chris@16
|
157 template <class T, class V>
|
Chris@16
|
158 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
159 eval_bitwise_and(T& result, V const& v)
|
Chris@16
|
160 {
|
Chris@16
|
161 T t(v);
|
Chris@16
|
162 eval_bitwise_and(result, t);
|
Chris@16
|
163 }
|
Chris@16
|
164 template <class T, class V>
|
Chris@16
|
165 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
166 eval_bitwise_or(T& result, V const& v)
|
Chris@16
|
167 {
|
Chris@16
|
168 T t;
|
Chris@16
|
169 t = v;
|
Chris@16
|
170 eval_bitwise_or(result, t);
|
Chris@16
|
171 }
|
Chris@16
|
172 template <class T, class V>
|
Chris@16
|
173 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
174 eval_bitwise_or(T& result, V const& v)
|
Chris@16
|
175 {
|
Chris@16
|
176 T t(v);
|
Chris@16
|
177 eval_bitwise_or(result, t);
|
Chris@16
|
178 }
|
Chris@16
|
179 template <class T, class V>
|
Chris@16
|
180 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
181 eval_bitwise_xor(T& result, V const& v)
|
Chris@16
|
182 {
|
Chris@16
|
183 T t;
|
Chris@16
|
184 t = v;
|
Chris@16
|
185 eval_bitwise_xor(result, t);
|
Chris@16
|
186 }
|
Chris@16
|
187 template <class T, class V>
|
Chris@16
|
188 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
189 eval_bitwise_xor(T& result, V const& v)
|
Chris@16
|
190 {
|
Chris@16
|
191 T t(v);
|
Chris@16
|
192 eval_bitwise_xor(result, t);
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 template <class T, class V>
|
Chris@16
|
196 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
|
Chris@16
|
197 eval_complement(T& result, V const& v)
|
Chris@16
|
198 {
|
Chris@16
|
199 T t;
|
Chris@16
|
200 t = v;
|
Chris@16
|
201 eval_complement(result, t);
|
Chris@16
|
202 }
|
Chris@16
|
203 template <class T, class V>
|
Chris@16
|
204 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
|
Chris@16
|
205 eval_complement(T& result, V const& v)
|
Chris@16
|
206 {
|
Chris@16
|
207 T t(v);
|
Chris@16
|
208 eval_complement(result, t);
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 //
|
Chris@16
|
212 // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
|
Chris@16
|
213 //
|
Chris@16
|
214 template <class T, class U, class V>
|
Chris@16
|
215 void eval_add(T& t, const U& u, const V& v);
|
Chris@16
|
216
|
Chris@16
|
217 template <class T>
|
Chris@16
|
218 inline void eval_add_default(T& t, const T& u, const T& v)
|
Chris@16
|
219 {
|
Chris@16
|
220 if(&t == &v)
|
Chris@16
|
221 {
|
Chris@16
|
222 eval_add(t, u);
|
Chris@16
|
223 }
|
Chris@16
|
224 else if(&t == &u)
|
Chris@16
|
225 {
|
Chris@16
|
226 eval_add(t, v);
|
Chris@16
|
227 }
|
Chris@16
|
228 else
|
Chris@16
|
229 {
|
Chris@16
|
230 t = u;
|
Chris@16
|
231 eval_add(t, v);
|
Chris@16
|
232 }
|
Chris@16
|
233 }
|
Chris@16
|
234 template <class T, class U>
|
Chris@16
|
235 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
|
Chris@16
|
236 {
|
Chris@16
|
237 T vv;
|
Chris@16
|
238 vv = v;
|
Chris@16
|
239 eval_add(t, u, vv);
|
Chris@16
|
240 }
|
Chris@16
|
241 template <class T, class U>
|
Chris@16
|
242 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
|
Chris@16
|
243 {
|
Chris@16
|
244 T vv(v);
|
Chris@16
|
245 eval_add(t, u, vv);
|
Chris@16
|
246 }
|
Chris@16
|
247 template <class T, class U>
|
Chris@16
|
248 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
|
Chris@16
|
249 {
|
Chris@16
|
250 eval_add(t, v, u);
|
Chris@16
|
251 }
|
Chris@16
|
252 template <class T, class U, class V>
|
Chris@16
|
253 inline void eval_add_default(T& t, const U& u, const V& v)
|
Chris@16
|
254 {
|
Chris@16
|
255 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
256 {
|
Chris@16
|
257 eval_add(t, u);
|
Chris@16
|
258 }
|
Chris@16
|
259 else
|
Chris@16
|
260 {
|
Chris@16
|
261 t = u;
|
Chris@16
|
262 eval_add(t, v);
|
Chris@16
|
263 }
|
Chris@16
|
264 }
|
Chris@16
|
265 template <class T, class U, class V>
|
Chris@16
|
266 inline void eval_add(T& t, const U& u, const V& v)
|
Chris@16
|
267 {
|
Chris@16
|
268 eval_add_default(t, u, v);
|
Chris@16
|
269 }
|
Chris@16
|
270
|
Chris@16
|
271 template <class T, class U, class V>
|
Chris@16
|
272 void eval_subtract(T& t, const U& u, const V& v);
|
Chris@16
|
273
|
Chris@16
|
274 template <class T>
|
Chris@16
|
275 inline void eval_subtract_default(T& t, const T& u, const T& v)
|
Chris@16
|
276 {
|
Chris@16
|
277 if((&t == &v) && is_signed_number<T>::value)
|
Chris@16
|
278 {
|
Chris@16
|
279 eval_subtract(t, u);
|
Chris@16
|
280 t.negate();
|
Chris@16
|
281 }
|
Chris@16
|
282 else if(&t == &u)
|
Chris@16
|
283 {
|
Chris@16
|
284 eval_subtract(t, v);
|
Chris@16
|
285 }
|
Chris@16
|
286 else
|
Chris@16
|
287 {
|
Chris@16
|
288 t = u;
|
Chris@16
|
289 eval_subtract(t, v);
|
Chris@16
|
290 }
|
Chris@16
|
291 }
|
Chris@16
|
292 template <class T, class U>
|
Chris@16
|
293 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
|
Chris@16
|
294 {
|
Chris@16
|
295 T vv;
|
Chris@16
|
296 vv = v;
|
Chris@16
|
297 eval_subtract(t, u, vv);
|
Chris@16
|
298 }
|
Chris@16
|
299 template <class T, class U>
|
Chris@16
|
300 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
|
Chris@16
|
301 {
|
Chris@16
|
302 T vv(v);
|
Chris@16
|
303 eval_subtract(t, u, vv);
|
Chris@16
|
304 }
|
Chris@16
|
305 template <class T, class U>
|
Chris@16
|
306 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
|
Chris@16
|
307 {
|
Chris@16
|
308 eval_subtract(t, v, u);
|
Chris@16
|
309 t.negate();
|
Chris@16
|
310 }
|
Chris@16
|
311 template <class T, class U>
|
Chris@16
|
312 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
|
Chris@16
|
313 {
|
Chris@16
|
314 T temp(u);
|
Chris@16
|
315 eval_subtract(t, temp, v);
|
Chris@16
|
316 }
|
Chris@16
|
317 template <class T, class U, class V>
|
Chris@16
|
318 inline void eval_subtract_default(T& t, const U& u, const V& v)
|
Chris@16
|
319 {
|
Chris@16
|
320 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
321 {
|
Chris@16
|
322 eval_subtract(t, u);
|
Chris@16
|
323 t.negate();
|
Chris@16
|
324 }
|
Chris@16
|
325 else
|
Chris@16
|
326 {
|
Chris@16
|
327 t = u;
|
Chris@16
|
328 eval_subtract(t, v);
|
Chris@16
|
329 }
|
Chris@16
|
330 }
|
Chris@16
|
331 template <class T, class U, class V>
|
Chris@16
|
332 inline void eval_subtract(T& t, const U& u, const V& v)
|
Chris@16
|
333 {
|
Chris@16
|
334 eval_subtract_default(t, u, v);
|
Chris@16
|
335 }
|
Chris@16
|
336
|
Chris@16
|
337 template <class T>
|
Chris@16
|
338 inline void eval_multiply_default(T& t, const T& u, const T& v)
|
Chris@16
|
339 {
|
Chris@16
|
340 if(&t == &v)
|
Chris@16
|
341 {
|
Chris@16
|
342 eval_multiply(t, u);
|
Chris@16
|
343 }
|
Chris@16
|
344 else if(&t == &u)
|
Chris@16
|
345 {
|
Chris@16
|
346 eval_multiply(t, v);
|
Chris@16
|
347 }
|
Chris@16
|
348 else
|
Chris@16
|
349 {
|
Chris@16
|
350 t = u;
|
Chris@16
|
351 eval_multiply(t, v);
|
Chris@16
|
352 }
|
Chris@16
|
353 }
|
Chris@16
|
354 template <class T, class U>
|
Chris@16
|
355 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
|
Chris@16
|
356 {
|
Chris@16
|
357 T vv;
|
Chris@16
|
358 vv = v;
|
Chris@16
|
359 eval_multiply(t, u, vv);
|
Chris@16
|
360 }
|
Chris@16
|
361 template <class T, class U>
|
Chris@16
|
362 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
|
Chris@16
|
363 {
|
Chris@16
|
364 T vv(v);
|
Chris@16
|
365 eval_multiply(t, u, vv);
|
Chris@16
|
366 }
|
Chris@16
|
367 template <class T, class U>
|
Chris@16
|
368 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
|
Chris@16
|
369 {
|
Chris@16
|
370 eval_multiply(t, v, u);
|
Chris@16
|
371 }
|
Chris@16
|
372 template <class T, class U, class V>
|
Chris@16
|
373 inline void eval_multiply_default(T& t, const U& u, const V& v)
|
Chris@16
|
374 {
|
Chris@16
|
375 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
376 {
|
Chris@16
|
377 eval_multiply(t, u);
|
Chris@16
|
378 }
|
Chris@16
|
379 else
|
Chris@16
|
380 {
|
Chris@16
|
381 t = u;
|
Chris@16
|
382 eval_multiply(t, v);
|
Chris@16
|
383 }
|
Chris@16
|
384 }
|
Chris@16
|
385 template <class T, class U, class V>
|
Chris@16
|
386 inline void eval_multiply(T& t, const U& u, const V& v)
|
Chris@16
|
387 {
|
Chris@16
|
388 eval_multiply_default(t, u, v);
|
Chris@16
|
389 }
|
Chris@16
|
390
|
Chris@16
|
391 template <class T, class U, class V, class X>
|
Chris@16
|
392 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
|
Chris@16
|
393 {
|
Chris@16
|
394 if((void*)&x == (void*)&t)
|
Chris@16
|
395 {
|
Chris@16
|
396 T z;
|
Chris@16
|
397 z = x;
|
Chris@16
|
398 eval_multiply_add(t, u, v, z);
|
Chris@16
|
399 }
|
Chris@16
|
400 else
|
Chris@16
|
401 {
|
Chris@16
|
402 eval_multiply(t, u, v);
|
Chris@16
|
403 eval_add(t, x);
|
Chris@16
|
404 }
|
Chris@16
|
405 }
|
Chris@16
|
406 template <class T, class U, class V, class X>
|
Chris@16
|
407 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
|
Chris@16
|
408 {
|
Chris@16
|
409 eval_multiply_add(t, v, u, x);
|
Chris@16
|
410 }
|
Chris@16
|
411 template <class T, class U, class V, class X>
|
Chris@16
|
412 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
|
Chris@16
|
413 {
|
Chris@16
|
414 if((void*)&x == (void*)&t)
|
Chris@16
|
415 {
|
Chris@16
|
416 T z;
|
Chris@16
|
417 z = x;
|
Chris@16
|
418 eval_multiply_subtract(t, u, v, z);
|
Chris@16
|
419 }
|
Chris@16
|
420 else
|
Chris@16
|
421 {
|
Chris@16
|
422 eval_multiply(t, u, v);
|
Chris@16
|
423 eval_subtract(t, x);
|
Chris@16
|
424 }
|
Chris@16
|
425 }
|
Chris@16
|
426 template <class T, class U, class V, class X>
|
Chris@16
|
427 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
|
Chris@16
|
428 {
|
Chris@16
|
429 eval_multiply_subtract(t, v, u, x);
|
Chris@16
|
430 }
|
Chris@16
|
431
|
Chris@16
|
432 template <class T, class U, class V>
|
Chris@16
|
433 void eval_divide(T& t, const U& u, const V& v);
|
Chris@16
|
434
|
Chris@16
|
435 template <class T>
|
Chris@16
|
436 inline void eval_divide_default(T& t, const T& u, const T& v)
|
Chris@16
|
437 {
|
Chris@16
|
438 if(&t == &u)
|
Chris@16
|
439 eval_divide(t, v);
|
Chris@16
|
440 else if(&t == &v)
|
Chris@16
|
441 {
|
Chris@16
|
442 T temp;
|
Chris@16
|
443 eval_divide(temp, u, v);
|
Chris@16
|
444 temp.swap(t);
|
Chris@16
|
445 }
|
Chris@16
|
446 else
|
Chris@16
|
447 {
|
Chris@16
|
448 t = u;
|
Chris@16
|
449 eval_divide(t, v);
|
Chris@16
|
450 }
|
Chris@16
|
451 }
|
Chris@16
|
452 template <class T, class U>
|
Chris@16
|
453 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
|
Chris@16
|
454 {
|
Chris@16
|
455 T vv;
|
Chris@16
|
456 vv = v;
|
Chris@16
|
457 eval_divide(t, u, vv);
|
Chris@16
|
458 }
|
Chris@16
|
459 template <class T, class U>
|
Chris@16
|
460 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
|
Chris@16
|
461 {
|
Chris@16
|
462 T vv(v);
|
Chris@16
|
463 eval_divide(t, u, vv);
|
Chris@16
|
464 }
|
Chris@16
|
465 template <class T, class U>
|
Chris@16
|
466 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
|
Chris@16
|
467 {
|
Chris@16
|
468 T uu;
|
Chris@16
|
469 uu = u;
|
Chris@16
|
470 eval_divide(t, uu, v);
|
Chris@16
|
471 }
|
Chris@16
|
472 template <class T, class U>
|
Chris@16
|
473 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
|
Chris@16
|
474 {
|
Chris@16
|
475 T uu(u);
|
Chris@16
|
476 eval_divide(t, uu, v);
|
Chris@16
|
477 }
|
Chris@16
|
478 template <class T, class U, class V>
|
Chris@16
|
479 inline void eval_divide_default(T& t, const U& u, const V& v)
|
Chris@16
|
480 {
|
Chris@16
|
481 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
482 {
|
Chris@16
|
483 T temp(u);
|
Chris@16
|
484 eval_divide(temp, v);
|
Chris@16
|
485 t = temp;
|
Chris@16
|
486 }
|
Chris@16
|
487 else
|
Chris@16
|
488 {
|
Chris@16
|
489 t = u;
|
Chris@16
|
490 eval_divide(t, v);
|
Chris@16
|
491 }
|
Chris@16
|
492 }
|
Chris@16
|
493 template <class T, class U, class V>
|
Chris@16
|
494 inline void eval_divide(T& t, const U& u, const V& v)
|
Chris@16
|
495 {
|
Chris@16
|
496 eval_divide_default(t, u, v);
|
Chris@16
|
497 }
|
Chris@16
|
498
|
Chris@16
|
499 template <class T, class U, class V>
|
Chris@16
|
500 void eval_modulus(T& t, const U& u, const V& v);
|
Chris@16
|
501
|
Chris@16
|
502 template <class T>
|
Chris@16
|
503 inline void eval_modulus_default(T& t, const T& u, const T& v)
|
Chris@16
|
504 {
|
Chris@16
|
505 if(&t == &u)
|
Chris@16
|
506 eval_modulus(t, v);
|
Chris@16
|
507 else if(&t == &v)
|
Chris@16
|
508 {
|
Chris@16
|
509 T temp;
|
Chris@16
|
510 eval_modulus(temp, u, v);
|
Chris@16
|
511 temp.swap(t);
|
Chris@16
|
512 }
|
Chris@16
|
513 else
|
Chris@16
|
514 {
|
Chris@16
|
515 t = u;
|
Chris@16
|
516 eval_modulus(t, v);
|
Chris@16
|
517 }
|
Chris@16
|
518 }
|
Chris@16
|
519 template <class T, class U>
|
Chris@16
|
520 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
|
Chris@16
|
521 {
|
Chris@16
|
522 T vv;
|
Chris@16
|
523 vv = v;
|
Chris@16
|
524 eval_modulus(t, u, vv);
|
Chris@16
|
525 }
|
Chris@16
|
526 template <class T, class U>
|
Chris@16
|
527 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
|
Chris@16
|
528 {
|
Chris@16
|
529 T vv(v);
|
Chris@16
|
530 eval_modulus(t, u, vv);
|
Chris@16
|
531 }
|
Chris@16
|
532 template <class T, class U>
|
Chris@16
|
533 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
|
Chris@16
|
534 {
|
Chris@16
|
535 T uu;
|
Chris@16
|
536 uu = u;
|
Chris@16
|
537 eval_modulus(t, uu, v);
|
Chris@16
|
538 }
|
Chris@16
|
539 template <class T, class U>
|
Chris@16
|
540 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
|
Chris@16
|
541 {
|
Chris@16
|
542 T uu(u);
|
Chris@16
|
543 eval_modulus(t, uu, v);
|
Chris@16
|
544 }
|
Chris@16
|
545 template <class T, class U, class V>
|
Chris@16
|
546 inline void eval_modulus_default(T& t, const U& u, const V& v)
|
Chris@16
|
547 {
|
Chris@16
|
548 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
549 {
|
Chris@16
|
550 T temp(u);
|
Chris@16
|
551 eval_modulus(temp, v);
|
Chris@16
|
552 t = temp;
|
Chris@16
|
553 }
|
Chris@16
|
554 else
|
Chris@16
|
555 {
|
Chris@16
|
556 t = u;
|
Chris@16
|
557 eval_modulus(t, v);
|
Chris@16
|
558 }
|
Chris@16
|
559 }
|
Chris@16
|
560 template <class T, class U, class V>
|
Chris@16
|
561 inline void eval_modulus(T& t, const U& u, const V& v)
|
Chris@16
|
562 {
|
Chris@16
|
563 eval_modulus_default(t, u, v);
|
Chris@16
|
564 }
|
Chris@16
|
565
|
Chris@16
|
566 template <class T, class U, class V>
|
Chris@16
|
567 void eval_bitwise_and(T& t, const U& u, const V& v);
|
Chris@16
|
568
|
Chris@16
|
569 template <class T>
|
Chris@16
|
570 inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
|
Chris@16
|
571 {
|
Chris@16
|
572 if(&t == &v)
|
Chris@16
|
573 {
|
Chris@16
|
574 eval_bitwise_and(t, u);
|
Chris@16
|
575 }
|
Chris@16
|
576 else if(&t == &u)
|
Chris@16
|
577 {
|
Chris@16
|
578 eval_bitwise_and(t, v);
|
Chris@16
|
579 }
|
Chris@16
|
580 else
|
Chris@16
|
581 {
|
Chris@16
|
582 t = u;
|
Chris@16
|
583 eval_bitwise_and(t, v);
|
Chris@16
|
584 }
|
Chris@16
|
585 }
|
Chris@16
|
586 template <class T, class U>
|
Chris@16
|
587 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
|
Chris@16
|
588 {
|
Chris@16
|
589 T vv;
|
Chris@16
|
590 vv = v;
|
Chris@16
|
591 eval_bitwise_and(t, u, vv);
|
Chris@16
|
592 }
|
Chris@16
|
593 template <class T, class U>
|
Chris@16
|
594 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
|
Chris@16
|
595 {
|
Chris@16
|
596 T vv(v);
|
Chris@16
|
597 eval_bitwise_and(t, u, vv);
|
Chris@16
|
598 }
|
Chris@16
|
599 template <class T, class U>
|
Chris@16
|
600 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
|
Chris@16
|
601 {
|
Chris@16
|
602 eval_bitwise_and(t, v, u);
|
Chris@16
|
603 }
|
Chris@16
|
604 template <class T, class U, class V>
|
Chris@16
|
605 inline void eval_bitwise_and_default(T& t, const U& u, const V& v)
|
Chris@16
|
606 {
|
Chris@16
|
607 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
608 {
|
Chris@16
|
609 eval_bitwise_and(t, u);
|
Chris@16
|
610 }
|
Chris@16
|
611 else
|
Chris@16
|
612 {
|
Chris@16
|
613 t = u;
|
Chris@16
|
614 eval_bitwise_and(t, v);
|
Chris@16
|
615 }
|
Chris@16
|
616 }
|
Chris@16
|
617 template <class T, class U, class V>
|
Chris@16
|
618 inline void eval_bitwise_and(T& t, const U& u, const V& v)
|
Chris@16
|
619 {
|
Chris@16
|
620 eval_bitwise_and_default(t, u, v);
|
Chris@16
|
621 }
|
Chris@16
|
622
|
Chris@16
|
623 template <class T, class U, class V>
|
Chris@16
|
624 void eval_bitwise_or(T& t, const U& u, const V& v);
|
Chris@16
|
625
|
Chris@16
|
626 template <class T>
|
Chris@16
|
627 inline void eval_bitwise_or_default(T& t, const T& u, const T& v)
|
Chris@16
|
628 {
|
Chris@16
|
629 if(&t == &v)
|
Chris@16
|
630 {
|
Chris@16
|
631 eval_bitwise_or(t, u);
|
Chris@16
|
632 }
|
Chris@16
|
633 else if(&t == &u)
|
Chris@16
|
634 {
|
Chris@16
|
635 eval_bitwise_or(t, v);
|
Chris@16
|
636 }
|
Chris@16
|
637 else
|
Chris@16
|
638 {
|
Chris@16
|
639 t = u;
|
Chris@16
|
640 eval_bitwise_or(t, v);
|
Chris@16
|
641 }
|
Chris@16
|
642 }
|
Chris@16
|
643 template <class T, class U>
|
Chris@16
|
644 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
|
Chris@16
|
645 {
|
Chris@16
|
646 T vv;
|
Chris@16
|
647 vv = v;
|
Chris@16
|
648 eval_bitwise_or(t, u, vv);
|
Chris@16
|
649 }
|
Chris@16
|
650 template <class T, class U>
|
Chris@16
|
651 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
|
Chris@16
|
652 {
|
Chris@16
|
653 T vv(v);
|
Chris@16
|
654 eval_bitwise_or(t, u, vv);
|
Chris@16
|
655 }
|
Chris@16
|
656 template <class T, class U>
|
Chris@16
|
657 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
|
Chris@16
|
658 {
|
Chris@16
|
659 eval_bitwise_or(t, v, u);
|
Chris@16
|
660 }
|
Chris@16
|
661 template <class T, class U, class V>
|
Chris@16
|
662 inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
|
Chris@16
|
663 {
|
Chris@16
|
664 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
665 {
|
Chris@16
|
666 eval_bitwise_or(t, u);
|
Chris@16
|
667 }
|
Chris@16
|
668 else
|
Chris@16
|
669 {
|
Chris@16
|
670 t = u;
|
Chris@16
|
671 eval_bitwise_or(t, v);
|
Chris@16
|
672 }
|
Chris@16
|
673 }
|
Chris@16
|
674 template <class T, class U, class V>
|
Chris@16
|
675 inline void eval_bitwise_or(T& t, const U& u, const V& v)
|
Chris@16
|
676 {
|
Chris@16
|
677 eval_bitwise_or_default(t, u, v);
|
Chris@16
|
678 }
|
Chris@16
|
679
|
Chris@16
|
680 template <class T, class U, class V>
|
Chris@16
|
681 void eval_bitwise_xor(T& t, const U& u, const V& v);
|
Chris@16
|
682
|
Chris@16
|
683 template <class T>
|
Chris@16
|
684 inline void eval_bitwise_xor_default(T& t, const T& u, const T& v)
|
Chris@16
|
685 {
|
Chris@16
|
686 if(&t == &v)
|
Chris@16
|
687 {
|
Chris@16
|
688 eval_bitwise_xor(t, u);
|
Chris@16
|
689 }
|
Chris@16
|
690 else if(&t == &u)
|
Chris@16
|
691 {
|
Chris@16
|
692 eval_bitwise_xor(t, v);
|
Chris@16
|
693 }
|
Chris@16
|
694 else
|
Chris@16
|
695 {
|
Chris@16
|
696 t = u;
|
Chris@16
|
697 eval_bitwise_xor(t, v);
|
Chris@16
|
698 }
|
Chris@16
|
699 }
|
Chris@16
|
700 template <class T, class U>
|
Chris@16
|
701 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
|
Chris@16
|
702 {
|
Chris@16
|
703 T vv;
|
Chris@16
|
704 vv = v;
|
Chris@16
|
705 eval_bitwise_xor(t, u, vv);
|
Chris@16
|
706 }
|
Chris@16
|
707 template <class T, class U>
|
Chris@16
|
708 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
|
Chris@16
|
709 {
|
Chris@16
|
710 T vv(v);
|
Chris@16
|
711 eval_bitwise_xor(t, u, vv);
|
Chris@16
|
712 }
|
Chris@16
|
713 template <class T, class U>
|
Chris@16
|
714 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
|
Chris@16
|
715 {
|
Chris@16
|
716 eval_bitwise_xor(t, v, u);
|
Chris@16
|
717 }
|
Chris@16
|
718 template <class T, class U, class V>
|
Chris@16
|
719 inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
|
Chris@16
|
720 {
|
Chris@16
|
721 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
|
Chris@16
|
722 {
|
Chris@16
|
723 eval_bitwise_xor(t, u);
|
Chris@16
|
724 }
|
Chris@16
|
725 else
|
Chris@16
|
726 {
|
Chris@16
|
727 t = u;
|
Chris@16
|
728 eval_bitwise_xor(t, v);
|
Chris@16
|
729 }
|
Chris@16
|
730 }
|
Chris@16
|
731 template <class T, class U, class V>
|
Chris@16
|
732 inline void eval_bitwise_xor(T& t, const U& u, const V& v)
|
Chris@16
|
733 {
|
Chris@16
|
734 eval_bitwise_xor_default(t, u, v);
|
Chris@16
|
735 }
|
Chris@16
|
736
|
Chris@16
|
737 template <class T>
|
Chris@16
|
738 inline void eval_increment(T& val)
|
Chris@16
|
739 {
|
Chris@16
|
740 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
|
Chris@16
|
741 eval_add(val, static_cast<ui_type>(1u));
|
Chris@16
|
742 }
|
Chris@16
|
743 template <class T>
|
Chris@16
|
744 inline void eval_decrement(T& val)
|
Chris@16
|
745 {
|
Chris@16
|
746 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
|
Chris@16
|
747 eval_subtract(val, static_cast<ui_type>(1u));
|
Chris@16
|
748 }
|
Chris@16
|
749
|
Chris@16
|
750 template <class T, class V>
|
Chris@16
|
751 inline void eval_left_shift(T& result, const T& arg, const V val)
|
Chris@16
|
752 {
|
Chris@16
|
753 result = arg;
|
Chris@16
|
754 eval_left_shift(result, val);
|
Chris@16
|
755 }
|
Chris@16
|
756
|
Chris@16
|
757 template <class T, class V>
|
Chris@16
|
758 inline void eval_right_shift(T& result, const T& arg, const V val)
|
Chris@16
|
759 {
|
Chris@16
|
760 result = arg;
|
Chris@16
|
761 eval_right_shift(result, val);
|
Chris@16
|
762 }
|
Chris@16
|
763
|
Chris@16
|
764 template <class T>
|
Chris@16
|
765 inline bool eval_is_zero(const T& val)
|
Chris@16
|
766 {
|
Chris@16
|
767 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
|
Chris@16
|
768 return val.compare(static_cast<ui_type>(0)) == 0;
|
Chris@16
|
769 }
|
Chris@16
|
770 template <class T>
|
Chris@16
|
771 inline int eval_get_sign(const T& val)
|
Chris@16
|
772 {
|
Chris@16
|
773 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
|
Chris@16
|
774 return val.compare(static_cast<ui_type>(0));
|
Chris@16
|
775 }
|
Chris@16
|
776
|
Chris@16
|
777 template <class T, class V>
|
Chris@16
|
778 inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl::int_<number_kind_rational>&)
|
Chris@16
|
779 {
|
Chris@16
|
780 result = v1;
|
Chris@16
|
781 T t;
|
Chris@16
|
782 t = v2;
|
Chris@16
|
783 eval_divide(result, t);
|
Chris@16
|
784 }
|
Chris@16
|
785
|
Chris@16
|
786 template <class T, class V>
|
Chris@16
|
787 inline void assign_components(T& result, const V& v1, const V& v2)
|
Chris@16
|
788 {
|
Chris@16
|
789 return assign_components_imp(result, v1, v2, typename number_category<T>::type());
|
Chris@16
|
790 }
|
Chris@16
|
791
|
Chris@16
|
792 template <class R, int b>
|
Chris@16
|
793 struct has_enough_bits
|
Chris@16
|
794 {
|
Chris@16
|
795 template <class T>
|
Chris@16
|
796 struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >{};
|
Chris@16
|
797 };
|
Chris@16
|
798
|
Chris@16
|
799 template <class R>
|
Chris@16
|
800 struct terminal
|
Chris@16
|
801 {
|
Chris@16
|
802 terminal(const R& v) : value(v){}
|
Chris@16
|
803 terminal(){}
|
Chris@16
|
804 terminal& operator = (R val) { value = val; }
|
Chris@16
|
805 R value;
|
Chris@16
|
806 operator R()const { return value; }
|
Chris@16
|
807 };
|
Chris@16
|
808
|
Chris@16
|
809 template<class R, class B>
|
Chris@16
|
810 struct calculate_next_larger_type
|
Chris@16
|
811 {
|
Chris@16
|
812 // Find which list we're looking through:
|
Chris@16
|
813 typedef typename mpl::if_<
|
Chris@16
|
814 is_signed<R>,
|
Chris@16
|
815 typename B::signed_types,
|
Chris@16
|
816 typename mpl::if_<
|
Chris@16
|
817 is_unsigned<R>,
|
Chris@16
|
818 typename B::unsigned_types,
|
Chris@16
|
819 typename B::float_types
|
Chris@16
|
820 >::type
|
Chris@16
|
821 >::type list_type;
|
Chris@16
|
822 // A predicate to find a type with enough bits:
|
Chris@16
|
823 typedef typename has_enough_bits<R, std::numeric_limits<R>::digits>::template type<mpl::_> pred_type;
|
Chris@16
|
824 // See if the last type is in the list, if so we have to start after this:
|
Chris@16
|
825 typedef typename mpl::find_if<
|
Chris@16
|
826 list_type,
|
Chris@16
|
827 is_same<R, mpl::_>
|
Chris@16
|
828 >::type start_last;
|
Chris@16
|
829 // Where we're starting from, either the start of the sequence or the last type found:
|
Chris@16
|
830 typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
|
Chris@16
|
831 // The range we're searching:
|
Chris@16
|
832 typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::type> range;
|
Chris@16
|
833 // Find the next type:
|
Chris@16
|
834 typedef typename mpl::find_if<
|
Chris@16
|
835 range,
|
Chris@16
|
836 pred_type
|
Chris@16
|
837 >::type iter_type;
|
Chris@16
|
838 // Either the next type, or a "terminal" to indicate we've run out of types to search:
|
Chris@16
|
839 typedef typename mpl::eval_if<
|
Chris@16
|
840 is_same<typename mpl::end<list_type>::type, iter_type>,
|
Chris@16
|
841 mpl::identity<terminal<R> >,
|
Chris@16
|
842 mpl::deref<iter_type>
|
Chris@16
|
843 >::type type;
|
Chris@16
|
844 };
|
Chris@16
|
845
|
Chris@16
|
846 template <class R, class T>
|
Chris@16
|
847 inline bool check_in_range(const T& t)
|
Chris@16
|
848 {
|
Chris@16
|
849 // Can t fit in an R?
|
Chris@16
|
850 if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
|
Chris@16
|
851 return true;
|
Chris@16
|
852 return false;
|
Chris@16
|
853 }
|
Chris@16
|
854
|
Chris@16
|
855 template <class R, class T>
|
Chris@16
|
856 inline bool check_in_range(const terminal<T>&)
|
Chris@16
|
857 {
|
Chris@16
|
858 return false;
|
Chris@16
|
859 }
|
Chris@16
|
860
|
Chris@16
|
861 template <class R, class B>
|
Chris@16
|
862 inline void eval_convert_to(R* result, const B& backend)
|
Chris@16
|
863 {
|
Chris@16
|
864 typedef typename calculate_next_larger_type<R, B>::type next_type;
|
Chris@16
|
865 next_type n;
|
Chris@16
|
866 eval_convert_to(&n, backend);
|
Chris@16
|
867 if(check_in_range<R>(n))
|
Chris@16
|
868 {
|
Chris@16
|
869 *result = (std::numeric_limits<R>::max)();
|
Chris@16
|
870 }
|
Chris@16
|
871 else
|
Chris@16
|
872 *result = static_cast<R>(n);
|
Chris@16
|
873 }
|
Chris@16
|
874
|
Chris@16
|
875 template <class R, class B>
|
Chris@16
|
876 inline void eval_convert_to(terminal<R>* result, const B& backend)
|
Chris@16
|
877 {
|
Chris@16
|
878 //
|
Chris@16
|
879 // We ran out of types to try for the conversion, try
|
Chris@16
|
880 // a lexical_cast and hope for the best:
|
Chris@16
|
881 //
|
Chris@16
|
882 result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
|
Chris@16
|
883 }
|
Chris@16
|
884
|
Chris@16
|
885 template <class B>
|
Chris@16
|
886 inline void eval_convert_to(std::string* result, const B& backend)
|
Chris@16
|
887 {
|
Chris@16
|
888 *result = backend.str(0, std::ios_base::fmtflags(0));
|
Chris@16
|
889 }
|
Chris@16
|
890 //
|
Chris@16
|
891 // Functions:
|
Chris@16
|
892 //
|
Chris@16
|
893 template <class T>
|
Chris@16
|
894 void eval_abs(T& result, const T& arg)
|
Chris@16
|
895 {
|
Chris@16
|
896 typedef typename T::signed_types type_list;
|
Chris@16
|
897 typedef typename mpl::front<type_list>::type front;
|
Chris@16
|
898 result = arg;
|
Chris@16
|
899 if(arg.compare(front(0)) < 0)
|
Chris@16
|
900 result.negate();
|
Chris@16
|
901 }
|
Chris@16
|
902 template <class T>
|
Chris@16
|
903 void eval_fabs(T& result, const T& arg)
|
Chris@16
|
904 {
|
Chris@16
|
905 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
|
Chris@16
|
906 typedef typename T::signed_types type_list;
|
Chris@16
|
907 typedef typename mpl::front<type_list>::type front;
|
Chris@16
|
908 result = arg;
|
Chris@16
|
909 if(arg.compare(front(0)) < 0)
|
Chris@16
|
910 result.negate();
|
Chris@16
|
911 }
|
Chris@16
|
912
|
Chris@16
|
913 template <class Backend>
|
Chris@16
|
914 inline int eval_fpclassify(const Backend& arg)
|
Chris@16
|
915 {
|
Chris@16
|
916 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
|
Chris@16
|
917 return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
|
Chris@16
|
918 }
|
Chris@16
|
919
|
Chris@16
|
920 template <class T>
|
Chris@16
|
921 inline void eval_fmod(T& result, const T& a, const T& b)
|
Chris@16
|
922 {
|
Chris@16
|
923 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
|
Chris@16
|
924 if((&result == &a) || (&result == &b))
|
Chris@16
|
925 {
|
Chris@16
|
926 T temp;
|
Chris@16
|
927 eval_fmod(temp, a, b);
|
Chris@16
|
928 result = temp;
|
Chris@16
|
929 return;
|
Chris@16
|
930 }
|
Chris@16
|
931 T n;
|
Chris@16
|
932 eval_divide(result, a, b);
|
Chris@16
|
933 if(eval_get_sign(a) < 0)
|
Chris@16
|
934 eval_ceil(n, result);
|
Chris@16
|
935 else
|
Chris@16
|
936 eval_floor(n, result);
|
Chris@16
|
937 eval_multiply(n, b);
|
Chris@16
|
938 eval_subtract(result, a, n);
|
Chris@16
|
939 }
|
Chris@16
|
940 template<class T, class A>
|
Chris@16
|
941 inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
|
Chris@16
|
942 {
|
Chris@16
|
943 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
|
Chris@16
|
944 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
|
Chris@16
|
945 cast_type c;
|
Chris@16
|
946 c = a;
|
Chris@16
|
947 eval_fmod(result, x, c);
|
Chris@16
|
948 }
|
Chris@16
|
949
|
Chris@16
|
950 template<class T, class A>
|
Chris@16
|
951 inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
|
Chris@16
|
952 {
|
Chris@16
|
953 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
|
Chris@16
|
954 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
|
Chris@16
|
955 cast_type c;
|
Chris@16
|
956 c = x;
|
Chris@16
|
957 eval_fmod(result, c, a);
|
Chris@16
|
958 }
|
Chris@16
|
959
|
Chris@16
|
960 template <class T>
|
Chris@16
|
961 inline void eval_trunc(T& result, const T& a)
|
Chris@16
|
962 {
|
Chris@16
|
963 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
|
Chris@16
|
964 int c = eval_fpclassify(a);
|
Chris@101
|
965 if(c == (int)FP_NAN || c == (int)FP_INFINITE)
|
Chris@16
|
966 {
|
Chris@16
|
967 result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
|
Chris@16
|
968 return;
|
Chris@16
|
969 }
|
Chris@16
|
970 if(eval_get_sign(a) < 0)
|
Chris@16
|
971 eval_ceil(result, a);
|
Chris@16
|
972 else
|
Chris@16
|
973 eval_floor(result, a);
|
Chris@16
|
974 }
|
Chris@16
|
975
|
Chris@16
|
976 template <class T>
|
Chris@16
|
977 inline void eval_round(T& result, const T& a)
|
Chris@16
|
978 {
|
Chris@16
|
979 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
|
Chris@16
|
980 typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
|
Chris@16
|
981 int c = eval_fpclassify(a);
|
Chris@101
|
982 if((c == (int)FP_NAN) || (c == (int)FP_INFINITE))
|
Chris@16
|
983 {
|
Chris@16
|
984 result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
|
Chris@16
|
985 return;
|
Chris@16
|
986 }
|
Chris@16
|
987 if(eval_get_sign(a) < 0)
|
Chris@16
|
988 {
|
Chris@16
|
989 eval_subtract(result, a, fp_type(0.5f));
|
Chris@16
|
990 eval_ceil(result, result);
|
Chris@16
|
991 }
|
Chris@16
|
992 else
|
Chris@16
|
993 {
|
Chris@16
|
994 eval_add(result, a, fp_type(0.5f));
|
Chris@16
|
995 eval_floor(result, result);
|
Chris@16
|
996 }
|
Chris@16
|
997 }
|
Chris@16
|
998
|
Chris@16
|
999 template <class B>
|
Chris@16
|
1000 void eval_lcm(B& result, const B& a, const B& b);
|
Chris@16
|
1001 template <class B>
|
Chris@16
|
1002 void eval_gcd(B& result, const B& a, const B& b);
|
Chris@16
|
1003
|
Chris@16
|
1004 template <class T, class Arithmetic>
|
Chris@16
|
1005 inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
|
Chris@16
|
1006 {
|
Chris@16
|
1007 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
|
Chris@16
|
1008 using default_ops::eval_gcd;
|
Chris@16
|
1009 T t;
|
Chris@16
|
1010 t = static_cast<si_type>(b);
|
Chris@16
|
1011 eval_gcd(result, a, t);
|
Chris@16
|
1012 }
|
Chris@16
|
1013 template <class T, class Arithmetic>
|
Chris@16
|
1014 inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
|
Chris@16
|
1015 {
|
Chris@16
|
1016 eval_gcd(result, b, a);
|
Chris@16
|
1017 }
|
Chris@16
|
1018 template <class T, class Arithmetic>
|
Chris@16
|
1019 inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
|
Chris@16
|
1020 {
|
Chris@16
|
1021 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
|
Chris@16
|
1022 using default_ops::eval_lcm;
|
Chris@16
|
1023 T t;
|
Chris@16
|
1024 t = static_cast<si_type>(b);
|
Chris@16
|
1025 eval_lcm(result, a, t);
|
Chris@16
|
1026 }
|
Chris@16
|
1027 template <class T, class Arithmetic>
|
Chris@16
|
1028 inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
|
Chris@16
|
1029 {
|
Chris@16
|
1030 eval_lcm(result, b, a);
|
Chris@16
|
1031 }
|
Chris@16
|
1032
|
Chris@16
|
1033 template <class T>
|
Chris@16
|
1034 inline unsigned eval_lsb(const T& val)
|
Chris@16
|
1035 {
|
Chris@16
|
1036 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
|
Chris@16
|
1037 int c = eval_get_sign(val);
|
Chris@16
|
1038 if(c == 0)
|
Chris@16
|
1039 {
|
Chris@16
|
1040 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
|
Chris@16
|
1041 }
|
Chris@16
|
1042 if(c < 0)
|
Chris@16
|
1043 {
|
Chris@16
|
1044 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
|
Chris@16
|
1045 }
|
Chris@16
|
1046 unsigned result = 0;
|
Chris@16
|
1047 T mask, t;
|
Chris@16
|
1048 mask = ui_type(1);
|
Chris@16
|
1049 do
|
Chris@16
|
1050 {
|
Chris@16
|
1051 eval_bitwise_and(t, mask, val);
|
Chris@16
|
1052 ++result;
|
Chris@16
|
1053 eval_left_shift(mask, 1);
|
Chris@16
|
1054 }
|
Chris@16
|
1055 while(eval_is_zero(t));
|
Chris@16
|
1056
|
Chris@16
|
1057 return --result;
|
Chris@16
|
1058 }
|
Chris@16
|
1059
|
Chris@16
|
1060 template <class T>
|
Chris@16
|
1061 inline int eval_msb(const T& val)
|
Chris@16
|
1062 {
|
Chris@16
|
1063 int c = eval_get_sign(val);
|
Chris@16
|
1064 if(c == 0)
|
Chris@16
|
1065 {
|
Chris@16
|
1066 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
|
Chris@16
|
1067 }
|
Chris@16
|
1068 if(c < 0)
|
Chris@16
|
1069 {
|
Chris@16
|
1070 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
|
Chris@16
|
1071 }
|
Chris@16
|
1072 //
|
Chris@16
|
1073 // This implementation is really really rubbish - it does
|
Chris@16
|
1074 // a linear scan for the most-significant-bit. We should really
|
Chris@16
|
1075 // do a binary search, but as none of our backends actually needs
|
Chris@16
|
1076 // this implementation, we'll leave it for now. In fact for most
|
Chris@16
|
1077 // backends it's likely that there will always be a more efficient
|
Chris@16
|
1078 // native implementation possible.
|
Chris@16
|
1079 //
|
Chris@16
|
1080 unsigned result = 0;
|
Chris@16
|
1081 T t(val);
|
Chris@16
|
1082 while(!eval_is_zero(t))
|
Chris@16
|
1083 {
|
Chris@16
|
1084 eval_right_shift(t, 1);
|
Chris@16
|
1085 ++result;
|
Chris@16
|
1086 }
|
Chris@16
|
1087 return --result;
|
Chris@16
|
1088 }
|
Chris@16
|
1089
|
Chris@16
|
1090 template <class T>
|
Chris@16
|
1091 inline bool eval_bit_test(const T& val, unsigned index)
|
Chris@16
|
1092 {
|
Chris@16
|
1093 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
|
Chris@16
|
1094 T mask, t;
|
Chris@16
|
1095 mask = ui_type(1);
|
Chris@16
|
1096 eval_left_shift(mask, index);
|
Chris@16
|
1097 eval_bitwise_and(t, mask, val);
|
Chris@16
|
1098 return !eval_is_zero(t);
|
Chris@16
|
1099 }
|
Chris@16
|
1100
|
Chris@16
|
1101 template <class T>
|
Chris@16
|
1102 inline void eval_bit_set(T& val, unsigned index)
|
Chris@16
|
1103 {
|
Chris@16
|
1104 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
|
Chris@16
|
1105 T mask;
|
Chris@16
|
1106 mask = ui_type(1);
|
Chris@16
|
1107 eval_left_shift(mask, index);
|
Chris@16
|
1108 eval_bitwise_or(val, mask);
|
Chris@16
|
1109 }
|
Chris@16
|
1110
|
Chris@16
|
1111 template <class T>
|
Chris@16
|
1112 inline void eval_bit_flip(T& val, unsigned index)
|
Chris@16
|
1113 {
|
Chris@16
|
1114 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
|
Chris@16
|
1115 T mask;
|
Chris@16
|
1116 mask = ui_type(1);
|
Chris@16
|
1117 eval_left_shift(mask, index);
|
Chris@16
|
1118 eval_bitwise_xor(val, mask);
|
Chris@16
|
1119 }
|
Chris@16
|
1120
|
Chris@16
|
1121 template <class T>
|
Chris@16
|
1122 inline void eval_bit_unset(T& val, unsigned index)
|
Chris@16
|
1123 {
|
Chris@16
|
1124 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
|
Chris@16
|
1125 T mask, t;
|
Chris@16
|
1126 mask = ui_type(1);
|
Chris@16
|
1127 eval_left_shift(mask, index);
|
Chris@16
|
1128 eval_bitwise_and(t, mask, val);
|
Chris@16
|
1129 if(!eval_is_zero(t))
|
Chris@16
|
1130 eval_bitwise_xor(val, mask);
|
Chris@16
|
1131 }
|
Chris@16
|
1132
|
Chris@16
|
1133 template <class B>
|
Chris@16
|
1134 void eval_integer_sqrt(B& s, B& r, const B& x)
|
Chris@16
|
1135 {
|
Chris@16
|
1136 //
|
Chris@16
|
1137 // This is slow bit-by-bit integer square root, see for example
|
Chris@16
|
1138 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
|
Chris@16
|
1139 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
|
Chris@16
|
1140 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
|
Chris@16
|
1141 // at some point.
|
Chris@16
|
1142 //
|
Chris@16
|
1143 typedef typename boost::multiprecision::detail::canonical<unsigned char, B>::type ui_type;
|
Chris@16
|
1144
|
Chris@16
|
1145 s = ui_type(0u);
|
Chris@16
|
1146 if(eval_get_sign(x) == 0)
|
Chris@16
|
1147 {
|
Chris@16
|
1148 r = ui_type(0u);
|
Chris@16
|
1149 return;
|
Chris@16
|
1150 }
|
Chris@16
|
1151 int g = eval_msb(x);
|
Chris@16
|
1152 if(g == 0)
|
Chris@16
|
1153 {
|
Chris@16
|
1154 r = ui_type(1);
|
Chris@16
|
1155 return;
|
Chris@16
|
1156 }
|
Chris@16
|
1157
|
Chris@16
|
1158 B t;
|
Chris@16
|
1159 r = x;
|
Chris@16
|
1160 g /= 2;
|
Chris@16
|
1161 int org_g = g;
|
Chris@16
|
1162 eval_bit_set(s, g);
|
Chris@16
|
1163 eval_bit_set(t, 2 * g);
|
Chris@16
|
1164 eval_subtract(r, x, t);
|
Chris@16
|
1165 --g;
|
Chris@16
|
1166 if(eval_get_sign(r) == 0)
|
Chris@16
|
1167 return;
|
Chris@16
|
1168 int msbr = eval_msb(r);
|
Chris@16
|
1169 do
|
Chris@16
|
1170 {
|
Chris@16
|
1171 if(msbr >= org_g + g + 1)
|
Chris@16
|
1172 {
|
Chris@16
|
1173 t = s;
|
Chris@16
|
1174 eval_left_shift(t, g + 1);
|
Chris@16
|
1175 eval_bit_set(t, 2 * g);
|
Chris@16
|
1176 if(t.compare(r) <= 0)
|
Chris@16
|
1177 {
|
Chris@16
|
1178 eval_bit_set(s, g);
|
Chris@16
|
1179 eval_subtract(r, t);
|
Chris@16
|
1180 if(eval_get_sign(r) == 0)
|
Chris@16
|
1181 return;
|
Chris@16
|
1182 msbr = eval_msb(r);
|
Chris@16
|
1183 }
|
Chris@16
|
1184 }
|
Chris@16
|
1185 --g;
|
Chris@16
|
1186 }
|
Chris@16
|
1187 while(g >= 0);
|
Chris@16
|
1188 }
|
Chris@16
|
1189
|
Chris@16
|
1190 //
|
Chris@16
|
1191 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
|
Chris@16
|
1192 //
|
Chris@16
|
1193 template <class T>
|
Chris@16
|
1194 typename enable_if_c<sizeof(T) == 0>::type eval_floor();
|
Chris@16
|
1195 template <class T>
|
Chris@16
|
1196 typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
|
Chris@16
|
1197 template <class T>
|
Chris@16
|
1198 typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
|
Chris@16
|
1199 template <class T>
|
Chris@16
|
1200 typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
|
Chris@16
|
1201 template <class T>
|
Chris@16
|
1202 typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
|
Chris@16
|
1203 template <class T>
|
Chris@16
|
1204 typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
|
Chris@101
|
1205
|
Chris@101
|
1206 //
|
Chris@101
|
1207 // eval_logb and eval_scalbn simply assume base 2 and forward to
|
Chris@101
|
1208 // eval_ldexp and eval_frexp:
|
Chris@101
|
1209 //
|
Chris@101
|
1210 template <class B>
|
Chris@101
|
1211 inline typename B::exponent_type eval_ilogb(const B& val)
|
Chris@101
|
1212 {
|
Chris@101
|
1213 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
|
Chris@101
|
1214 typename B::exponent_type e;
|
Chris@101
|
1215 B result;
|
Chris@101
|
1216 eval_frexp(result, val, &e);
|
Chris@101
|
1217 return e - 1;
|
Chris@101
|
1218 }
|
Chris@101
|
1219 template <class B>
|
Chris@101
|
1220 inline void eval_logb(B& result, const B& val)
|
Chris@101
|
1221 {
|
Chris@101
|
1222 typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, long long, boost::intmax_t>::type max_t;
|
Chris@101
|
1223 result = static_cast<max_t>(eval_ilogb(val));
|
Chris@101
|
1224 }
|
Chris@101
|
1225 template <class B, class A>
|
Chris@101
|
1226 inline void eval_scalbn(B& result, const B& val, A e)
|
Chris@101
|
1227 {
|
Chris@101
|
1228 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
|
Chris@101
|
1229 eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
|
Chris@101
|
1230 }
|
Chris@16
|
1231 //
|
Chris@16
|
1232 // These functions are implemented in separate files, but expanded inline here,
|
Chris@16
|
1233 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
|
Chris@16
|
1234 //
|
Chris@16
|
1235 #include <boost/multiprecision/detail/functions/constants.hpp>
|
Chris@16
|
1236 #include <boost/multiprecision/detail/functions/pow.hpp>
|
Chris@16
|
1237 #include <boost/multiprecision/detail/functions/trig.hpp>
|
Chris@16
|
1238
|
Chris@16
|
1239 }
|
Chris@16
|
1240
|
Chris@16
|
1241 } // namespace multiprecision
|
Chris@16
|
1242 namespace math{
|
Chris@16
|
1243 //
|
Chris@16
|
1244 // Default versions of floating point classification routines:
|
Chris@16
|
1245 //
|
Chris@16
|
1246 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1247 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1248 {
|
Chris@16
|
1249 using multiprecision::default_ops::eval_fpclassify;
|
Chris@16
|
1250 return eval_fpclassify(arg.backend());
|
Chris@16
|
1251 }
|
Chris@16
|
1252 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1253 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1254 {
|
Chris@16
|
1255 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1256 return (fpclassify)(value_type(arg));
|
Chris@16
|
1257 }
|
Chris@16
|
1258 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1259 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1260 {
|
Chris@16
|
1261 int v = (fpclassify)(arg);
|
Chris@101
|
1262 return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
|
Chris@16
|
1263 }
|
Chris@16
|
1264 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1265 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1266 {
|
Chris@16
|
1267 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1268 return (isfinite)(value_type(arg));
|
Chris@16
|
1269 }
|
Chris@16
|
1270 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1271 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1272 {
|
Chris@101
|
1273 return (fpclassify)(arg) == (int)FP_NAN;
|
Chris@16
|
1274 }
|
Chris@16
|
1275 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1276 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1277 {
|
Chris@16
|
1278 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1279 return (isnan)(value_type(arg));
|
Chris@16
|
1280 }
|
Chris@16
|
1281 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1282 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1283 {
|
Chris@101
|
1284 return (fpclassify)(arg) == (int)FP_INFINITE;
|
Chris@16
|
1285 }
|
Chris@16
|
1286 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1287 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1288 {
|
Chris@16
|
1289 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1290 return (isinf)(value_type(arg));
|
Chris@16
|
1291 }
|
Chris@16
|
1292 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1293 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1294 {
|
Chris@101
|
1295 return (fpclassify)(arg) == (int)FP_NORMAL;
|
Chris@16
|
1296 }
|
Chris@16
|
1297 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1298 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1299 {
|
Chris@16
|
1300 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1301 return (isnormal)(value_type(arg));
|
Chris@16
|
1302 }
|
Chris@16
|
1303
|
Chris@16
|
1304 } // namespace math
|
Chris@16
|
1305 namespace multiprecision{
|
Chris@16
|
1306
|
Chris@16
|
1307 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1308 inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1309 {
|
Chris@16
|
1310 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1311 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1312 using default_ops::eval_add;
|
Chris@16
|
1313 eval_add(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1314 return result;
|
Chris@16
|
1315 }
|
Chris@16
|
1316
|
Chris@16
|
1317 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1318 inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1319 {
|
Chris@16
|
1320 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1321 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1322 using default_ops::eval_subtract;
|
Chris@16
|
1323 eval_subtract(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1324 return result;
|
Chris@16
|
1325 }
|
Chris@16
|
1326
|
Chris@16
|
1327 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1328 inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1329 {
|
Chris@16
|
1330 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1331 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1332 using default_ops::eval_multiply;
|
Chris@16
|
1333 eval_multiply(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1334 return result;
|
Chris@16
|
1335 }
|
Chris@16
|
1336
|
Chris@16
|
1337 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1338 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1339 add(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1340 {
|
Chris@16
|
1341 using default_ops::eval_add;
|
Chris@16
|
1342 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1343 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1344 return result;
|
Chris@16
|
1345 }
|
Chris@16
|
1346
|
Chris@16
|
1347 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1348 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1349 subtract(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1350 {
|
Chris@16
|
1351 using default_ops::eval_subtract;
|
Chris@16
|
1352 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1353 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1354 return result;
|
Chris@16
|
1355 }
|
Chris@16
|
1356
|
Chris@16
|
1357 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1358 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1359 multiply(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1360 {
|
Chris@16
|
1361 using default_ops::eval_multiply;
|
Chris@16
|
1362 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1363 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1364 return result;
|
Chris@16
|
1365 }
|
Chris@16
|
1366
|
Chris@16
|
1367 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1368 inline typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1369 {
|
Chris@16
|
1370 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1371 return BOOST_MP_MOVE(trunc(number_type(v), pol));
|
Chris@16
|
1372 }
|
Chris@16
|
1373
|
Chris@16
|
1374 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1375 inline number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
|
Chris@16
|
1376 {
|
Chris@16
|
1377 using default_ops::eval_trunc;
|
Chris@16
|
1378 number<Backend, ExpressionTemplates> result;
|
Chris@16
|
1379 eval_trunc(result.backend(), v.backend());
|
Chris@16
|
1380 return BOOST_MP_MOVE(result);
|
Chris@16
|
1381 }
|
Chris@16
|
1382
|
Chris@16
|
1383 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1384 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1385 {
|
Chris@16
|
1386 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1387 number_type r = trunc(v, pol);
|
Chris@16
|
1388 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1389 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
|
Chris@16
|
1390 return r.template convert_to<int>();
|
Chris@16
|
1391 }
|
Chris@16
|
1392 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1393 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1394 {
|
Chris@16
|
1395 return itrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1396 }
|
Chris@16
|
1397 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1398 inline int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1399 {
|
Chris@16
|
1400 number<Backend, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1401 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1402 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
|
Chris@16
|
1403 return r.template convert_to<int>();
|
Chris@16
|
1404 }
|
Chris@16
|
1405 template <class Backend, expression_template_option ExpressionTemplates>
|
Chris@16
|
1406 inline int itrunc(const number<Backend, ExpressionTemplates>& v)
|
Chris@16
|
1407 {
|
Chris@16
|
1408 return itrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1409 }
|
Chris@16
|
1410 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1411 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1412 {
|
Chris@16
|
1413 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1414 number_type r = trunc(v, pol);
|
Chris@16
|
1415 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1416 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
|
Chris@16
|
1417 return r.template convert_to<long>();
|
Chris@16
|
1418 }
|
Chris@16
|
1419 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1420 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1421 {
|
Chris@16
|
1422 return ltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1423 }
|
Chris@16
|
1424 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1425 inline long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1426 {
|
Chris@16
|
1427 number<T, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1428 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1429 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
|
Chris@16
|
1430 return r.template convert_to<long>();
|
Chris@16
|
1431 }
|
Chris@16
|
1432 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1433 inline long ltrunc(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1434 {
|
Chris@16
|
1435 return ltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1436 }
|
Chris@16
|
1437 #ifndef BOOST_NO_LONG_LONG
|
Chris@16
|
1438 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1439 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1440 {
|
Chris@16
|
1441 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1442 number_type r = trunc(v, pol);
|
Chris@16
|
1443 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1444 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
|
Chris@16
|
1445 return r.template convert_to<long long>();
|
Chris@16
|
1446 }
|
Chris@16
|
1447 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1448 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1449 {
|
Chris@16
|
1450 return lltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1451 }
|
Chris@16
|
1452 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1453 inline long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1454 {
|
Chris@16
|
1455 number<T, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1456 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1457 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
|
Chris@16
|
1458 return r.template convert_to<long long>();
|
Chris@16
|
1459 }
|
Chris@16
|
1460 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1461 inline long long lltrunc(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1462 {
|
Chris@16
|
1463 return lltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1464 }
|
Chris@16
|
1465 #endif
|
Chris@16
|
1466 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1467 inline typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1468 {
|
Chris@16
|
1469 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1470 return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
|
Chris@16
|
1471 }
|
Chris@16
|
1472 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1473 inline number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
|
Chris@16
|
1474 {
|
Chris@16
|
1475 using default_ops::eval_round;
|
Chris@16
|
1476 number<T, ExpressionTemplates> result;
|
Chris@16
|
1477 eval_round(result.backend(), v.backend());
|
Chris@16
|
1478 return BOOST_MP_MOVE(result);
|
Chris@16
|
1479 }
|
Chris@16
|
1480
|
Chris@16
|
1481 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1482 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1483 {
|
Chris@16
|
1484 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1485 number_type r = round(v, pol);
|
Chris@16
|
1486 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1487 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
|
Chris@16
|
1488 return r.template convert_to<int>();
|
Chris@16
|
1489 }
|
Chris@16
|
1490 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1491 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1492 {
|
Chris@16
|
1493 return iround(v, boost::math::policies::policy<>());
|
Chris@16
|
1494 }
|
Chris@16
|
1495 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1496 inline int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1497 {
|
Chris@16
|
1498 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1499 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1500 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
|
Chris@16
|
1501 return r.template convert_to<int>();
|
Chris@16
|
1502 }
|
Chris@16
|
1503 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1504 inline int iround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1505 {
|
Chris@16
|
1506 return iround(v, boost::math::policies::policy<>());
|
Chris@16
|
1507 }
|
Chris@16
|
1508 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1509 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1510 {
|
Chris@16
|
1511 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1512 number_type r = round(v, pol);
|
Chris@16
|
1513 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1514 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
|
Chris@16
|
1515 return r.template convert_to<long>();
|
Chris@16
|
1516 }
|
Chris@16
|
1517 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1518 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1519 {
|
Chris@16
|
1520 return lround(v, boost::math::policies::policy<>());
|
Chris@16
|
1521 }
|
Chris@16
|
1522 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1523 inline long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1524 {
|
Chris@16
|
1525 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1526 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1527 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
|
Chris@16
|
1528 return r.template convert_to<long>();
|
Chris@16
|
1529 }
|
Chris@16
|
1530 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1531 inline long lround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1532 {
|
Chris@16
|
1533 return lround(v, boost::math::policies::policy<>());
|
Chris@16
|
1534 }
|
Chris@16
|
1535 #ifndef BOOST_NO_LONG_LONG
|
Chris@16
|
1536 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1537 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1538 {
|
Chris@16
|
1539 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1540 number_type r = round(v, pol);
|
Chris@16
|
1541 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1542 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
|
Chris@16
|
1543 return r.template convert_to<long long>();
|
Chris@16
|
1544 }
|
Chris@16
|
1545 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1546 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1547 {
|
Chris@16
|
1548 return llround(v, boost::math::policies::policy<>());
|
Chris@16
|
1549 }
|
Chris@16
|
1550 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1551 inline long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1552 {
|
Chris@16
|
1553 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1554 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1555 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
|
Chris@16
|
1556 return r.template convert_to<long long>();
|
Chris@16
|
1557 }
|
Chris@16
|
1558 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1559 inline long long llround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1560 {
|
Chris@16
|
1561 return llround(v, boost::math::policies::policy<>());
|
Chris@16
|
1562 }
|
Chris@16
|
1563 #endif
|
Chris@101
|
1564 //
|
Chris@101
|
1565 // frexp does not return an expression template since we require the
|
Chris@101
|
1566 // integer argument to be evaluated even if the returned value is
|
Chris@101
|
1567 // not assigned to anything...
|
Chris@101
|
1568 //
|
Chris@101
|
1569 template <class T, expression_template_option ExpressionTemplates>
|
Chris@101
|
1570 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
|
Chris@101
|
1571 {
|
Chris@101
|
1572 using default_ops::eval_frexp;
|
Chris@101
|
1573 number<T, ExpressionTemplates> result;
|
Chris@101
|
1574 eval_frexp(result.backend(), v.backend(), pint);
|
Chris@101
|
1575 return BOOST_MP_MOVE(result);
|
Chris@101
|
1576 }
|
Chris@101
|
1577 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@101
|
1578 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
Chris@101
|
1579 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
|
Chris@101
|
1580 {
|
Chris@101
|
1581 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@101
|
1582 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
|
Chris@101
|
1583 }
|
Chris@101
|
1584 template <class T, expression_template_option ExpressionTemplates>
|
Chris@101
|
1585 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
|
Chris@101
|
1586 {
|
Chris@101
|
1587 using default_ops::eval_frexp;
|
Chris@101
|
1588 number<T, ExpressionTemplates> result;
|
Chris@101
|
1589 eval_frexp(result.backend(), v.backend(), pint);
|
Chris@101
|
1590 return BOOST_MP_MOVE(result);
|
Chris@101
|
1591 }
|
Chris@101
|
1592 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@101
|
1593 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
Chris@101
|
1594 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
|
Chris@101
|
1595 {
|
Chris@101
|
1596 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@101
|
1597 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
|
Chris@101
|
1598 }
|
Chris@101
|
1599 template <class T, expression_template_option ExpressionTemplates>
|
Chris@101
|
1600 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
|
Chris@101
|
1601 {
|
Chris@101
|
1602 using default_ops::eval_frexp;
|
Chris@101
|
1603 number<T, ExpressionTemplates> result;
|
Chris@101
|
1604 eval_frexp(result.backend(), v.backend(), pint);
|
Chris@101
|
1605 return BOOST_MP_MOVE(result);
|
Chris@101
|
1606 }
|
Chris@101
|
1607 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@101
|
1608 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
Chris@101
|
1609 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
|
Chris@101
|
1610 {
|
Chris@101
|
1611 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@101
|
1612 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
|
Chris@101
|
1613 }
|
Chris@101
|
1614 template <class T, expression_template_option ExpressionTemplates>
|
Chris@101
|
1615 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
|
Chris@101
|
1616 {
|
Chris@101
|
1617 using default_ops::eval_frexp;
|
Chris@101
|
1618 number<T, ExpressionTemplates> result;
|
Chris@101
|
1619 eval_frexp(result.backend(), v.backend(), pint);
|
Chris@101
|
1620 return BOOST_MP_MOVE(result);
|
Chris@101
|
1621 }
|
Chris@101
|
1622 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@101
|
1623 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
|
Chris@101
|
1624 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
|
Chris@101
|
1625 {
|
Chris@101
|
1626 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@101
|
1627 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
|
Chris@101
|
1628 }
|
Chris@16
|
1629
|
Chris@16
|
1630 template <class B, expression_template_option ExpressionTemplates>
|
Chris@16
|
1631 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
Chris@16
|
1632 sqrt(const number<B, ExpressionTemplates>& x)
|
Chris@16
|
1633 {
|
Chris@16
|
1634 using default_ops::eval_integer_sqrt;
|
Chris@16
|
1635 number<B, ExpressionTemplates> s, r;
|
Chris@16
|
1636 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
Chris@16
|
1637 return s;
|
Chris@16
|
1638 }
|
Chris@16
|
1639
|
Chris@16
|
1640 template <class B, expression_template_option ExpressionTemplates>
|
Chris@16
|
1641 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
Chris@16
|
1642 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
|
Chris@16
|
1643 {
|
Chris@16
|
1644 using default_ops::eval_integer_sqrt;
|
Chris@16
|
1645 number<B, ExpressionTemplates> s;
|
Chris@16
|
1646 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
Chris@16
|
1647 return s;
|
Chris@16
|
1648 }
|
Chris@16
|
1649
|
Chris@16
|
1650 #define UNARY_OP_FUNCTOR(func, category)\
|
Chris@16
|
1651 namespace detail{\
|
Chris@16
|
1652 template <class Backend> \
|
Chris@16
|
1653 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
1654 {\
|
Chris@16
|
1655 void operator()(Backend& result, const Backend& arg)const\
|
Chris@16
|
1656 {\
|
Chris@16
|
1657 using default_ops::BOOST_JOIN(eval_,func);\
|
Chris@16
|
1658 BOOST_JOIN(eval_,func)(result, arg);\
|
Chris@16
|
1659 }\
|
Chris@16
|
1660 };\
|
Chris@16
|
1661 \
|
Chris@16
|
1662 }\
|
Chris@16
|
1663 \
|
Chris@16
|
1664 template <class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1665 inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category,\
|
Chris@16
|
1666 detail::expression<\
|
Chris@16
|
1667 detail::function\
|
Chris@16
|
1668 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1669 , detail::expression<tag, A1, A2, A3, A4> > \
|
Chris@16
|
1670 >::type \
|
Chris@16
|
1671 func(const detail::expression<tag, A1, A2, A3, A4>& arg)\
|
Chris@16
|
1672 {\
|
Chris@16
|
1673 return detail::expression<\
|
Chris@16
|
1674 detail::function\
|
Chris@16
|
1675 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1676 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1677 > (\
|
Chris@16
|
1678 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1679 , arg \
|
Chris@16
|
1680 );\
|
Chris@16
|
1681 }\
|
Chris@16
|
1682 template <class Backend> \
|
Chris@16
|
1683 inline typename enable_if_c<number_category<Backend>::value == category,\
|
Chris@16
|
1684 detail::expression<\
|
Chris@16
|
1685 detail::function\
|
Chris@16
|
1686 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1687 , number<Backend, et_on> > \
|
Chris@16
|
1688 >::type \
|
Chris@16
|
1689 func(const number<Backend, et_on>& arg)\
|
Chris@16
|
1690 {\
|
Chris@16
|
1691 return detail::expression<\
|
Chris@16
|
1692 detail::function\
|
Chris@16
|
1693 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1694 , number<Backend, et_on> \
|
Chris@16
|
1695 >(\
|
Chris@16
|
1696 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1697 , arg \
|
Chris@16
|
1698 );\
|
Chris@16
|
1699 }\
|
Chris@16
|
1700 template <class Backend> \
|
Chris@16
|
1701 inline typename boost::enable_if_c<\
|
Chris@16
|
1702 boost::multiprecision::number_category<Backend>::value == category,\
|
Chris@16
|
1703 number<Backend, et_off> >::type \
|
Chris@16
|
1704 func(const number<Backend, et_off>& arg)\
|
Chris@16
|
1705 {\
|
Chris@16
|
1706 number<Backend, et_off> result;\
|
Chris@16
|
1707 using default_ops::BOOST_JOIN(eval_,func);\
|
Chris@16
|
1708 BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\
|
Chris@16
|
1709 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1710 }
|
Chris@16
|
1711
|
Chris@16
|
1712 #define BINARY_OP_FUNCTOR(func, category)\
|
Chris@16
|
1713 namespace detail{\
|
Chris@16
|
1714 template <class Backend> \
|
Chris@16
|
1715 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
1716 {\
|
Chris@16
|
1717 void operator()(Backend& result, const Backend& arg, const Backend& a)const\
|
Chris@16
|
1718 {\
|
Chris@16
|
1719 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1720 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1721 }\
|
Chris@16
|
1722 template <class Arithmetic> \
|
Chris@16
|
1723 void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\
|
Chris@16
|
1724 {\
|
Chris@16
|
1725 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1726 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1727 }\
|
Chris@16
|
1728 template <class Arithmetic> \
|
Chris@16
|
1729 void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
|
Chris@16
|
1730 {\
|
Chris@16
|
1731 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1732 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1733 }\
|
Chris@16
|
1734 };\
|
Chris@16
|
1735 \
|
Chris@16
|
1736 }\
|
Chris@16
|
1737 template <class Backend> \
|
Chris@16
|
1738 inline typename enable_if_c<number_category<Backend>::value == category,\
|
Chris@16
|
1739 detail::expression<\
|
Chris@16
|
1740 detail::function\
|
Chris@16
|
1741 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1742 , number<Backend, et_on> \
|
Chris@16
|
1743 , number<Backend, et_on> > \
|
Chris@16
|
1744 >::type \
|
Chris@16
|
1745 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a)\
|
Chris@16
|
1746 {\
|
Chris@16
|
1747 return detail::expression<\
|
Chris@16
|
1748 detail::function\
|
Chris@16
|
1749 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1750 , number<Backend, et_on> \
|
Chris@16
|
1751 , number<Backend, et_on> \
|
Chris@16
|
1752 >(\
|
Chris@16
|
1753 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1754 , arg,\
|
Chris@16
|
1755 a\
|
Chris@16
|
1756 );\
|
Chris@16
|
1757 }\
|
Chris@16
|
1758 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1759 inline typename enable_if_c<\
|
Chris@16
|
1760 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1761 detail::expression<\
|
Chris@16
|
1762 detail::function\
|
Chris@16
|
1763 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1764 , number<Backend, et_on> \
|
Chris@16
|
1765 , detail::expression<tag, A1, A2, A3, A4> > \
|
Chris@16
|
1766 >::type \
|
Chris@16
|
1767 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
|
Chris@16
|
1768 {\
|
Chris@16
|
1769 return detail::expression<\
|
Chris@16
|
1770 detail::function\
|
Chris@16
|
1771 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1772 , number<Backend, et_on> \
|
Chris@16
|
1773 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1774 >(\
|
Chris@16
|
1775 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1776 , arg,\
|
Chris@16
|
1777 a\
|
Chris@16
|
1778 );\
|
Chris@16
|
1779 }\
|
Chris@16
|
1780 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
|
Chris@16
|
1781 inline typename enable_if_c<\
|
Chris@16
|
1782 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1783 detail::expression<\
|
Chris@16
|
1784 detail::function\
|
Chris@16
|
1785 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1786 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1787 , number<Backend, et_on> > \
|
Chris@16
|
1788 >::type \
|
Chris@16
|
1789 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)\
|
Chris@16
|
1790 {\
|
Chris@16
|
1791 return detail::expression<\
|
Chris@16
|
1792 detail::function\
|
Chris@16
|
1793 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1794 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1795 , number<Backend, et_on> \
|
Chris@16
|
1796 >(\
|
Chris@16
|
1797 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1798 , arg,\
|
Chris@16
|
1799 a\
|
Chris@16
|
1800 );\
|
Chris@16
|
1801 }\
|
Chris@16
|
1802 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
|
Chris@16
|
1803 inline typename enable_if_c<\
|
Chris@16
|
1804 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category),\
|
Chris@16
|
1805 detail::expression<\
|
Chris@16
|
1806 detail::function\
|
Chris@16
|
1807 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1808 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1809 , detail::expression<tagb, A1b, A2b, A3b, A4b> > \
|
Chris@16
|
1810 >::type \
|
Chris@16
|
1811 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)\
|
Chris@16
|
1812 {\
|
Chris@16
|
1813 return detail::expression<\
|
Chris@16
|
1814 detail::function\
|
Chris@16
|
1815 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1816 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1817 , detail::expression<tagb, A1b, A2b, A3b, A4b> \
|
Chris@16
|
1818 >(\
|
Chris@16
|
1819 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1820 , arg,\
|
Chris@16
|
1821 a\
|
Chris@16
|
1822 );\
|
Chris@16
|
1823 }\
|
Chris@16
|
1824 template <class Backend, class Arithmetic> \
|
Chris@16
|
1825 inline typename enable_if_c<\
|
Chris@16
|
1826 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1827 detail::expression<\
|
Chris@16
|
1828 detail::function\
|
Chris@16
|
1829 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1830 , number<Backend, et_on> \
|
Chris@16
|
1831 , Arithmetic\
|
Chris@16
|
1832 > \
|
Chris@16
|
1833 >::type \
|
Chris@16
|
1834 func(const number<Backend, et_on>& arg, const Arithmetic& a)\
|
Chris@16
|
1835 {\
|
Chris@16
|
1836 return detail::expression<\
|
Chris@16
|
1837 detail::function\
|
Chris@16
|
1838 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1839 , number<Backend, et_on> \
|
Chris@16
|
1840 , Arithmetic\
|
Chris@16
|
1841 >(\
|
Chris@16
|
1842 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1843 , arg,\
|
Chris@16
|
1844 a\
|
Chris@16
|
1845 );\
|
Chris@16
|
1846 }\
|
Chris@16
|
1847 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
|
Chris@16
|
1848 inline typename enable_if_c<\
|
Chris@16
|
1849 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1850 detail::expression<\
|
Chris@16
|
1851 detail::function\
|
Chris@16
|
1852 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1853 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1854 , Arithmetic\
|
Chris@16
|
1855 > \
|
Chris@16
|
1856 >::type \
|
Chris@16
|
1857 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a)\
|
Chris@16
|
1858 {\
|
Chris@16
|
1859 return detail::expression<\
|
Chris@16
|
1860 detail::function\
|
Chris@16
|
1861 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1862 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1863 , Arithmetic\
|
Chris@16
|
1864 >(\
|
Chris@16
|
1865 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1866 , arg,\
|
Chris@16
|
1867 a\
|
Chris@16
|
1868 );\
|
Chris@16
|
1869 }\
|
Chris@16
|
1870 template <class Backend, class Arithmetic> \
|
Chris@16
|
1871 inline typename enable_if_c<\
|
Chris@16
|
1872 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1873 detail::expression<\
|
Chris@16
|
1874 detail::function\
|
Chris@16
|
1875 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1876 , Arithmetic \
|
Chris@16
|
1877 , number<Backend, et_on> \
|
Chris@16
|
1878 > \
|
Chris@16
|
1879 >::type \
|
Chris@16
|
1880 func(const Arithmetic& arg, const number<Backend, et_on>& a)\
|
Chris@16
|
1881 {\
|
Chris@16
|
1882 return detail::expression<\
|
Chris@16
|
1883 detail::function\
|
Chris@16
|
1884 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1885 , Arithmetic \
|
Chris@16
|
1886 , number<Backend, et_on> \
|
Chris@16
|
1887 >(\
|
Chris@16
|
1888 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1889 , arg,\
|
Chris@16
|
1890 a\
|
Chris@16
|
1891 );\
|
Chris@16
|
1892 }\
|
Chris@16
|
1893 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
|
Chris@16
|
1894 inline typename enable_if_c<\
|
Chris@16
|
1895 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1896 detail::expression<\
|
Chris@16
|
1897 detail::function\
|
Chris@16
|
1898 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1899 , Arithmetic \
|
Chris@16
|
1900 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1901 > \
|
Chris@16
|
1902 >::type \
|
Chris@16
|
1903 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
|
Chris@16
|
1904 {\
|
Chris@16
|
1905 return detail::expression<\
|
Chris@16
|
1906 detail::function\
|
Chris@16
|
1907 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1908 , Arithmetic \
|
Chris@16
|
1909 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1910 >(\
|
Chris@16
|
1911 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1912 , arg,\
|
Chris@16
|
1913 a\
|
Chris@16
|
1914 );\
|
Chris@16
|
1915 }\
|
Chris@16
|
1916 template <class Backend> \
|
Chris@16
|
1917 inline typename enable_if_c<(number_category<Backend>::value == category),\
|
Chris@16
|
1918 number<Backend, et_off> >::type \
|
Chris@16
|
1919 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a)\
|
Chris@16
|
1920 {\
|
Chris@16
|
1921 number<Backend, et_off> result;\
|
Chris@16
|
1922 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1923 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\
|
Chris@16
|
1924 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1925 }\
|
Chris@16
|
1926 template <class Backend, class Arithmetic> \
|
Chris@16
|
1927 inline typename enable_if_c<\
|
Chris@16
|
1928 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1929 number<Backend, et_off> \
|
Chris@16
|
1930 >::type \
|
Chris@16
|
1931 func(const number<Backend, et_off>& arg, const Arithmetic& a)\
|
Chris@16
|
1932 {\
|
Chris@16
|
1933 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
|
Chris@16
|
1934 number<Backend, et_off> result;\
|
Chris@16
|
1935 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1936 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast<canonical_type>(a));\
|
Chris@16
|
1937 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1938 }\
|
Chris@16
|
1939 template <class Backend, class Arithmetic> \
|
Chris@16
|
1940 inline typename enable_if_c<\
|
Chris@16
|
1941 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1942 number<Backend, et_off> \
|
Chris@16
|
1943 >::type \
|
Chris@16
|
1944 func(const Arithmetic& a, const number<Backend, et_off>& arg)\
|
Chris@16
|
1945 {\
|
Chris@16
|
1946 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
|
Chris@16
|
1947 number<Backend, et_off> result;\
|
Chris@16
|
1948 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1949 BOOST_JOIN(eval_,func)(result.backend(), static_cast<canonical_type>(a), arg.backend());\
|
Chris@16
|
1950 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1951 }\
|
Chris@16
|
1952
|
Chris@16
|
1953
|
Chris@16
|
1954 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\
|
Chris@16
|
1955 template <class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1956 inline typename enable_if_c<\
|
Chris@16
|
1957 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1958 detail::expression<\
|
Chris@16
|
1959 detail::function\
|
Chris@16
|
1960 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1961 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1962 , Arg2> \
|
Chris@16
|
1963 >::type \
|
Chris@16
|
1964 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a)\
|
Chris@16
|
1965 {\
|
Chris@16
|
1966 return detail::expression<\
|
Chris@16
|
1967 detail::function\
|
Chris@16
|
1968 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1969 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1970 , Arg2\
|
Chris@16
|
1971 >(\
|
Chris@16
|
1972 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1973 , arg, a \
|
Chris@16
|
1974 );\
|
Chris@16
|
1975 }\
|
Chris@16
|
1976 template <class Backend> \
|
Chris@16
|
1977 inline typename enable_if_c<\
|
Chris@16
|
1978 (number_category<Backend>::value == category),\
|
Chris@16
|
1979 detail::expression<\
|
Chris@16
|
1980 detail::function\
|
Chris@16
|
1981 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1982 , number<Backend, et_on> \
|
Chris@16
|
1983 , Arg2> \
|
Chris@16
|
1984 >::type \
|
Chris@16
|
1985 func(const number<Backend, et_on>& arg, Arg2 const& a)\
|
Chris@16
|
1986 {\
|
Chris@16
|
1987 return detail::expression<\
|
Chris@16
|
1988 detail::function\
|
Chris@16
|
1989 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1990 , number<Backend, et_on> \
|
Chris@16
|
1991 , Arg2\
|
Chris@16
|
1992 >(\
|
Chris@16
|
1993 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1994 , arg,\
|
Chris@16
|
1995 a\
|
Chris@16
|
1996 );\
|
Chris@16
|
1997 }\
|
Chris@16
|
1998 template <class Backend> \
|
Chris@16
|
1999 inline typename enable_if_c<\
|
Chris@16
|
2000 (number_category<Backend>::value == category),\
|
Chris@16
|
2001 number<Backend, et_off> >::type \
|
Chris@16
|
2002 func(const number<Backend, et_off>& arg, Arg2 const& a)\
|
Chris@16
|
2003 {\
|
Chris@16
|
2004 number<Backend, et_off> result;\
|
Chris@16
|
2005 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
2006 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\
|
Chris@16
|
2007 return BOOST_MP_MOVE(result);\
|
Chris@16
|
2008 }\
|
Chris@16
|
2009
|
Chris@16
|
2010 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\
|
Chris@16
|
2011 namespace detail{\
|
Chris@16
|
2012 template <class Backend> \
|
Chris@16
|
2013 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
2014 {\
|
Chris@16
|
2015 template <class Arg>\
|
Chris@16
|
2016 void operator()(Backend& result, Backend const& arg, Arg a)const\
|
Chris@16
|
2017 {\
|
Chris@16
|
2018 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
2019 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
2020 }\
|
Chris@16
|
2021 };\
|
Chris@16
|
2022 \
|
Chris@16
|
2023 }\
|
Chris@16
|
2024 \
|
Chris@16
|
2025 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
|
Chris@16
|
2026
|
Chris@16
|
2027 namespace detail{
|
Chris@16
|
2028 template <class Backend>
|
Chris@16
|
2029 struct abs_funct
|
Chris@16
|
2030 {
|
Chris@16
|
2031 void operator()(Backend& result, const Backend& arg)const
|
Chris@16
|
2032 {
|
Chris@16
|
2033 using default_ops::eval_abs;
|
Chris@16
|
2034 eval_abs(result, arg);
|
Chris@16
|
2035 }
|
Chris@16
|
2036 };
|
Chris@16
|
2037
|
Chris@16
|
2038 }
|
Chris@16
|
2039
|
Chris@16
|
2040 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
2041 inline detail::expression<
|
Chris@16
|
2042 detail::function
|
Chris@16
|
2043 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
|
Chris@16
|
2044 , detail::expression<tag, A1, A2, A3, A4> >
|
Chris@16
|
2045 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
2046 {
|
Chris@16
|
2047 return detail::expression<
|
Chris@16
|
2048 detail::function
|
Chris@16
|
2049 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
|
Chris@16
|
2050 , detail::expression<tag, A1, A2, A3, A4>
|
Chris@16
|
2051 > (
|
Chris@16
|
2052 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>()
|
Chris@16
|
2053 , arg
|
Chris@16
|
2054 );
|
Chris@16
|
2055 }
|
Chris@16
|
2056 template <class Backend>
|
Chris@16
|
2057 inline detail::expression<
|
Chris@16
|
2058 detail::function
|
Chris@16
|
2059 , detail::abs_funct<Backend>
|
Chris@16
|
2060 , number<Backend, et_on> >
|
Chris@16
|
2061 abs(const number<Backend, et_on>& arg)
|
Chris@16
|
2062 {
|
Chris@16
|
2063 return detail::expression<
|
Chris@16
|
2064 detail::function
|
Chris@16
|
2065 , detail::abs_funct<Backend>
|
Chris@16
|
2066 , number<Backend, et_on>
|
Chris@16
|
2067 >(
|
Chris@16
|
2068 detail::abs_funct<Backend>()
|
Chris@16
|
2069 , arg
|
Chris@16
|
2070 );
|
Chris@16
|
2071 }
|
Chris@16
|
2072 template <class Backend>
|
Chris@16
|
2073 inline number<Backend, et_off>
|
Chris@16
|
2074 abs(const number<Backend, et_off>& arg)
|
Chris@16
|
2075 {
|
Chris@16
|
2076 number<Backend, et_off> result;
|
Chris@16
|
2077 using default_ops::eval_abs;
|
Chris@16
|
2078 eval_abs(result.backend(), arg.backend());
|
Chris@16
|
2079 return BOOST_MP_MOVE(result);
|
Chris@16
|
2080 }
|
Chris@16
|
2081
|
Chris@16
|
2082 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
|
Chris@16
|
2083 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
|
Chris@16
|
2084 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
|
Chris@16
|
2085 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
|
Chris@16
|
2086 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
|
Chris@16
|
2087 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
|
Chris@16
|
2088 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
|
Chris@16
|
2089 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
|
Chris@16
|
2090 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
|
Chris@16
|
2091 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
|
Chris@16
|
2092 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
|
Chris@16
|
2093 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
|
Chris@16
|
2094 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
|
Chris@16
|
2095 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
|
Chris@16
|
2096 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
|
Chris@16
|
2097 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
|
Chris@16
|
2098 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
|
Chris@16
|
2099 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
|
Chris@16
|
2100
|
Chris@101
|
2101 HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
|
Chris@101
|
2102 //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
|
Chris@101
|
2103 HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
|
Chris@101
|
2104 //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
|
Chris@16
|
2105 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
|
Chris@101
|
2106 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
|
Chris@16
|
2107 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
|
Chris@101
|
2108 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
|
Chris@16
|
2109 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
|
Chris@16
|
2110 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
|
Chris@16
|
2111 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
|
Chris@16
|
2112
|
Chris@101
|
2113 UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
|
Chris@101
|
2114 HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
|
Chris@101
|
2115 HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
|
Chris@101
|
2116 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
|
Chris@101
|
2117 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
|
Chris@101
|
2118
|
Chris@16
|
2119 //
|
Chris@16
|
2120 // Integer functions:
|
Chris@16
|
2121 //
|
Chris@16
|
2122 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
|
Chris@16
|
2123 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
|
Chris@16
|
2124 HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
|
Chris@16
|
2125
|
Chris@16
|
2126 #undef BINARY_OP_FUNCTOR
|
Chris@16
|
2127 #undef UNARY_OP_FUNCTOR
|
Chris@16
|
2128
|
Chris@101
|
2129 //
|
Chris@101
|
2130 // ilogb:
|
Chris@101
|
2131 //
|
Chris@101
|
2132 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@101
|
2133 inline typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
|
Chris@101
|
2134 ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
|
Chris@101
|
2135 {
|
Chris@101
|
2136 using default_ops::eval_ilogb;
|
Chris@101
|
2137 return eval_ilogb(val.backend());
|
Chris@101
|
2138 }
|
Chris@101
|
2139
|
Chris@101
|
2140 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@101
|
2141 inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
|
Chris@101
|
2142 ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
|
Chris@101
|
2143 {
|
Chris@101
|
2144 using default_ops::eval_ilogb;
|
Chris@101
|
2145 typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
|
Chris@101
|
2146 return eval_ilogb(arg.backend());
|
Chris@101
|
2147 }
|
Chris@101
|
2148
|
Chris@16
|
2149 } //namespace multiprecision
|
Chris@16
|
2150
|
Chris@16
|
2151 namespace math{
|
Chris@16
|
2152 //
|
Chris@16
|
2153 // Overload of Boost.Math functions that find the wrong overload when used with number:
|
Chris@16
|
2154 //
|
Chris@16
|
2155 namespace detail{
|
Chris@16
|
2156 template <class T> T sinc_pi_imp(T);
|
Chris@16
|
2157 template <class T> T sinhc_pi_imp(T);
|
Chris@16
|
2158 }
|
Chris@16
|
2159 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
2160 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
Chris@16
|
2161 {
|
Chris@16
|
2162 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
|
Chris@16
|
2163 }
|
Chris@16
|
2164
|
Chris@16
|
2165 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
2166 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
|
Chris@16
|
2167 {
|
Chris@16
|
2168 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
|
Chris@16
|
2169 }
|
Chris@16
|
2170
|
Chris@16
|
2171 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
2172 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
Chris@16
|
2173 {
|
Chris@16
|
2174 return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
|
Chris@16
|
2175 }
|
Chris@16
|
2176
|
Chris@16
|
2177 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
2178 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
|
Chris@16
|
2179 {
|
Chris@16
|
2180 return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
|
Chris@16
|
2181 }
|
Chris@16
|
2182
|
Chris@16
|
2183 #ifdef BOOST_MSVC
|
Chris@16
|
2184 #pragma warning(pop)
|
Chris@16
|
2185 #endif
|
Chris@16
|
2186 } // namespace math
|
Chris@16
|
2187 } // namespace boost
|
Chris@16
|
2188
|
Chris@16
|
2189 //
|
Chris@16
|
2190 // This has to come last of all:
|
Chris@16
|
2191 //
|
Chris@16
|
2192 #include <boost/multiprecision/detail/no_et_ops.hpp>
|
Chris@16
|
2193 #include <boost/multiprecision/detail/et_ops.hpp>
|
Chris@16
|
2194
|
Chris@16
|
2195 #endif
|
Chris@16
|
2196
|