1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2018 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_MULTIPRECISION_COMPLEX_ADAPTOR_HPP
7 #define BOOST_MULTIPRECISION_COMPLEX_ADAPTOR_HPP
9 #include <boost/multiprecision/number.hpp>
10 #include <boost/cstdint.hpp>
11 #include <boost/multiprecision/detail/digits.hpp>
12 #include <boost/functional/hash_fwd.hpp>
13 #include <boost/type_traits/is_complex.hpp>
19 namespace multiprecision {
22 template <class Backend>
23 struct complex_adaptor
26 Backend m_real, m_imag;
33 const Backend& real_data() const
41 const Backend& imag_data() const
46 typedef typename Backend::signed_types signed_types;
47 typedef typename Backend::unsigned_types unsigned_types;
48 typedef typename Backend::float_types float_types;
49 typedef typename Backend::exponent_type exponent_type;
52 complex_adaptor(const complex_adaptor& o) : m_real(o.real_data()), m_imag(o.imag_data()) {}
53 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
54 complex_adaptor(complex_adaptor&& o) : m_real(std::move(o.real_data())), m_imag(std::move(o.imag_data()))
57 complex_adaptor(const Backend& val)
61 complex_adaptor(const std::complex<float>& val)
63 m_real = (long double)val.real();
64 m_imag = (long double)val.imag();
66 complex_adaptor(const std::complex<double>& val)
68 m_real = (long double)val.real();
69 m_imag = (long double)val.imag();
71 complex_adaptor(const std::complex<long double>& val)
77 complex_adaptor& operator=(const complex_adaptor& o)
79 m_real = o.real_data();
80 m_imag = o.imag_data();
83 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
84 complex_adaptor& operator=(complex_adaptor&& o) BOOST_NOEXCEPT
86 m_real = std::move(o.real_data());
87 m_imag = std::move(o.imag_data());
92 complex_adaptor& operator=(const V& v)
94 typedef typename mpl::front<unsigned_types>::type ui_type;
100 complex_adaptor& operator=(const std::complex<T>& val)
102 m_real = (long double)val.real();
103 m_imag = (long double)val.imag();
106 complex_adaptor& operator=(const char* s)
108 typedef typename mpl::front<unsigned_types>::type ui_type;
111 using default_ops::eval_fpclassify;
113 if (s && (*s == '('))
117 while (*p && (*p != ',') && (*p != ')'))
121 real_data() = part.c_str();
125 if (*p && (*p != ')'))
128 while (*p && (*p != ')'))
130 part.assign(s + 1, p);
135 imag_data() = part.c_str();
139 if (eval_fpclassify(imag_data()) == (int)FP_NAN)
141 real_data() = imag_data();
152 int compare(const complex_adaptor& o) const
154 // They are either equal or not:
155 return (m_real.compare(o.real_data()) == 0) && (m_imag.compare(o.imag_data()) == 0) ? 0 : 1;
158 int compare(const T& val) const
160 using default_ops::eval_is_zero;
161 return (m_real.compare(val) == 0) && eval_is_zero(m_imag) ? 0 : 1;
163 void swap(complex_adaptor& o)
165 real_data().swap(o.real_data());
166 imag_data().swap(o.imag_data());
168 std::string str(std::streamsize dig, std::ios_base::fmtflags f) const
170 using default_ops::eval_is_zero;
171 if (eval_is_zero(imag_data()))
172 return m_real.str(dig, f);
173 return "(" + m_real.str(dig, f) + "," + m_imag.str(dig, f) + ")";
182 template <class Backend, class T>
183 inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const complex_adaptor<Backend>& a, const T& b) BOOST_NOEXCEPT
185 return a.compare(b) == 0;
188 template <class Backend>
189 inline void eval_add(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& o)
191 eval_add(result.real_data(), o.real_data());
192 eval_add(result.imag_data(), o.imag_data());
194 template <class Backend>
195 inline void eval_subtract(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& o)
197 eval_subtract(result.real_data(), o.real_data());
198 eval_subtract(result.imag_data(), o.imag_data());
200 template <class Backend>
201 inline void eval_multiply(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& o)
204 eval_multiply(t1, result.real_data(), o.real_data());
205 eval_multiply(t2, result.imag_data(), o.imag_data());
206 eval_subtract(t3, t1, t2);
207 eval_multiply(t1, result.real_data(), o.imag_data());
208 eval_multiply(t2, result.imag_data(), o.real_data());
210 result.real_data() = BOOST_MP_MOVE(t3);
211 result.imag_data() = BOOST_MP_MOVE(t1);
213 template <class Backend>
214 inline void eval_divide(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& z)
217 using default_ops::eval_add;
218 using default_ops::eval_divide;
219 using default_ops::eval_fabs;
220 using default_ops::eval_is_zero;
221 using default_ops::eval_multiply;
222 using default_ops::eval_subtract;
225 if (eval_is_zero(z.imag_data()))
227 eval_divide(result.real_data(), z.real_data());
228 eval_divide(result.imag_data(), z.real_data());
232 eval_fabs(t1, z.real_data());
233 eval_fabs(t2, z.imag_data());
234 if (t1.compare(t2) < 0)
236 eval_divide(t1, z.real_data(), z.imag_data()); // t1 = c/d
237 eval_multiply(t2, z.real_data(), t1);
238 eval_add(t2, z.imag_data()); // denom = c * (c/d) + d
239 Backend t_real(result.real_data());
240 // real = (a * (c/d) + b) / (denom)
241 eval_multiply(result.real_data(), t1);
242 eval_add(result.real_data(), result.imag_data());
243 eval_divide(result.real_data(), t2);
244 // imag = (b * c/d - a) / denom
245 eval_multiply(result.imag_data(), t1);
246 eval_subtract(result.imag_data(), t_real);
247 eval_divide(result.imag_data(), t2);
251 eval_divide(t1, z.imag_data(), z.real_data()); // t1 = d/c
252 eval_multiply(t2, z.imag_data(), t1);
253 eval_add(t2, z.real_data()); // denom = d * d/c + c
255 Backend r_t(result.real_data());
256 Backend i_t(result.imag_data());
258 // real = (b * d/c + a) / denom
259 eval_multiply(result.real_data(), result.imag_data(), t1);
260 eval_add(result.real_data(), r_t);
261 eval_divide(result.real_data(), t2);
262 // imag = (-a * d/c + b) / denom
263 eval_multiply(result.imag_data(), r_t, t1);
264 result.imag_data().negate();
265 eval_add(result.imag_data(), i_t);
266 eval_divide(result.imag_data(), t2);
269 template <class Backend, class T>
270 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_add(complex_adaptor<Backend>& result, const T& scalar)
272 using default_ops::eval_add;
273 eval_add(result.real_data(), scalar);
275 template <class Backend, class T>
276 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_subtract(complex_adaptor<Backend>& result, const T& scalar)
278 using default_ops::eval_subtract;
279 eval_subtract(result.real_data(), scalar);
281 template <class Backend, class T>
282 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_multiply(complex_adaptor<Backend>& result, const T& scalar)
284 using default_ops::eval_multiply;
285 eval_multiply(result.real_data(), scalar);
286 eval_multiply(result.imag_data(), scalar);
288 template <class Backend, class T>
289 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_divide(complex_adaptor<Backend>& result, const T& scalar)
291 using default_ops::eval_divide;
292 eval_divide(result.real_data(), scalar);
293 eval_divide(result.imag_data(), scalar);
295 // Optimised 3 arg versions:
296 template <class Backend, class T>
297 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_add(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& a, const T& scalar)
299 using default_ops::eval_add;
300 eval_add(result.real_data(), a.real_data(), scalar);
301 result.imag_data() = a.imag_data();
303 template <class Backend, class T>
304 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_subtract(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& a, const T& scalar)
306 using default_ops::eval_subtract;
307 eval_subtract(result.real_data(), a.real_data(), scalar);
308 result.imag_data() = a.imag_data();
310 template <class Backend, class T>
311 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_multiply(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& a, const T& scalar)
313 using default_ops::eval_multiply;
314 eval_multiply(result.real_data(), a.real_data(), scalar);
315 eval_multiply(result.imag_data(), a.imag_data(), scalar);
317 template <class Backend, class T>
318 inline typename boost::disable_if_c<boost::is_same<complex_adaptor<Backend>, T>::value>::type eval_divide(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& a, const T& scalar)
320 using default_ops::eval_divide;
321 eval_divide(result.real_data(), a.real_data(), scalar);
322 eval_divide(result.imag_data(), a.imag_data(), scalar);
325 template <class Backend>
326 inline bool eval_is_zero(const complex_adaptor<Backend>& val) BOOST_NOEXCEPT
328 using default_ops::eval_is_zero;
329 return eval_is_zero(val.real_data()) && eval_is_zero(val.imag_data());
331 template <class Backend>
332 inline int eval_get_sign(const complex_adaptor<Backend>&)
334 BOOST_STATIC_ASSERT_MSG(sizeof(Backend) == UINT_MAX, "Complex numbers have no sign bit."); // designed to always fail
338 template <class Result, class Backend>
339 inline typename disable_if_c<boost::is_complex<Result>::value>::type eval_convert_to(Result* result, const complex_adaptor<Backend>& val)
341 using default_ops::eval_convert_to;
342 using default_ops::eval_is_zero;
343 if (!eval_is_zero(val.imag_data()))
345 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert imaginary number to scalar."));
347 eval_convert_to(result, val.real_data());
350 template <class Backend, class T>
351 inline void assign_components(complex_adaptor<Backend>& result, const T& a, const T& b)
353 result.real_data() = a;
354 result.imag_data() = b;
358 // Native non-member operations:
360 template <class Backend>
361 inline void eval_sqrt(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& val)
363 // Use the following:
364 // sqrt(z) = (s, zi / 2s) for zr >= 0
365 // (|zi| / 2s, +-s) for zr < 0
366 // where s = sqrt{ [ |zr| + sqrt(zr^2 + zi^2) ] / 2 },
367 // and the +- sign is the same as the sign of zi.
368 using default_ops::eval_abs;
369 using default_ops::eval_add;
370 using default_ops::eval_divide;
371 using default_ops::eval_get_sign;
372 using default_ops::eval_is_zero;
374 if (eval_is_zero(val.imag_data()) && (eval_get_sign(val.real_data()) >= 0))
376 static const typename mpl::front<typename Backend::unsigned_types>::type zero = 0u;
377 eval_sqrt(result.real_data(), val.real_data());
378 result.imag_data() = zero;
382 const bool __my_real_part_is_neg(eval_get_sign(val.real_data()) < 0);
384 Backend __my_real_part_fabs(val.real_data());
385 if (__my_real_part_is_neg)
386 __my_real_part_fabs.negate();
388 Backend t, __my_sqrt_part;
389 eval_abs(__my_sqrt_part, val);
390 eval_add(__my_sqrt_part, __my_real_part_fabs);
391 eval_ldexp(t, __my_sqrt_part, -1);
392 eval_sqrt(__my_sqrt_part, t);
394 if (__my_real_part_is_neg == false)
396 eval_ldexp(t, __my_sqrt_part, 1);
397 eval_divide(result.imag_data(), val.imag_data(), t);
398 result.real_data() = __my_sqrt_part;
402 const bool __my_imag_part_is_neg(eval_get_sign(val.imag_data()) < 0);
404 Backend __my_imag_part_fabs(val.imag_data());
405 if (__my_imag_part_is_neg)
406 __my_imag_part_fabs.negate();
408 eval_ldexp(t, __my_sqrt_part, 1);
409 eval_divide(result.real_data(), __my_imag_part_fabs, t);
410 if (__my_imag_part_is_neg)
411 __my_sqrt_part.negate();
412 result.imag_data() = __my_sqrt_part;
416 template <class Backend>
417 inline void eval_abs(Backend& result, const complex_adaptor<Backend>& val)
420 eval_multiply(t1, val.real_data(), val.real_data());
421 eval_multiply(t2, val.imag_data(), val.imag_data());
423 eval_sqrt(result, t1);
426 template <class Backend>
427 inline void eval_pow(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& b, const complex_adaptor<Backend>& e)
429 using default_ops::eval_acos;
430 using default_ops::eval_cos;
431 using default_ops::eval_exp;
432 using default_ops::eval_get_sign;
433 using default_ops::eval_is_zero;
434 using default_ops::eval_multiply;
435 using default_ops::eval_sin;
439 typename mpl::front<typename Backend::unsigned_types>::type one(1);
443 else if (eval_is_zero(b))
445 if (eval_is_zero(e.real_data()))
447 Backend n = std::numeric_limits<number<Backend> >::quiet_NaN().backend();
448 result.real_data() = n;
449 result.imag_data() = n;
451 else if (eval_get_sign(e.real_data()) < 0)
453 Backend n = std::numeric_limits<number<Backend> >::infinity().backend();
454 result.real_data() = n;
455 typename mpl::front<typename Backend::unsigned_types>::type zero(0);
456 if (eval_is_zero(e.imag_data()))
457 result.imag_data() = zero;
459 result.imag_data() = n;
463 typename mpl::front<typename Backend::unsigned_types>::type zero(0);
468 complex_adaptor<Backend> t;
474 template <class Backend>
475 inline void eval_exp(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
477 using default_ops::eval_cos;
478 using default_ops::eval_exp;
479 using default_ops::eval_is_zero;
480 using default_ops::eval_multiply;
481 using default_ops::eval_sin;
483 if (eval_is_zero(arg.imag_data()))
485 eval_exp(result.real_data(), arg.real_data());
486 typename mpl::front<typename Backend::unsigned_types>::type zero(0);
487 result.imag_data() = zero;
490 eval_cos(result.real_data(), arg.imag_data());
491 eval_sin(result.imag_data(), arg.imag_data());
493 eval_exp(e, arg.real_data());
494 if (eval_is_zero(result.real_data()))
495 eval_multiply(result.imag_data(), e);
496 else if (eval_is_zero(result.imag_data()))
497 eval_multiply(result.real_data(), e);
499 eval_multiply(result, e);
502 template <class Backend>
503 inline void eval_log(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
505 using default_ops::eval_add;
506 using default_ops::eval_atan2;
507 using default_ops::eval_get_sign;
508 using default_ops::eval_is_zero;
509 using default_ops::eval_log;
510 using default_ops::eval_multiply;
512 if (eval_is_zero(arg.imag_data()) && (eval_get_sign(arg.real_data()) >= 0))
514 eval_log(result.real_data(), arg.real_data());
515 typename mpl::front<typename Backend::unsigned_types>::type zero(0);
516 result.imag_data() = zero;
521 eval_multiply(t1, arg.real_data(), arg.real_data());
522 eval_multiply(t2, arg.imag_data(), arg.imag_data());
525 eval_ldexp(result.real_data(), t2, -1);
526 eval_atan2(result.imag_data(), arg.imag_data(), arg.real_data());
529 template <class Backend>
530 inline void eval_log10(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
532 using default_ops::eval_divide;
533 using default_ops::eval_log;
535 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
540 eval_log(l_ten, ten);
541 eval_log(result, arg);
542 eval_divide(result, l_ten);
545 template <class Backend>
546 inline void eval_sin(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
548 using default_ops::eval_cos;
549 using default_ops::eval_cosh;
550 using default_ops::eval_sin;
551 using default_ops::eval_sinh;
554 eval_sin(t1, arg.real_data());
555 eval_cosh(t2, arg.imag_data());
556 eval_multiply(result.real_data(), t1, t2);
558 eval_cos(t1, arg.real_data());
559 eval_sinh(t2, arg.imag_data());
560 eval_multiply(result.imag_data(), t1, t2);
563 template <class Backend>
564 inline void eval_cos(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
566 using default_ops::eval_cos;
567 using default_ops::eval_cosh;
568 using default_ops::eval_sin;
569 using default_ops::eval_sinh;
572 eval_cos(t1, arg.real_data());
573 eval_cosh(t2, arg.imag_data());
574 eval_multiply(result.real_data(), t1, t2);
576 eval_sin(t1, arg.real_data());
577 eval_sinh(t2, arg.imag_data());
578 eval_multiply(result.imag_data(), t1, t2);
579 result.imag_data().negate();
582 template <class Backend>
583 inline void eval_tan(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
585 complex_adaptor<Backend> c;
587 eval_sin(result, arg);
588 eval_divide(result, c);
591 template <class Backend>
592 inline void eval_asin(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
594 using default_ops::eval_add;
595 using default_ops::eval_multiply;
597 if (eval_is_zero(arg))
603 complex_adaptor<Backend> t1, t2;
604 assign_components(t1, arg.imag_data(), arg.real_data());
605 t1.real_data().negate();
608 assign_components(result, t2.imag_data(), t2.real_data());
609 result.imag_data().negate();
612 template <class Backend>
613 inline void eval_acos(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
615 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
617 using default_ops::eval_asin;
620 t1 = static_cast<ui_type>(1u);
621 eval_asin(half_pi, t1);
622 eval_asin(result, arg);
624 eval_add(result.real_data(), half_pi);
627 template <class Backend>
628 inline void eval_atan(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
630 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
631 ui_type one = (ui_type)1u;
633 using default_ops::eval_add;
634 using default_ops::eval_is_zero;
635 using default_ops::eval_log;
636 using default_ops::eval_subtract;
638 complex_adaptor<Backend> __my_z_times_i, t1, t2, t3;
639 assign_components(__my_z_times_i, arg.imag_data(), arg.real_data());
640 __my_z_times_i.real_data().negate();
642 eval_add(t1, __my_z_times_i, one);
644 eval_subtract(t1, one, __my_z_times_i);
646 eval_subtract(t1, t3, t2);
648 eval_ldexp(result.real_data(), t1.imag_data(), -1);
649 eval_ldexp(result.imag_data(), t1.real_data(), -1);
650 if (!eval_is_zero(result.real_data()))
651 result.real_data().negate();
654 template <class Backend>
655 inline void eval_sinh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
657 using default_ops::eval_cos;
658 using default_ops::eval_cosh;
659 using default_ops::eval_sin;
660 using default_ops::eval_sinh;
663 eval_cos(t1, arg.imag_data());
664 eval_sinh(t2, arg.real_data());
665 eval_multiply(result.real_data(), t1, t2);
667 eval_cosh(t1, arg.real_data());
668 eval_sin(t2, arg.imag_data());
669 eval_multiply(result.imag_data(), t1, t2);
672 template <class Backend>
673 inline void eval_cosh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
675 using default_ops::eval_cos;
676 using default_ops::eval_cosh;
677 using default_ops::eval_sin;
678 using default_ops::eval_sinh;
681 eval_cos(t1, arg.imag_data());
682 eval_cosh(t2, arg.real_data());
683 eval_multiply(result.real_data(), t1, t2);
685 eval_sin(t1, arg.imag_data());
686 eval_sinh(t2, arg.real_data());
687 eval_multiply(result.imag_data(), t1, t2);
690 template <class Backend>
691 inline void eval_tanh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
693 using default_ops::eval_divide;
694 complex_adaptor<Backend> s, c;
697 eval_divide(result, s, c);
700 template <class Backend>
701 inline void eval_asinh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
703 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
704 ui_type one = (ui_type)1u;
706 using default_ops::eval_add;
707 using default_ops::eval_log;
708 using default_ops::eval_multiply;
710 complex_adaptor<Backend> t1, t2;
711 eval_multiply(t1, arg, arg);
715 eval_log(result, t2);
718 template <class Backend>
719 inline void eval_acosh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
721 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
722 ui_type one = (ui_type)1u;
724 using default_ops::eval_add;
725 using default_ops::eval_divide;
726 using default_ops::eval_log;
727 using default_ops::eval_multiply;
728 using default_ops::eval_subtract;
730 complex_adaptor<Backend> __my_zp(arg);
731 eval_add(__my_zp.real_data(), one);
732 complex_adaptor<Backend> __my_zm(arg);
733 eval_subtract(__my_zm.real_data(), one);
735 complex_adaptor<Backend> t1, t2;
736 eval_divide(t1, __my_zm, __my_zp);
738 eval_multiply(t2, __my_zp);
740 eval_log(result, t2);
743 template <class Backend>
744 inline void eval_atanh(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
746 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
747 ui_type one = (ui_type)1u;
749 using default_ops::eval_add;
750 using default_ops::eval_divide;
751 using default_ops::eval_log;
752 using default_ops::eval_multiply;
753 using default_ops::eval_subtract;
755 complex_adaptor<Backend> t1, t2, t3;
756 eval_add(t1, arg, one);
758 eval_subtract(t1, one, arg);
760 eval_subtract(t2, t3);
762 eval_ldexp(result.real_data(), t2.real_data(), -1);
763 eval_ldexp(result.imag_data(), t2.imag_data(), -1);
766 template <class Backend>
767 inline void eval_conj(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
770 result.imag_data().negate();
773 template <class Backend>
774 inline void eval_proj(complex_adaptor<Backend>& result, const complex_adaptor<Backend>& arg)
776 using default_ops::eval_get_sign;
778 typedef typename mpl::front<typename Backend::unsigned_types>::type ui_type;
779 ui_type zero = (ui_type)0u;
781 int c1 = eval_fpclassify(arg.real_data());
782 int c2 = eval_fpclassify(arg.imag_data());
783 if (c1 == FP_INFINITE)
785 result.real_data() = arg.real_data();
786 if (eval_get_sign(result.real_data()) < 0)
787 result.real_data().negate();
788 result.imag_data() = zero;
789 if (eval_get_sign(arg.imag_data()) < 0)
790 result.imag_data().negate();
792 else if (c2 == FP_INFINITE)
794 result.real_data() = arg.imag_data();
795 if (eval_get_sign(result.real_data()) < 0)
796 result.real_data().negate();
797 result.imag_data() = zero;
798 if (eval_get_sign(arg.imag_data()) < 0)
799 result.imag_data().negate();
805 template <class Backend>
806 inline void eval_real(Backend& result, const complex_adaptor<Backend>& arg)
808 result = arg.real_data();
810 template <class Backend>
811 inline void eval_imag(Backend& result, const complex_adaptor<Backend>& arg)
813 result = arg.imag_data();
816 template <class Backend, class T>
817 inline void eval_set_imag(complex_adaptor<Backend>& result, const T& arg)
819 result.imag_data() = arg;
822 template <class Backend, class T>
823 inline void eval_set_real(complex_adaptor<Backend>& result, const T& arg)
825 result.real_data() = arg;
828 template <class Backend>
829 inline std::size_t hash_value(const complex_adaptor<Backend>& val)
831 std::size_t result = hash_value(val.real_data());
832 std::size_t result2 = hash_value(val.imag_data());
833 boost::hash_combine(result, result2);
837 } // namespace backends
839 using boost::multiprecision::backends::complex_adaptor;
841 template <class Backend>
842 struct number_category<complex_adaptor<Backend> > : public boost::mpl::int_<boost::multiprecision::number_kind_complex>
845 template <class Backend, expression_template_option ExpressionTemplates>
846 struct component_type<number<complex_adaptor<Backend>, ExpressionTemplates> >
848 typedef number<Backend, ExpressionTemplates> type;
851 template <class Backend, expression_template_option ExpressionTemplates>
852 struct complex_result_from_scalar<number<Backend, ExpressionTemplates> >
854 typedef number<complex_adaptor<Backend>, ExpressionTemplates> type;
859 } // namespace boost::multiprecision