// Boost.Units - A C++ library for zero-overhead dimensional analysis and // unit/quantity manipulation and conversion // // Copyright (C) 2003-2008 Matthias Christian Schabel // Copyright (C) 2008 Steven Watanabe // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) /** \file \brief complex.cpp \detailed Demonstrate a complex number class that functions correctly with quantities. Output: @verbatim //[complex_output_1 +L = 2 + 1 i m -L = -2 + -1 i m L+L = 4 + 2 i m L-L = 0 + 0 i m L*L = 3 + 4 i m^2 L/L = 1 + 0 i dimensionless L^3 = 2 + 11 i m^3 L^(3/2) = 2.56713 + 2.14247 i m^(3/2) 3vL = 1.29207 + 0.201294 i m^(1/3) (3/2)vL = 1.62894 + 0.520175 i m^(2/3) //] //[complex_output_2 +L = 2 m + 1 m i -L = -2 m + -1 m i L+L = 4 m + 2 m i L-L = 0 m + 0 m i L*L = 3 m^2 + 4 m^2 i L/L = 1 dimensionless + 0 dimensionless i L^3 = 2 m^3 + 11 m^3 i L^(3/2) = 2.56713 m^(3/2) + 2.14247 m^(3/2) i 3vL = 1.29207 m^(1/3) + 0.201294 m^(1/3) i (3/2)vL = 1.62894 m^(2/3) + 0.520175 m^(2/3) i //] @endverbatim **/ #include #include #include #include #include #include #include #include "test_system.hpp" //[complex_class_snippet_1 namespace boost { namespace units { /// replacement complex class template class complex { public: typedef complex this_type; complex(const T& r = 0,const T& i = 0) : r_(r),i_(i) { } complex(const this_type& source) : r_(source.r_),i_(source.i_) { } this_type& operator=(const this_type& source) { if (this == &source) return *this; r_ = source.r_; i_ = source.i_; return *this; } T& real() { return r_; } T& imag() { return i_; } const T& real() const { return r_; } const T& imag() const { return i_; } this_type& operator+=(const T& val) { r_ += val; return *this; } this_type& operator-=(const T& val) { r_ -= val; return *this; } this_type& operator*=(const T& val) { r_ *= val; i_ *= val; return *this; } this_type& operator/=(const T& val) { r_ /= val; i_ /= val; return *this; } this_type& operator+=(const this_type& source) { r_ += source.r_; i_ += source.i_; return *this; } this_type& operator-=(const this_type& source) { r_ -= source.r_; i_ -= source.i_; return *this; } this_type& operator*=(const this_type& source) { *this = *this * source; return *this; } this_type& operator/=(const this_type& source) { *this = *this / source; return *this; } private: T r_,i_; }; } } #if BOOST_UNITS_HAS_BOOST_TYPEOF #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::complex, 1) #endif namespace boost { namespace units { template complex::type> operator+(const complex& x) { typedef typename unary_plus_typeof_helper::type type; return complex(x.real(),x.imag()); } template complex::type> operator-(const complex& x) { typedef typename unary_minus_typeof_helper::type type; return complex(-x.real(),-x.imag()); } template complex::type> operator+(const complex& x,const complex& y) { typedef typename boost::units::add_typeof_helper::type type; return complex(x.real()+y.real(),x.imag()+y.imag()); } template complex::type> operator-(const complex& x,const complex& y) { typedef typename boost::units::subtract_typeof_helper::type type; return complex(x.real()-y.real(),x.imag()-y.imag()); } template complex::type> operator*(const complex& x,const complex& y) { typedef typename boost::units::multiply_typeof_helper::type type; return complex(x.real()*y.real() - x.imag()*y.imag(), x.real()*y.imag() + x.imag()*y.real()); // fully correct implementation has more complex return type // // typedef typename boost::units::multiply_typeof_helper::type xy_type; // // typedef typename boost::units::add_typeof_helper< // xy_type,xy_type>::type xy_plus_xy_type; // typedef typename // boost::units::subtract_typeof_helper::type // xy_minus_xy_type; // // BOOST_STATIC_ASSERT((boost::is_same::value == true)); // // return complex(x.real()*y.real()-x.imag()*y.imag(), // x.real()*y.imag()+x.imag()*y.real()); } template complex::type> operator/(const complex& x,const complex& y) { // naive implementation of complex division typedef typename boost::units::divide_typeof_helper::type type; return complex((x.real()*y.real()+x.imag()*y.imag())/ (y.real()*y.real()+y.imag()*y.imag()), (x.imag()*y.real()-x.real()*y.imag())/ (y.real()*y.real()+y.imag()*y.imag())); // fully correct implementation has more complex return type // // typedef typename boost::units::multiply_typeof_helper::type xy_type; // typedef typename boost::units::multiply_typeof_helper::type yy_type; // // typedef typename boost::units::add_typeof_helper::type // xy_plus_xy_type; // typedef typename boost::units::subtract_typeof_helper< // xy_type,xy_type>::type xy_minus_xy_type; // // typedef typename boost::units::divide_typeof_helper< // xy_plus_xy_type,yy_type>::type xy_plus_xy_over_yy_type; // typedef typename boost::units::divide_typeof_helper< // xy_minus_xy_type,yy_type>::type xy_minus_xy_over_yy_type; // // BOOST_STATIC_ASSERT((boost::is_same::value == true)); // // return complex( // (x.real()*y.real()+x.imag()*y.imag())/ // (y.real()*y.real()+y.imag()*y.imag()), // (x.imag()*y.real()-x.real()*y.imag())/ // (y.real()*y.real()+y.imag()*y.imag())); } template complex pow(const complex& x,const Y& y) { std::complex tmp(x.real(),x.imag()); tmp = std::pow(tmp,y); return complex(tmp.real(),tmp.imag()); } template std::ostream& operator<<(std::ostream& os,const complex& val) { os << val.real() << " + " << val.imag() << " i"; return os; } /// specialize power typeof helper for complex template struct power_typeof_helper,static_rational > { typedef complex< typename power_typeof_helper >::type > type; static type value(const complex& x) { const static_rational rat; const Y m = Y(rat.numerator())/Y(rat.denominator()); return boost::units::pow(x,m); } }; /// specialize root typeof helper for complex template struct root_typeof_helper,static_rational > { typedef complex< typename root_typeof_helper >::type > type; static type value(const complex& x) { const static_rational rat; const Y m = Y(rat.denominator())/Y(rat.numerator()); return boost::units::pow(x,m); } }; /// specialize power typeof helper for complex > template struct power_typeof_helper >,static_rational > { typedef typename power_typeof_helper >::type value_type; typedef typename power_typeof_helper >::type unit_type; typedef quantity quantity_type; typedef complex type; static type value(const complex >& x) { const complex tmp = pow >(complex(x.real().value(), x.imag().value())); return type(quantity_type::from_value(tmp.real()), quantity_type::from_value(tmp.imag())); } }; /// specialize root typeof helper for complex > template struct root_typeof_helper >,static_rational > { typedef typename root_typeof_helper >::type value_type; typedef typename root_typeof_helper >::type unit_type; typedef quantity quantity_type; typedef complex type; static type value(const complex >& x) { const complex tmp = root >(complex(x.real().value(), x.imag().value())); return type(quantity_type::from_value(tmp.real()), quantity_type::from_value(tmp.imag())); } }; } // namespace units } // namespace boost //] int main(void) { using namespace boost::math; using namespace boost::units; using namespace boost::units::test; { //[complex_snippet_1 typedef quantity > length_dimension; length_dimension L(complex(2.0,1.0)*meters); //] std::cout << "+L = " << +L << std::endl << "-L = " << -L << std::endl << "L+L = " << L+L << std::endl << "L-L = " << L-L << std::endl << "L*L = " << L*L << std::endl << "L/L = " << L/L << std::endl << "L^3 = " << pow<3>(L) << std::endl << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl << "3vL = " << root<3>(L) << std::endl << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl << std::endl; } { //[complex_snippet_2 typedef complex > length_dimension; length_dimension L(2.0*meters,1.0*meters); //] std::cout << "+L = " << +L << std::endl << "-L = " << -L << std::endl << "L+L = " << L+L << std::endl << "L-L = " << L-L << std::endl << "L*L = " << L*L << std::endl << "L/L = " << L/L << std::endl << "L^3 = " << pow<3>(L) << std::endl << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl << "3vL = " << root<3>(L) << std::endl << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl << std::endl; } return 0; }