complex.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. // Boost.Units - A C++ library for zero-overhead dimensional analysis and
  2. // unit/quantity manipulation and conversion
  3. //
  4. // Copyright (C) 2003-2008 Matthias Christian Schabel
  5. // Copyright (C) 2008 Steven Watanabe
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. /**
  11. \file
  12. \brief complex.cpp
  13. \details
  14. Demonstrate a complex number class that functions correctly with quantities.
  15. Output:
  16. @verbatim
  17. //[complex_output_1
  18. +L = 2 + 1 i m
  19. -L = -2 + -1 i m
  20. L+L = 4 + 2 i m
  21. L-L = 0 + 0 i m
  22. L*L = 3 + 4 i m^2
  23. L/L = 1 + 0 i dimensionless
  24. L^3 = 2 + 11 i m^3
  25. L^(3/2) = 2.56713 + 2.14247 i m^(3/2)
  26. 3vL = 1.29207 + 0.201294 i m^(1/3)
  27. (3/2)vL = 1.62894 + 0.520175 i m^(2/3)
  28. //]
  29. //[complex_output_2
  30. +L = 2 m + 1 m i
  31. -L = -2 m + -1 m i
  32. L+L = 4 m + 2 m i
  33. L-L = 0 m + 0 m i
  34. L*L = 3 m^2 + 4 m^2 i
  35. L/L = 1 dimensionless + 0 dimensionless i
  36. L^3 = 2 m^3 + 11 m^3 i
  37. L^(3/2) = 2.56713 m^(3/2) + 2.14247 m^(3/2) i
  38. 3vL = 1.29207 m^(1/3) + 0.201294 m^(1/3) i
  39. (3/2)vL = 1.62894 m^(2/3) + 0.520175 m^(2/3) i
  40. //]
  41. @endverbatim
  42. **/
  43. #include <cmath>
  44. #include <complex>
  45. #include <iostream>
  46. #include <boost/mpl/list.hpp>
  47. #include <boost/units/io.hpp>
  48. #include <boost/units/pow.hpp>
  49. #include <boost/units/quantity.hpp>
  50. #include "test_system.hpp"
  51. //[complex_class_snippet_1
  52. namespace boost {
  53. namespace units {
  54. /// replacement complex class
  55. template<class T>
  56. class complex
  57. {
  58. public:
  59. typedef complex<T> this_type;
  60. constexpr complex(const T& r = 0,const T& i = 0) : r_(r),i_(i) { }
  61. constexpr complex(const this_type& source) : r_(source.r_),i_(source.i_) { }
  62. constexpr this_type& operator=(const this_type& source)
  63. {
  64. if (this == &source) return *this;
  65. r_ = source.r_;
  66. i_ = source.i_;
  67. return *this;
  68. }
  69. constexpr T& real() { return r_; }
  70. constexpr T& imag() { return i_; }
  71. constexpr const T& real() const { return r_; }
  72. constexpr const T& imag() const { return i_; }
  73. constexpr this_type& operator+=(const T& val)
  74. {
  75. r_ += val;
  76. return *this;
  77. }
  78. constexpr this_type& operator-=(const T& val)
  79. {
  80. r_ -= val;
  81. return *this;
  82. }
  83. constexpr this_type& operator*=(const T& val)
  84. {
  85. r_ *= val;
  86. i_ *= val;
  87. return *this;
  88. }
  89. constexpr this_type& operator/=(const T& val)
  90. {
  91. r_ /= val;
  92. i_ /= val;
  93. return *this;
  94. }
  95. constexpr this_type& operator+=(const this_type& source)
  96. {
  97. r_ += source.r_;
  98. i_ += source.i_;
  99. return *this;
  100. }
  101. constexpr this_type& operator-=(const this_type& source)
  102. {
  103. r_ -= source.r_;
  104. i_ -= source.i_;
  105. return *this;
  106. }
  107. constexpr this_type& operator*=(const this_type& source)
  108. {
  109. *this = *this * source;
  110. return *this;
  111. }
  112. constexpr this_type& operator/=(const this_type& source)
  113. {
  114. *this = *this / source;
  115. return *this;
  116. }
  117. private:
  118. T r_,i_;
  119. };
  120. }
  121. }
  122. #if BOOST_UNITS_HAS_BOOST_TYPEOF
  123. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  124. BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::complex, 1)
  125. #endif
  126. namespace boost {
  127. namespace units {
  128. template<class X>
  129. constexpr
  130. complex<typename unary_plus_typeof_helper<X>::type>
  131. operator+(const complex<X>& x)
  132. {
  133. typedef typename unary_plus_typeof_helper<X>::type type;
  134. return complex<type>(x.real(),x.imag());
  135. }
  136. template<class X>
  137. constexpr
  138. complex<typename unary_minus_typeof_helper<X>::type>
  139. operator-(const complex<X>& x)
  140. {
  141. typedef typename unary_minus_typeof_helper<X>::type type;
  142. return complex<type>(-x.real(),-x.imag());
  143. }
  144. template<class X,class Y>
  145. constexpr
  146. complex<typename add_typeof_helper<X,Y>::type>
  147. operator+(const complex<X>& x,const complex<Y>& y)
  148. {
  149. typedef typename boost::units::add_typeof_helper<X,Y>::type type;
  150. return complex<type>(x.real()+y.real(),x.imag()+y.imag());
  151. }
  152. template<class X,class Y>
  153. constexpr
  154. complex<typename boost::units::subtract_typeof_helper<X,Y>::type>
  155. operator-(const complex<X>& x,const complex<Y>& y)
  156. {
  157. typedef typename boost::units::subtract_typeof_helper<X,Y>::type type;
  158. return complex<type>(x.real()-y.real(),x.imag()-y.imag());
  159. }
  160. template<class X,class Y>
  161. constexpr
  162. complex<typename boost::units::multiply_typeof_helper<X,Y>::type>
  163. operator*(const complex<X>& x,const complex<Y>& y)
  164. {
  165. typedef typename boost::units::multiply_typeof_helper<X,Y>::type type;
  166. return complex<type>(x.real()*y.real() - x.imag()*y.imag(),
  167. x.real()*y.imag() + x.imag()*y.real());
  168. // fully correct implementation has more complex return type
  169. //
  170. // typedef typename boost::units::multiply_typeof_helper<X,Y>::type xy_type;
  171. //
  172. // typedef typename boost::units::add_typeof_helper<
  173. // xy_type,xy_type>::type xy_plus_xy_type;
  174. // typedef typename
  175. // boost::units::subtract_typeof_helper<xy_type,xy_type>::type
  176. // xy_minus_xy_type;
  177. //
  178. // BOOST_STATIC_ASSERT((boost::is_same<xy_plus_xy_type,
  179. // xy_minus_xy_type>::value == true));
  180. //
  181. // return complex<xy_plus_xy_type>(x.real()*y.real()-x.imag()*y.imag(),
  182. // x.real()*y.imag()+x.imag()*y.real());
  183. }
  184. template<class X,class Y>
  185. constexpr
  186. complex<typename boost::units::divide_typeof_helper<X,Y>::type>
  187. operator/(const complex<X>& x,const complex<Y>& y)
  188. {
  189. // naive implementation of complex division
  190. typedef typename boost::units::divide_typeof_helper<X,Y>::type type;
  191. return complex<type>((x.real()*y.real()+x.imag()*y.imag())/
  192. (y.real()*y.real()+y.imag()*y.imag()),
  193. (x.imag()*y.real()-x.real()*y.imag())/
  194. (y.real()*y.real()+y.imag()*y.imag()));
  195. // fully correct implementation has more complex return type
  196. //
  197. // typedef typename boost::units::multiply_typeof_helper<X,Y>::type xy_type;
  198. // typedef typename boost::units::multiply_typeof_helper<Y,Y>::type yy_type;
  199. //
  200. // typedef typename boost::units::add_typeof_helper<xy_type, xy_type>::type
  201. // xy_plus_xy_type;
  202. // typedef typename boost::units::subtract_typeof_helper<
  203. // xy_type,xy_type>::type xy_minus_xy_type;
  204. //
  205. // typedef typename boost::units::divide_typeof_helper<
  206. // xy_plus_xy_type,yy_type>::type xy_plus_xy_over_yy_type;
  207. // typedef typename boost::units::divide_typeof_helper<
  208. // xy_minus_xy_type,yy_type>::type xy_minus_xy_over_yy_type;
  209. //
  210. // BOOST_STATIC_ASSERT((boost::is_same<xy_plus_xy_over_yy_type,
  211. // xy_minus_xy_over_yy_type>::value == true));
  212. //
  213. // return complex<xy_plus_xy_over_yy_type>(
  214. // (x.real()*y.real()+x.imag()*y.imag())/
  215. // (y.real()*y.real()+y.imag()*y.imag()),
  216. // (x.imag()*y.real()-x.real()*y.imag())/
  217. // (y.real()*y.real()+y.imag()*y.imag()));
  218. }
  219. template<class Y>
  220. complex<Y>
  221. pow(const complex<Y>& x,const Y& y)
  222. {
  223. std::complex<Y> tmp(x.real(),x.imag());
  224. tmp = std::pow(tmp,y);
  225. return complex<Y>(tmp.real(),tmp.imag());
  226. }
  227. template<class Y>
  228. std::ostream& operator<<(std::ostream& os,const complex<Y>& val)
  229. {
  230. os << val.real() << " + " << val.imag() << " i";
  231. return os;
  232. }
  233. /// specialize power typeof helper for complex<Y>
  234. template<class Y,long N,long D>
  235. struct power_typeof_helper<complex<Y>,static_rational<N,D> >
  236. {
  237. typedef complex<
  238. typename power_typeof_helper<Y,static_rational<N,D> >::type
  239. > type;
  240. static type value(const complex<Y>& x)
  241. {
  242. const static_rational<N,D> rat;
  243. const Y m = Y(rat.numerator())/Y(rat.denominator());
  244. return boost::units::pow(x,m);
  245. }
  246. };
  247. /// specialize root typeof helper for complex<Y>
  248. template<class Y,long N,long D>
  249. struct root_typeof_helper<complex<Y>,static_rational<N,D> >
  250. {
  251. typedef complex<
  252. typename root_typeof_helper<Y,static_rational<N,D> >::type
  253. > type;
  254. static type value(const complex<Y>& x)
  255. {
  256. const static_rational<N,D> rat;
  257. const Y m = Y(rat.denominator())/Y(rat.numerator());
  258. return boost::units::pow(x,m);
  259. }
  260. };
  261. /// specialize power typeof helper for complex<quantity<Unit,Y> >
  262. template<class Y,class Unit,long N,long D>
  263. struct power_typeof_helper<complex<quantity<Unit,Y> >,static_rational<N,D> >
  264. {
  265. typedef typename
  266. power_typeof_helper<Y,static_rational<N,D> >::type value_type;
  267. typedef typename
  268. power_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
  269. typedef quantity<unit_type,value_type> quantity_type;
  270. typedef complex<quantity_type> type;
  271. static type value(const complex<quantity<Unit,Y> >& x)
  272. {
  273. const complex<value_type> tmp =
  274. pow<static_rational<N,D> >(complex<Y>(x.real().value(),
  275. x.imag().value()));
  276. return type(quantity_type::from_value(tmp.real()),
  277. quantity_type::from_value(tmp.imag()));
  278. }
  279. };
  280. /// specialize root typeof helper for complex<quantity<Unit,Y> >
  281. template<class Y,class Unit,long N,long D>
  282. struct root_typeof_helper<complex<quantity<Unit,Y> >,static_rational<N,D> >
  283. {
  284. typedef typename
  285. root_typeof_helper<Y,static_rational<N,D> >::type value_type;
  286. typedef typename
  287. root_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
  288. typedef quantity<unit_type,value_type> quantity_type;
  289. typedef complex<quantity_type> type;
  290. static type value(const complex<quantity<Unit,Y> >& x)
  291. {
  292. const complex<value_type> tmp =
  293. root<static_rational<N,D> >(complex<Y>(x.real().value(),
  294. x.imag().value()));
  295. return type(quantity_type::from_value(tmp.real()),
  296. quantity_type::from_value(tmp.imag()));
  297. }
  298. };
  299. } // namespace units
  300. } // namespace boost
  301. //]
  302. int main(void)
  303. {
  304. using namespace boost::units;
  305. using namespace boost::units::test;
  306. {
  307. //[complex_snippet_1
  308. typedef quantity<length,complex<double> > length_dimension;
  309. const length_dimension L(complex<double>(2.0,1.0)*meters);
  310. //]
  311. std::cout << "+L = " << +L << std::endl
  312. << "-L = " << -L << std::endl
  313. << "L+L = " << L+L << std::endl
  314. << "L-L = " << L-L << std::endl
  315. << "L*L = " << L*L << std::endl
  316. << "L/L = " << L/L << std::endl
  317. << "L^3 = " << pow<3>(L) << std::endl
  318. << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl
  319. << "3vL = " << root<3>(L) << std::endl
  320. << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl
  321. << std::endl;
  322. }
  323. {
  324. //[complex_snippet_2
  325. typedef complex<quantity<length> > length_dimension;
  326. const length_dimension L(2.0*meters,1.0*meters);
  327. //]
  328. std::cout << "+L = " << +L << std::endl
  329. << "-L = " << -L << std::endl
  330. << "L+L = " << L+L << std::endl
  331. << "L-L = " << L-L << std::endl
  332. << "L*L = " << L*L << std::endl
  333. << "L/L = " << L/L << std::endl
  334. << "L^3 = " << pow<3>(L) << std::endl
  335. << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl
  336. << "3vL = " << root<3>(L) << std::endl
  337. << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl
  338. << std::endl;
  339. }
  340. return 0;
  341. }