#ifndef SPROUT_COMPLEX_OPERATORS_HPP #define SPROUT_COMPLEX_OPERATORS_HPP #include #include #include #include namespace sprout { // 26.4.6, operators: template inline SPROUT_CONSTEXPR sprout::complex operator+(sprout::complex const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs.real() + rhs.real(), lhs.imag() + rhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator+(sprout::complex const& lhs, T const& rhs) { return sprout::complex( lhs.real() + rhs, lhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator+(T const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs + rhs.real(), rhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator-(sprout::complex const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs.real() - rhs.real(), lhs.imag() - rhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator-(sprout::complex const& lhs, T const& rhs) { return sprout::complex( lhs.real() - rhs, lhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator-(T const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs - rhs.real(), -rhs.imag() ); } template inline SPROUT_CONSTEXPR sprout::complex operator*(sprout::complex const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs.real() * rhs.real() - lhs.imag() * rhs.imag(), lhs.real() * rhs.imag() + lhs.imag() * rhs.real() ); } template inline SPROUT_CONSTEXPR sprout::complex operator*(sprout::complex const& lhs, T const& rhs) { return sprout::complex( lhs.real() * rhs, lhs.imag() * rhs ); } template inline SPROUT_CONSTEXPR sprout::complex operator*(T const& lhs, sprout::complex const& rhs) { return sprout::complex( lhs * rhs.real(), lhs * rhs.imag() ); } namespace detail { template inline SPROUT_CONSTEXPR sprout::complex divides_impl( sprout::complex const& lhs, sprout::complex const& rhs, T const& n ) { return sprout::complex( (lhs.real() * rhs.real() + lhs.imag() * rhs.imag()) / n, (lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / n ); } template inline SPROUT_CONSTEXPR sprout::complex divides_impl( T const& lhs, sprout::complex const& rhs, T const& n ) { return sprout::complex( lhs * rhs.real() / n, -lhs * rhs.imag() / n ); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::complex operator/(sprout::complex const& lhs, sprout::complex const& rhs) { return sprout::detail::divides_impl(lhs, rhs, sprout::detail::complex_norm(rhs)); } template inline SPROUT_CONSTEXPR sprout::complex operator/(sprout::complex const& lhs, T const& rhs) { return sprout::complex( lhs.real() / rhs, lhs.imag() / rhs ); } template inline SPROUT_CONSTEXPR sprout::complex operator/(T const& lhs, sprout::complex const& rhs) { return sprout::detail::divides_impl(lhs, rhs, sprout::detail::complex_norm(rhs)); } template inline SPROUT_CONSTEXPR sprout::complex operator+(sprout::complex const& x) { return x; } template inline SPROUT_CONSTEXPR sprout::complex operator-(sprout::complex const& x) { return sprout::complex(-x.real(), -x.imag()); } template inline SPROUT_CONSTEXPR bool operator==(sprout::complex const& lhs, sprout::complex const& rhs) { return lhs.real() == rhs.real() && lhs.imag() == rhs.imag(); } template inline SPROUT_CONSTEXPR bool operator==(sprout::complex const& lhs, T const& rhs) { return lhs.real() == rhs && lhs.imag() == T(); } template inline SPROUT_CONSTEXPR bool operator==(T const& lhs, sprout::complex const& rhs) { return lhs == rhs.real() && T() == rhs.imag(); } template inline SPROUT_CONSTEXPR bool operator!=(sprout::complex const& lhs, sprout::complex const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR bool operator!=(sprout::complex const& lhs, T const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR bool operator!=(T const& lhs, sprout::complex const& rhs) { return !(lhs == rhs); } template std::basic_istream& operator>>(std::basic_istream& lhs, sprout::complex& rhs) { T re, im; Char ch; lhs >> ch; if (ch == '(') { lhs >> re >> ch; if (ch == ',') { lhs >> im >> ch; if (ch == ')') { rhs = sprout::complex(re, im); } else { lhs.setstate(std::ios_base::failbit); } } else if (ch == ')') { rhs = re; } else { lhs.setstate(std::ios_base::failbit); } } else { lhs.putback(ch); lhs >> re; rhs = re; } return lhs; } template std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::complex const& rhs) { return lhs << '(' << rhs.real() << ',' << rhs.imag() << ')'; } } // namespace sprout #endif // #ifndef SPROUT_COMPLEX_OPERATORS_HPP