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@16
|
965 if(c == FP_NAN || c == 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@16
|
982 if(c == FP_NAN || c == 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@16
|
1205 //
|
Chris@16
|
1206 // These functions are implemented in separate files, but expanded inline here,
|
Chris@16
|
1207 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
|
Chris@16
|
1208 //
|
Chris@16
|
1209 #include <boost/multiprecision/detail/functions/constants.hpp>
|
Chris@16
|
1210 #include <boost/multiprecision/detail/functions/pow.hpp>
|
Chris@16
|
1211 #include <boost/multiprecision/detail/functions/trig.hpp>
|
Chris@16
|
1212
|
Chris@16
|
1213 }
|
Chris@16
|
1214
|
Chris@16
|
1215 } // namespace multiprecision
|
Chris@16
|
1216 namespace math{
|
Chris@16
|
1217 //
|
Chris@16
|
1218 // Default versions of floating point classification routines:
|
Chris@16
|
1219 //
|
Chris@16
|
1220 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1221 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1222 {
|
Chris@16
|
1223 using multiprecision::default_ops::eval_fpclassify;
|
Chris@16
|
1224 return eval_fpclassify(arg.backend());
|
Chris@16
|
1225 }
|
Chris@16
|
1226 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1227 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1228 {
|
Chris@16
|
1229 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1230 return (fpclassify)(value_type(arg));
|
Chris@16
|
1231 }
|
Chris@16
|
1232 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1233 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1234 {
|
Chris@16
|
1235 int v = (fpclassify)(arg);
|
Chris@16
|
1236 return (v != FP_INFINITE) && (v != FP_NAN);
|
Chris@16
|
1237 }
|
Chris@16
|
1238 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1239 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1240 {
|
Chris@16
|
1241 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1242 return (isfinite)(value_type(arg));
|
Chris@16
|
1243 }
|
Chris@16
|
1244 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1245 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1246 {
|
Chris@16
|
1247 return (fpclassify)(arg) == FP_NAN;
|
Chris@16
|
1248 }
|
Chris@16
|
1249 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1250 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1251 {
|
Chris@16
|
1252 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1253 return (isnan)(value_type(arg));
|
Chris@16
|
1254 }
|
Chris@16
|
1255 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1256 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1257 {
|
Chris@16
|
1258 return (fpclassify)(arg) == FP_INFINITE;
|
Chris@16
|
1259 }
|
Chris@16
|
1260 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1261 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1262 {
|
Chris@16
|
1263 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1264 return (isinf)(value_type(arg));
|
Chris@16
|
1265 }
|
Chris@16
|
1266 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
1267 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
Chris@16
|
1268 {
|
Chris@16
|
1269 return (fpclassify)(arg) == FP_NORMAL;
|
Chris@16
|
1270 }
|
Chris@16
|
1271 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1272 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1273 {
|
Chris@16
|
1274 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
|
Chris@16
|
1275 return (isnormal)(value_type(arg));
|
Chris@16
|
1276 }
|
Chris@16
|
1277
|
Chris@16
|
1278 } // namespace math
|
Chris@16
|
1279 namespace multiprecision{
|
Chris@16
|
1280
|
Chris@16
|
1281 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1282 inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1283 {
|
Chris@16
|
1284 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1285 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1286 using default_ops::eval_add;
|
Chris@16
|
1287 eval_add(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1288 return result;
|
Chris@16
|
1289 }
|
Chris@16
|
1290
|
Chris@16
|
1291 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1292 inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1293 {
|
Chris@16
|
1294 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1295 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1296 using default_ops::eval_subtract;
|
Chris@16
|
1297 eval_subtract(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1298 return result;
|
Chris@16
|
1299 }
|
Chris@16
|
1300
|
Chris@16
|
1301 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
|
Chris@16
|
1302 inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
|
Chris@16
|
1303 {
|
Chris@16
|
1304 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1305 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
|
Chris@16
|
1306 using default_ops::eval_multiply;
|
Chris@16
|
1307 eval_multiply(result.backend(), a.backend(), b.backend());
|
Chris@16
|
1308 return result;
|
Chris@16
|
1309 }
|
Chris@16
|
1310
|
Chris@16
|
1311 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1312 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1313 add(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1314 {
|
Chris@16
|
1315 using default_ops::eval_add;
|
Chris@16
|
1316 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1317 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1318 return result;
|
Chris@16
|
1319 }
|
Chris@16
|
1320
|
Chris@16
|
1321 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1322 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1323 subtract(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1324 {
|
Chris@16
|
1325 using default_ops::eval_subtract;
|
Chris@16
|
1326 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1327 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1328 return result;
|
Chris@16
|
1329 }
|
Chris@16
|
1330
|
Chris@16
|
1331 template <class B, expression_template_option ET, class I>
|
Chris@16
|
1332 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
|
Chris@16
|
1333 multiply(number<B, ET>& result, const I& a, const I& b)
|
Chris@16
|
1334 {
|
Chris@16
|
1335 using default_ops::eval_multiply;
|
Chris@16
|
1336 typedef typename detail::canonical<I, B>::type canonical_type;
|
Chris@16
|
1337 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
|
Chris@16
|
1338 return result;
|
Chris@16
|
1339 }
|
Chris@16
|
1340
|
Chris@16
|
1341 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1342 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
|
1343 {
|
Chris@16
|
1344 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1345 return BOOST_MP_MOVE(trunc(number_type(v), pol));
|
Chris@16
|
1346 }
|
Chris@16
|
1347
|
Chris@16
|
1348 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1349 inline number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
|
Chris@16
|
1350 {
|
Chris@16
|
1351 using default_ops::eval_trunc;
|
Chris@16
|
1352 number<Backend, ExpressionTemplates> result;
|
Chris@16
|
1353 eval_trunc(result.backend(), v.backend());
|
Chris@16
|
1354 return BOOST_MP_MOVE(result);
|
Chris@16
|
1355 }
|
Chris@16
|
1356
|
Chris@16
|
1357 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1358 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1359 {
|
Chris@16
|
1360 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1361 number_type r = trunc(v, pol);
|
Chris@16
|
1362 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1363 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
|
Chris@16
|
1364 return r.template convert_to<int>();
|
Chris@16
|
1365 }
|
Chris@16
|
1366 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1367 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1368 {
|
Chris@16
|
1369 return itrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1370 }
|
Chris@16
|
1371 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1372 inline int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1373 {
|
Chris@16
|
1374 number<Backend, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1375 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1376 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
|
Chris@16
|
1377 return r.template convert_to<int>();
|
Chris@16
|
1378 }
|
Chris@16
|
1379 template <class Backend, expression_template_option ExpressionTemplates>
|
Chris@16
|
1380 inline int itrunc(const number<Backend, ExpressionTemplates>& v)
|
Chris@16
|
1381 {
|
Chris@16
|
1382 return itrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1383 }
|
Chris@16
|
1384 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1385 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1386 {
|
Chris@16
|
1387 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1388 number_type r = trunc(v, pol);
|
Chris@16
|
1389 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1390 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
|
Chris@16
|
1391 return r.template convert_to<long>();
|
Chris@16
|
1392 }
|
Chris@16
|
1393 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1394 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1395 {
|
Chris@16
|
1396 return ltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1397 }
|
Chris@16
|
1398 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1399 inline long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1400 {
|
Chris@16
|
1401 number<T, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1402 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1403 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
|
Chris@16
|
1404 return r.template convert_to<long>();
|
Chris@16
|
1405 }
|
Chris@16
|
1406 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1407 inline long ltrunc(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1408 {
|
Chris@16
|
1409 return ltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1410 }
|
Chris@16
|
1411 #ifndef BOOST_NO_LONG_LONG
|
Chris@16
|
1412 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1413 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1414 {
|
Chris@16
|
1415 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1416 number_type r = trunc(v, pol);
|
Chris@16
|
1417 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1418 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
|
Chris@16
|
1419 return r.template convert_to<long long>();
|
Chris@16
|
1420 }
|
Chris@16
|
1421 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1422 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1423 {
|
Chris@16
|
1424 return lltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1425 }
|
Chris@16
|
1426 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1427 inline long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1428 {
|
Chris@16
|
1429 number<T, ExpressionTemplates> r = trunc(v, pol);
|
Chris@16
|
1430 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1431 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
|
Chris@16
|
1432 return r.template convert_to<long long>();
|
Chris@16
|
1433 }
|
Chris@16
|
1434 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1435 inline long long lltrunc(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1436 {
|
Chris@16
|
1437 return lltrunc(v, boost::math::policies::policy<>());
|
Chris@16
|
1438 }
|
Chris@16
|
1439 #endif
|
Chris@16
|
1440 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1441 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
|
1442 {
|
Chris@16
|
1443 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1444 return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
|
Chris@16
|
1445 }
|
Chris@16
|
1446 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1447 inline number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
|
Chris@16
|
1448 {
|
Chris@16
|
1449 using default_ops::eval_round;
|
Chris@16
|
1450 number<T, ExpressionTemplates> result;
|
Chris@16
|
1451 eval_round(result.backend(), v.backend());
|
Chris@16
|
1452 return BOOST_MP_MOVE(result);
|
Chris@16
|
1453 }
|
Chris@16
|
1454
|
Chris@16
|
1455 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1456 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1457 {
|
Chris@16
|
1458 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1459 number_type r = round(v, pol);
|
Chris@16
|
1460 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1461 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
|
Chris@16
|
1462 return r.template convert_to<int>();
|
Chris@16
|
1463 }
|
Chris@16
|
1464 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1465 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1466 {
|
Chris@16
|
1467 return iround(v, boost::math::policies::policy<>());
|
Chris@16
|
1468 }
|
Chris@16
|
1469 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1470 inline int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1471 {
|
Chris@16
|
1472 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1473 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1474 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
|
Chris@16
|
1475 return r.template convert_to<int>();
|
Chris@16
|
1476 }
|
Chris@16
|
1477 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1478 inline int iround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1479 {
|
Chris@16
|
1480 return iround(v, boost::math::policies::policy<>());
|
Chris@16
|
1481 }
|
Chris@16
|
1482 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1483 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1484 {
|
Chris@16
|
1485 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1486 number_type r = round(v, pol);
|
Chris@16
|
1487 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1488 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
|
Chris@16
|
1489 return r.template convert_to<long>();
|
Chris@16
|
1490 }
|
Chris@16
|
1491 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1492 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1493 {
|
Chris@16
|
1494 return lround(v, boost::math::policies::policy<>());
|
Chris@16
|
1495 }
|
Chris@16
|
1496 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1497 inline long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1498 {
|
Chris@16
|
1499 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1500 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1501 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
|
Chris@16
|
1502 return r.template convert_to<long>();
|
Chris@16
|
1503 }
|
Chris@16
|
1504 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1505 inline long lround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1506 {
|
Chris@16
|
1507 return lround(v, boost::math::policies::policy<>());
|
Chris@16
|
1508 }
|
Chris@16
|
1509 #ifndef BOOST_NO_LONG_LONG
|
Chris@16
|
1510 template <class tag, class A1, class A2, class A3, class A4, class Policy>
|
Chris@16
|
1511 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
|
Chris@16
|
1512 {
|
Chris@16
|
1513 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
|
Chris@16
|
1514 number_type r = round(v, pol);
|
Chris@16
|
1515 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1516 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
|
Chris@16
|
1517 return r.template convert_to<long long>();
|
Chris@16
|
1518 }
|
Chris@16
|
1519 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1520 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
|
Chris@16
|
1521 {
|
Chris@16
|
1522 return llround(v, boost::math::policies::policy<>());
|
Chris@16
|
1523 }
|
Chris@16
|
1524 template <class T, expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
1525 inline long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
|
Chris@16
|
1526 {
|
Chris@16
|
1527 number<T, ExpressionTemplates> r = round(v, pol);
|
Chris@16
|
1528 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
|
Chris@16
|
1529 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
|
Chris@16
|
1530 return r.template convert_to<long long>();
|
Chris@16
|
1531 }
|
Chris@16
|
1532 template <class T, expression_template_option ExpressionTemplates>
|
Chris@16
|
1533 inline long long llround(const number<T, ExpressionTemplates>& v)
|
Chris@16
|
1534 {
|
Chris@16
|
1535 return llround(v, boost::math::policies::policy<>());
|
Chris@16
|
1536 }
|
Chris@16
|
1537 #endif
|
Chris@16
|
1538
|
Chris@16
|
1539 template <class B, expression_template_option ExpressionTemplates>
|
Chris@16
|
1540 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
Chris@16
|
1541 sqrt(const number<B, ExpressionTemplates>& x)
|
Chris@16
|
1542 {
|
Chris@16
|
1543 using default_ops::eval_integer_sqrt;
|
Chris@16
|
1544 number<B, ExpressionTemplates> s, r;
|
Chris@16
|
1545 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
Chris@16
|
1546 return s;
|
Chris@16
|
1547 }
|
Chris@16
|
1548
|
Chris@16
|
1549 template <class B, expression_template_option ExpressionTemplates>
|
Chris@16
|
1550 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
|
Chris@16
|
1551 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
|
Chris@16
|
1552 {
|
Chris@16
|
1553 using default_ops::eval_integer_sqrt;
|
Chris@16
|
1554 number<B, ExpressionTemplates> s;
|
Chris@16
|
1555 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
|
Chris@16
|
1556 return s;
|
Chris@16
|
1557 }
|
Chris@16
|
1558
|
Chris@16
|
1559 #define UNARY_OP_FUNCTOR(func, category)\
|
Chris@16
|
1560 namespace detail{\
|
Chris@16
|
1561 template <class Backend> \
|
Chris@16
|
1562 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
1563 {\
|
Chris@16
|
1564 void operator()(Backend& result, const Backend& arg)const\
|
Chris@16
|
1565 {\
|
Chris@16
|
1566 using default_ops::BOOST_JOIN(eval_,func);\
|
Chris@16
|
1567 BOOST_JOIN(eval_,func)(result, arg);\
|
Chris@16
|
1568 }\
|
Chris@16
|
1569 };\
|
Chris@16
|
1570 \
|
Chris@16
|
1571 }\
|
Chris@16
|
1572 \
|
Chris@16
|
1573 template <class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1574 inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category,\
|
Chris@16
|
1575 detail::expression<\
|
Chris@16
|
1576 detail::function\
|
Chris@16
|
1577 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1578 , detail::expression<tag, A1, A2, A3, A4> > \
|
Chris@16
|
1579 >::type \
|
Chris@16
|
1580 func(const detail::expression<tag, A1, A2, A3, A4>& arg)\
|
Chris@16
|
1581 {\
|
Chris@16
|
1582 return detail::expression<\
|
Chris@16
|
1583 detail::function\
|
Chris@16
|
1584 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1585 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1586 > (\
|
Chris@16
|
1587 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1588 , arg \
|
Chris@16
|
1589 );\
|
Chris@16
|
1590 }\
|
Chris@16
|
1591 template <class Backend> \
|
Chris@16
|
1592 inline typename enable_if_c<number_category<Backend>::value == category,\
|
Chris@16
|
1593 detail::expression<\
|
Chris@16
|
1594 detail::function\
|
Chris@16
|
1595 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1596 , number<Backend, et_on> > \
|
Chris@16
|
1597 >::type \
|
Chris@16
|
1598 func(const number<Backend, et_on>& arg)\
|
Chris@16
|
1599 {\
|
Chris@16
|
1600 return detail::expression<\
|
Chris@16
|
1601 detail::function\
|
Chris@16
|
1602 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1603 , number<Backend, et_on> \
|
Chris@16
|
1604 >(\
|
Chris@16
|
1605 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1606 , arg \
|
Chris@16
|
1607 );\
|
Chris@16
|
1608 }\
|
Chris@16
|
1609 template <class Backend> \
|
Chris@16
|
1610 inline typename boost::enable_if_c<\
|
Chris@16
|
1611 boost::multiprecision::number_category<Backend>::value == category,\
|
Chris@16
|
1612 number<Backend, et_off> >::type \
|
Chris@16
|
1613 func(const number<Backend, et_off>& arg)\
|
Chris@16
|
1614 {\
|
Chris@16
|
1615 number<Backend, et_off> result;\
|
Chris@16
|
1616 using default_ops::BOOST_JOIN(eval_,func);\
|
Chris@16
|
1617 BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\
|
Chris@16
|
1618 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1619 }
|
Chris@16
|
1620
|
Chris@16
|
1621 #define BINARY_OP_FUNCTOR(func, category)\
|
Chris@16
|
1622 namespace detail{\
|
Chris@16
|
1623 template <class Backend> \
|
Chris@16
|
1624 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
1625 {\
|
Chris@16
|
1626 void operator()(Backend& result, const Backend& arg, const Backend& a)const\
|
Chris@16
|
1627 {\
|
Chris@16
|
1628 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1629 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1630 }\
|
Chris@16
|
1631 template <class Arithmetic> \
|
Chris@16
|
1632 void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\
|
Chris@16
|
1633 {\
|
Chris@16
|
1634 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1635 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1636 }\
|
Chris@16
|
1637 template <class Arithmetic> \
|
Chris@16
|
1638 void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
|
Chris@16
|
1639 {\
|
Chris@16
|
1640 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1641 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1642 }\
|
Chris@16
|
1643 };\
|
Chris@16
|
1644 \
|
Chris@16
|
1645 }\
|
Chris@16
|
1646 template <class Backend> \
|
Chris@16
|
1647 inline typename enable_if_c<number_category<Backend>::value == category,\
|
Chris@16
|
1648 detail::expression<\
|
Chris@16
|
1649 detail::function\
|
Chris@16
|
1650 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1651 , number<Backend, et_on> \
|
Chris@16
|
1652 , number<Backend, et_on> > \
|
Chris@16
|
1653 >::type \
|
Chris@16
|
1654 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a)\
|
Chris@16
|
1655 {\
|
Chris@16
|
1656 return detail::expression<\
|
Chris@16
|
1657 detail::function\
|
Chris@16
|
1658 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1659 , number<Backend, et_on> \
|
Chris@16
|
1660 , number<Backend, et_on> \
|
Chris@16
|
1661 >(\
|
Chris@16
|
1662 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1663 , arg,\
|
Chris@16
|
1664 a\
|
Chris@16
|
1665 );\
|
Chris@16
|
1666 }\
|
Chris@16
|
1667 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1668 inline typename enable_if_c<\
|
Chris@16
|
1669 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1670 detail::expression<\
|
Chris@16
|
1671 detail::function\
|
Chris@16
|
1672 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1673 , number<Backend, et_on> \
|
Chris@16
|
1674 , detail::expression<tag, A1, A2, A3, A4> > \
|
Chris@16
|
1675 >::type \
|
Chris@16
|
1676 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
|
Chris@16
|
1677 {\
|
Chris@16
|
1678 return detail::expression<\
|
Chris@16
|
1679 detail::function\
|
Chris@16
|
1680 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1681 , number<Backend, et_on> \
|
Chris@16
|
1682 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1683 >(\
|
Chris@16
|
1684 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1685 , arg,\
|
Chris@16
|
1686 a\
|
Chris@16
|
1687 );\
|
Chris@16
|
1688 }\
|
Chris@16
|
1689 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
|
Chris@16
|
1690 inline typename enable_if_c<\
|
Chris@16
|
1691 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1692 detail::expression<\
|
Chris@16
|
1693 detail::function\
|
Chris@16
|
1694 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1695 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1696 , number<Backend, et_on> > \
|
Chris@16
|
1697 >::type \
|
Chris@16
|
1698 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)\
|
Chris@16
|
1699 {\
|
Chris@16
|
1700 return detail::expression<\
|
Chris@16
|
1701 detail::function\
|
Chris@16
|
1702 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1703 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1704 , number<Backend, et_on> \
|
Chris@16
|
1705 >(\
|
Chris@16
|
1706 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1707 , arg,\
|
Chris@16
|
1708 a\
|
Chris@16
|
1709 );\
|
Chris@16
|
1710 }\
|
Chris@16
|
1711 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
|
Chris@16
|
1712 inline typename enable_if_c<\
|
Chris@16
|
1713 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category),\
|
Chris@16
|
1714 detail::expression<\
|
Chris@16
|
1715 detail::function\
|
Chris@16
|
1716 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1717 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1718 , detail::expression<tagb, A1b, A2b, A3b, A4b> > \
|
Chris@16
|
1719 >::type \
|
Chris@16
|
1720 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)\
|
Chris@16
|
1721 {\
|
Chris@16
|
1722 return detail::expression<\
|
Chris@16
|
1723 detail::function\
|
Chris@16
|
1724 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1725 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1726 , detail::expression<tagb, A1b, A2b, A3b, A4b> \
|
Chris@16
|
1727 >(\
|
Chris@16
|
1728 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1729 , arg,\
|
Chris@16
|
1730 a\
|
Chris@16
|
1731 );\
|
Chris@16
|
1732 }\
|
Chris@16
|
1733 template <class Backend, class Arithmetic> \
|
Chris@16
|
1734 inline typename enable_if_c<\
|
Chris@16
|
1735 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1736 detail::expression<\
|
Chris@16
|
1737 detail::function\
|
Chris@16
|
1738 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1739 , number<Backend, et_on> \
|
Chris@16
|
1740 , Arithmetic\
|
Chris@16
|
1741 > \
|
Chris@16
|
1742 >::type \
|
Chris@16
|
1743 func(const number<Backend, et_on>& arg, const Arithmetic& a)\
|
Chris@16
|
1744 {\
|
Chris@16
|
1745 return detail::expression<\
|
Chris@16
|
1746 detail::function\
|
Chris@16
|
1747 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1748 , number<Backend, et_on> \
|
Chris@16
|
1749 , Arithmetic\
|
Chris@16
|
1750 >(\
|
Chris@16
|
1751 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1752 , arg,\
|
Chris@16
|
1753 a\
|
Chris@16
|
1754 );\
|
Chris@16
|
1755 }\
|
Chris@16
|
1756 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
|
Chris@16
|
1757 inline typename enable_if_c<\
|
Chris@16
|
1758 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1759 detail::expression<\
|
Chris@16
|
1760 detail::function\
|
Chris@16
|
1761 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1762 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1763 , Arithmetic\
|
Chris@16
|
1764 > \
|
Chris@16
|
1765 >::type \
|
Chris@16
|
1766 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a)\
|
Chris@16
|
1767 {\
|
Chris@16
|
1768 return detail::expression<\
|
Chris@16
|
1769 detail::function\
|
Chris@16
|
1770 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1771 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1772 , Arithmetic\
|
Chris@16
|
1773 >(\
|
Chris@16
|
1774 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1775 , arg,\
|
Chris@16
|
1776 a\
|
Chris@16
|
1777 );\
|
Chris@16
|
1778 }\
|
Chris@16
|
1779 template <class Backend, class Arithmetic> \
|
Chris@16
|
1780 inline typename enable_if_c<\
|
Chris@16
|
1781 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1782 detail::expression<\
|
Chris@16
|
1783 detail::function\
|
Chris@16
|
1784 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1785 , Arithmetic \
|
Chris@16
|
1786 , number<Backend, et_on> \
|
Chris@16
|
1787 > \
|
Chris@16
|
1788 >::type \
|
Chris@16
|
1789 func(const Arithmetic& 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 , Arithmetic \
|
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 Arithmetic> \
|
Chris@16
|
1803 inline typename enable_if_c<\
|
Chris@16
|
1804 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::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 , Arithmetic \
|
Chris@16
|
1809 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1810 > \
|
Chris@16
|
1811 >::type \
|
Chris@16
|
1812 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
|
Chris@16
|
1813 {\
|
Chris@16
|
1814 return detail::expression<\
|
Chris@16
|
1815 detail::function\
|
Chris@16
|
1816 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1817 , Arithmetic \
|
Chris@16
|
1818 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1819 >(\
|
Chris@16
|
1820 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1821 , arg,\
|
Chris@16
|
1822 a\
|
Chris@16
|
1823 );\
|
Chris@16
|
1824 }\
|
Chris@16
|
1825 template <class Backend> \
|
Chris@16
|
1826 inline typename enable_if_c<(number_category<Backend>::value == category),\
|
Chris@16
|
1827 number<Backend, et_off> >::type \
|
Chris@16
|
1828 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a)\
|
Chris@16
|
1829 {\
|
Chris@16
|
1830 number<Backend, et_off> result;\
|
Chris@16
|
1831 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1832 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\
|
Chris@16
|
1833 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1834 }\
|
Chris@16
|
1835 template <class Backend, class Arithmetic> \
|
Chris@16
|
1836 inline typename enable_if_c<\
|
Chris@16
|
1837 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1838 number<Backend, et_off> \
|
Chris@16
|
1839 >::type \
|
Chris@16
|
1840 func(const number<Backend, et_off>& arg, const Arithmetic& a)\
|
Chris@16
|
1841 {\
|
Chris@16
|
1842 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
|
Chris@16
|
1843 number<Backend, et_off> result;\
|
Chris@16
|
1844 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1845 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast<canonical_type>(a));\
|
Chris@16
|
1846 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1847 }\
|
Chris@16
|
1848 template <class Backend, class Arithmetic> \
|
Chris@16
|
1849 inline typename enable_if_c<\
|
Chris@16
|
1850 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
|
Chris@16
|
1851 number<Backend, et_off> \
|
Chris@16
|
1852 >::type \
|
Chris@16
|
1853 func(const Arithmetic& a, const number<Backend, et_off>& arg)\
|
Chris@16
|
1854 {\
|
Chris@16
|
1855 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
|
Chris@16
|
1856 number<Backend, et_off> result;\
|
Chris@16
|
1857 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1858 BOOST_JOIN(eval_,func)(result.backend(), static_cast<canonical_type>(a), arg.backend());\
|
Chris@16
|
1859 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1860 }\
|
Chris@16
|
1861
|
Chris@16
|
1862
|
Chris@16
|
1863 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\
|
Chris@16
|
1864 template <class tag, class A1, class A2, class A3, class A4> \
|
Chris@16
|
1865 inline typename enable_if_c<\
|
Chris@16
|
1866 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
|
Chris@16
|
1867 detail::expression<\
|
Chris@16
|
1868 detail::function\
|
Chris@16
|
1869 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1870 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1871 , Arg2> \
|
Chris@16
|
1872 >::type \
|
Chris@16
|
1873 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a)\
|
Chris@16
|
1874 {\
|
Chris@16
|
1875 return detail::expression<\
|
Chris@16
|
1876 detail::function\
|
Chris@16
|
1877 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
|
Chris@16
|
1878 , detail::expression<tag, A1, A2, A3, A4> \
|
Chris@16
|
1879 , Arg2\
|
Chris@16
|
1880 >(\
|
Chris@16
|
1881 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
|
Chris@16
|
1882 , arg, a \
|
Chris@16
|
1883 );\
|
Chris@16
|
1884 }\
|
Chris@16
|
1885 template <class Backend> \
|
Chris@16
|
1886 inline typename enable_if_c<\
|
Chris@16
|
1887 (number_category<Backend>::value == category),\
|
Chris@16
|
1888 detail::expression<\
|
Chris@16
|
1889 detail::function\
|
Chris@16
|
1890 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1891 , number<Backend, et_on> \
|
Chris@16
|
1892 , Arg2> \
|
Chris@16
|
1893 >::type \
|
Chris@16
|
1894 func(const number<Backend, et_on>& arg, Arg2 const& a)\
|
Chris@16
|
1895 {\
|
Chris@16
|
1896 return detail::expression<\
|
Chris@16
|
1897 detail::function\
|
Chris@16
|
1898 , detail::BOOST_JOIN(func, _funct)<Backend> \
|
Chris@16
|
1899 , number<Backend, et_on> \
|
Chris@16
|
1900 , Arg2\
|
Chris@16
|
1901 >(\
|
Chris@16
|
1902 detail::BOOST_JOIN(func, _funct)<Backend>() \
|
Chris@16
|
1903 , arg,\
|
Chris@16
|
1904 a\
|
Chris@16
|
1905 );\
|
Chris@16
|
1906 }\
|
Chris@16
|
1907 template <class Backend> \
|
Chris@16
|
1908 inline typename enable_if_c<\
|
Chris@16
|
1909 (number_category<Backend>::value == category),\
|
Chris@16
|
1910 number<Backend, et_off> >::type \
|
Chris@16
|
1911 func(const number<Backend, et_off>& arg, Arg2 const& a)\
|
Chris@16
|
1912 {\
|
Chris@16
|
1913 number<Backend, et_off> result;\
|
Chris@16
|
1914 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1915 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\
|
Chris@16
|
1916 return BOOST_MP_MOVE(result);\
|
Chris@16
|
1917 }\
|
Chris@16
|
1918
|
Chris@16
|
1919 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\
|
Chris@16
|
1920 namespace detail{\
|
Chris@16
|
1921 template <class Backend> \
|
Chris@16
|
1922 struct BOOST_JOIN(func, _funct)\
|
Chris@16
|
1923 {\
|
Chris@16
|
1924 template <class Arg>\
|
Chris@16
|
1925 void operator()(Backend& result, Backend const& arg, Arg a)const\
|
Chris@16
|
1926 {\
|
Chris@16
|
1927 using default_ops:: BOOST_JOIN(eval_,func);\
|
Chris@16
|
1928 BOOST_JOIN(eval_,func)(result, arg, a);\
|
Chris@16
|
1929 }\
|
Chris@16
|
1930 };\
|
Chris@16
|
1931 \
|
Chris@16
|
1932 }\
|
Chris@16
|
1933 \
|
Chris@16
|
1934 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
|
Chris@16
|
1935
|
Chris@16
|
1936 namespace detail{
|
Chris@16
|
1937 template <class Backend>
|
Chris@16
|
1938 struct abs_funct
|
Chris@16
|
1939 {
|
Chris@16
|
1940 void operator()(Backend& result, const Backend& arg)const
|
Chris@16
|
1941 {
|
Chris@16
|
1942 using default_ops::eval_abs;
|
Chris@16
|
1943 eval_abs(result, arg);
|
Chris@16
|
1944 }
|
Chris@16
|
1945 };
|
Chris@16
|
1946
|
Chris@16
|
1947 }
|
Chris@16
|
1948
|
Chris@16
|
1949 template <class tag, class A1, class A2, class A3, class A4>
|
Chris@16
|
1950 inline detail::expression<
|
Chris@16
|
1951 detail::function
|
Chris@16
|
1952 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
|
Chris@16
|
1953 , detail::expression<tag, A1, A2, A3, A4> >
|
Chris@16
|
1954 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
|
Chris@16
|
1955 {
|
Chris@16
|
1956 return detail::expression<
|
Chris@16
|
1957 detail::function
|
Chris@16
|
1958 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
|
Chris@16
|
1959 , detail::expression<tag, A1, A2, A3, A4>
|
Chris@16
|
1960 > (
|
Chris@16
|
1961 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>()
|
Chris@16
|
1962 , arg
|
Chris@16
|
1963 );
|
Chris@16
|
1964 }
|
Chris@16
|
1965 template <class Backend>
|
Chris@16
|
1966 inline detail::expression<
|
Chris@16
|
1967 detail::function
|
Chris@16
|
1968 , detail::abs_funct<Backend>
|
Chris@16
|
1969 , number<Backend, et_on> >
|
Chris@16
|
1970 abs(const number<Backend, et_on>& arg)
|
Chris@16
|
1971 {
|
Chris@16
|
1972 return detail::expression<
|
Chris@16
|
1973 detail::function
|
Chris@16
|
1974 , detail::abs_funct<Backend>
|
Chris@16
|
1975 , number<Backend, et_on>
|
Chris@16
|
1976 >(
|
Chris@16
|
1977 detail::abs_funct<Backend>()
|
Chris@16
|
1978 , arg
|
Chris@16
|
1979 );
|
Chris@16
|
1980 }
|
Chris@16
|
1981 template <class Backend>
|
Chris@16
|
1982 inline number<Backend, et_off>
|
Chris@16
|
1983 abs(const number<Backend, et_off>& arg)
|
Chris@16
|
1984 {
|
Chris@16
|
1985 number<Backend, et_off> result;
|
Chris@16
|
1986 using default_ops::eval_abs;
|
Chris@16
|
1987 eval_abs(result.backend(), arg.backend());
|
Chris@16
|
1988 return BOOST_MP_MOVE(result);
|
Chris@16
|
1989 }
|
Chris@16
|
1990
|
Chris@16
|
1991 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
|
Chris@16
|
1992 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
|
Chris@16
|
1993 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
|
Chris@16
|
1994 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
|
Chris@16
|
1995 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
|
Chris@16
|
1996 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
|
Chris@16
|
1997 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
|
Chris@16
|
1998 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
|
Chris@16
|
1999 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
|
Chris@16
|
2000 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
|
Chris@16
|
2001 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
|
Chris@16
|
2002 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
|
Chris@16
|
2003 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
|
Chris@16
|
2004 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
|
Chris@16
|
2005 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
|
Chris@16
|
2006 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
|
Chris@16
|
2007 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
|
Chris@16
|
2008 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
|
Chris@16
|
2009
|
Chris@16
|
2010 HETERO_BINARY_OP_FUNCTOR(ldexp, int, number_kind_floating_point)
|
Chris@16
|
2011 HETERO_BINARY_OP_FUNCTOR(frexp, int*, number_kind_floating_point)
|
Chris@16
|
2012 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
|
Chris@16
|
2013 HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
|
Chris@16
|
2014 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
|
Chris@16
|
2015 HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
|
Chris@16
|
2016 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
|
Chris@16
|
2017 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
|
Chris@16
|
2018 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
|
Chris@16
|
2019
|
Chris@16
|
2020 //
|
Chris@16
|
2021 // Integer functions:
|
Chris@16
|
2022 //
|
Chris@16
|
2023 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
|
Chris@16
|
2024 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
|
Chris@16
|
2025 HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
|
Chris@16
|
2026
|
Chris@16
|
2027 #undef BINARY_OP_FUNCTOR
|
Chris@16
|
2028 #undef UNARY_OP_FUNCTOR
|
Chris@16
|
2029
|
Chris@16
|
2030 } //namespace multiprecision
|
Chris@16
|
2031
|
Chris@16
|
2032 namespace math{
|
Chris@16
|
2033 //
|
Chris@16
|
2034 // Overload of Boost.Math functions that find the wrong overload when used with number:
|
Chris@16
|
2035 //
|
Chris@16
|
2036 namespace detail{
|
Chris@16
|
2037 template <class T> T sinc_pi_imp(T);
|
Chris@16
|
2038 template <class T> T sinhc_pi_imp(T);
|
Chris@16
|
2039 }
|
Chris@16
|
2040 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
2041 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
Chris@16
|
2042 {
|
Chris@16
|
2043 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
|
Chris@16
|
2044 }
|
Chris@16
|
2045
|
Chris@16
|
2046 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
2047 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
|
Chris@16
|
2048 {
|
Chris@16
|
2049 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
|
Chris@16
|
2050 }
|
Chris@16
|
2051
|
Chris@16
|
2052 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
2053 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
|
Chris@16
|
2054 {
|
Chris@16
|
2055 return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
|
Chris@16
|
2056 }
|
Chris@16
|
2057
|
Chris@16
|
2058 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
|
Chris@16
|
2059 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
|
Chris@16
|
2060 {
|
Chris@16
|
2061 return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
|
Chris@16
|
2062 }
|
Chris@16
|
2063
|
Chris@16
|
2064 #ifdef BOOST_MSVC
|
Chris@16
|
2065 #pragma warning(pop)
|
Chris@16
|
2066 #endif
|
Chris@16
|
2067 } // namespace math
|
Chris@16
|
2068 } // namespace boost
|
Chris@16
|
2069
|
Chris@16
|
2070 //
|
Chris@16
|
2071 // This has to come last of all:
|
Chris@16
|
2072 //
|
Chris@16
|
2073 #include <boost/multiprecision/detail/no_et_ops.hpp>
|
Chris@16
|
2074 #include <boost/multiprecision/detail/et_ops.hpp>
|
Chris@16
|
2075
|
Chris@16
|
2076 #endif
|
Chris@16
|
2077
|