diff --git a/sprout/complex.hpp b/sprout/complex.hpp new file mode 100644 index 00000000..26df2016 --- /dev/null +++ b/sprout/complex.hpp @@ -0,0 +1,593 @@ +#ifndef SPROUT_COMPLEX_HPP +#define SPROUT_COMPLEX_HPP + +#include +#include + +namespace sprout { + namespace detail { + template + SPROUT_CONSTEXPR T pi_div_two() { + return 1.5707963267948966192313216916397514L; + } + } // namespace detail + template + class complex; + template + SPROUT_CONSTEXPR T norm(sprout::complex const& x); + // + // complex + // + template + class complex { + public: + typedef T value_type; + private: + T re_; + T im_; + public: + SPROUT_CONSTEXPR complex(T const& re = T(), T const& im = T()) + : re_(re) + , im_(im) + {} + SPROUT_CONSTEXPR complex(complex const&) = default; + template + SPROUT_CONSTEXPR complex(complex const& other) + : re_(other.real()) + , im_(other.imag()) + {} + SPROUT_CONSTEXPR T real() const { + return re_; + } + void real(T re) { + re_ = re; + } + SPROUT_CONSTEXPR T imag() const{ + return im_; + } + void imag(T im) { + im_ = im; + } + complex& operator=(T const& rhs) { + re_ = rhs; + im_ = T(); + return *this; + } + complex& operator+=(T const& rhs) { + re_ += rhs; + return *this; + } + complex& operator-=(T const& rhs) { + re_ -= rhs; + return *this; + } + complex& operator*=(T const& rhs) { + re_ *= rhs; + im_ *= rhs; + return *this; + } + complex& operator/=(T const& rhs) { + re_ /= rhs; + im_ /= rhs; + return *this; + } + complex& operator=(complex const&) = default; + template + complex& operator=(complex const& rhs) { + re_ = rhs.real(); + im_ = rhs.imag(); + return *this; + } + template + complex& operator+=(complex const& rhs) { + re_ += rhs.real(); + im_ += rhs.imag(); + return *this; + } + template + complex& operator-=(complex const& rhs) { + re_ -= rhs.real(); + im_ -= rhs.imag(); + return *this; + } + template + complex& operator*=(complex const& rhs) { + return *this = complex( + re_ * rhs.real() - im_ * rhs.imag(), + re_ * rhs.imag() + im_ * rhs.imag() + ); + } + template + complex& operator/=(complex const& rhs) { + T n = sprout::norm(rhs); + return *this = complex( + (re_ * rhs.real() + im_ * rhs.imag()) / n, + (im_ * rhs.real() - re_ * rhs.imag()) / n + ); + } + }; + // 26.4.6, operators: + template + 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 + SPROUT_CONSTEXPR sprout::complex operator+(sprout::complex const& lhs, T const& rhs) { + return sprout::complex( + lhs.real() + rhs, + lhs.imag() + ); + } + template + SPROUT_CONSTEXPR sprout::complex operator+(T const& lhs, sprout::complex const& rhs) { + return sprout::complex( + lhs + rhs.real(), + rhs.imag() + ); + } + template + 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 + SPROUT_CONSTEXPR sprout::complex operator-(sprout::complex const& lhs, T const& rhs) { + return sprout::complex( + lhs.real() - rhs, + lhs.imag() + ); + } + template + SPROUT_CONSTEXPR sprout::complex operator-(T const& lhs, sprout::complex const& rhs) { + return sprout::complex( + lhs - rhs.real(), + -rhs.imag() + ); + } + template + 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.imag() + ); + } + template + SPROUT_CONSTEXPR sprout::complex operator*(sprout::complex const& lhs, T const& rhs) { + return sprout::complex( + lhs.real() * rhs, + lhs.imag() * rhs + ); + } + template + SPROUT_CONSTEXPR sprout::complex operator*(T const& lhs, sprout::complex const& rhs) { + return sprout::complex( + lhs * rhs.real(), + lhs * rhs.imag() + ); + } + namespace detail { + template + 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 + 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 + SPROUT_CONSTEXPR sprout::complex operator/(sprout::complex const& lhs, sprout::complex const& rhs) { + return sprout::detail::divides_impl(lhs, rhs, sprout::norm(rhs)); + } + template + SPROUT_CONSTEXPR sprout::complex operator/(sprout::complex const& lhs, T const& rhs) { + return sprout::complex( + lhs.real() / rhs, + lhs.imag() / rhs + ); + } + template + SPROUT_CONSTEXPR sprout::complex operator/(T const& lhs, sprout::complex const& rhs) { + return sprout::detail::divides_impl(lhs, rhs, sprout::norm(rhs)); + } + template + SPROUT_CONSTEXPR sprout::complex operator+(sprout::complex const& x) { + return x; + } + template + SPROUT_CONSTEXPR sprout::complex operator-(sprout::complex const& x) { + return sprout::complex(-x.real(), -x.imag()); + } + template + SPROUT_CONSTEXPR bool operator==(sprout::complex const& lhs, sprout::complex const& rhs) { + return lhs.real() == rhs.real() && lhs.imag() == rhs.imag(); + } + template + SPROUT_CONSTEXPR bool operator==(sprout::complex const& lhs, T const& rhs) { + return lhs.real() == rhs && lhs.imag() == T(); + } + template + SPROUT_CONSTEXPR bool operator==(T const& lhs, sprout::complex const& rhs) { + return lhs == rhs.real() && T() == rhs.imag(); + } + template + SPROUT_CONSTEXPR bool operator!=(sprout::complex const& lhs, sprout::complex const& rhs) { + return !(lhs == rhs); + } + template + SPROUT_CONSTEXPR bool operator!=(sprout::complex const& lhs, T const& rhs) { + return !(lhs == rhs); + } + template + 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() << ')'; + } + // 26.4.7, values: + template + SPROUT_CONSTEXPR T real(sprout::complex const& x) { + return x.real(); + } + template + SPROUT_CONSTEXPR T imag(sprout::complex const& x) { + return x.imag(); + } + template + SPROUT_CONSTEXPR T abs(sprout::complex const& x) { + using std::sqrt; + return sqrt(sprout::norm(x)); + } + template + SPROUT_CONSTEXPR T arg(sprout::complex const& x) { + using std::atan2; + return atan2(x.imag(), x.real()); + } + template + SPROUT_CONSTEXPR T norm(sprout::complex const& x) { + return x.real() * x.real() + x.imag() * x.imag(); + } + template + SPROUT_CONSTEXPR sprout::complex conj(sprout::complex const& x) { + return sprout::complex(x.real(), -x.imag()); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex proj_impl(sprout::complex const& x, T const& den) { + return sprout::complex( + T(2) * x.real() / den, + T(2) * x.imag() / den + ); + } + } // detail + template + SPROUT_CONSTEXPR sprout::complex proj(sprout::complex const& x) { + return sprout::detail::proj_impl( + x, + sprout::norm(x) + T(1) + ); + } + template + SPROUT_CONSTEXPR sprout::complex polar(T const& rho, T const& theta = 0) { + using std::cos; + using std::sin; + return sprout::complex(rho * cos(theta), rho * sin(theta)); + } + // 26.4.8, transcendentals: + template + SPROUT_CONSTEXPR sprout::complex acos(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex asin(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex atan(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex acosh(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex asinh(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex atanh(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex cos(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex cosh(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex exp(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex log(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex log10(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, T const& y); + template + SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, sprout::complex const& y); + template + SPROUT_CONSTEXPR sprout::complex pow(T const& x, sprout::complex const& y); + template + SPROUT_CONSTEXPR sprout::complex sin(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex sinh(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex sqrt(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex tan(sprout::complex const& x); + template + SPROUT_CONSTEXPR sprout::complex tanh(sprout::complex const& x); + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex acos_impl(sprout::complex const& t) { + return sprout::complex(sprout::detail::pi_div_two() - t.real(), -t.imag()); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex acos(sprout::complex const& x) { + return sprout::detail::acos_impl(sprout::asin(x)); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex asin_impl(sprout::complex const& t) { + return sprout::complex(t.imag(), -t.real()); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex asin(sprout::complex const& x) { + return sprout::detail::asin_impl(sprout::asinh(sprout::complex(-x.imag(), x.real()))); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex atan_impl_1( + sprout::complex const& x, + T const& r2, + T const& z, + T const& num, + T const& den + ) + { + using std::atan2; + using std::log; + return sprout::complex( + T(0.5) * atan2(T(2) * x.real(), z), + T(0.25) * log((r2 + num * num) / (r2 + den * den)) + ); + } + template + SPROUT_CONSTEXPR sprout::complex atan_impl( + sprout::complex const& x, + T const& r2 + ) + { + return sprout::detail::atan_impl_1( + x, + r2, + T(1) - r2 - x.imag() * x.imag(), + x.imag() + T(1), + x.imag() - T(1) + ); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex atan(sprout::complex const& x) { + return sprout::detail::atan_impl(x, x.real() * x.real()); + } + template + SPROUT_CONSTEXPR sprout::complex acosh(sprout::complex const& x) { + return T(2) * sprout::log(sprout::sqrt(T(0.5) * (x + T(1))) + sprout::sqrt(T(0.5) * (x - T(1)))); + } + template + SPROUT_CONSTEXPR sprout::complex asinh(sprout::complex const& x) { + return sprout::log( + sprout::sqrt( + sprout::complex( + (x.real() - x.imag()) * (x.real() + x.imag()) + T(1), + T(2) * x.real() * x.imag() + ) + ) + + x + ); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex atanh_impl_1( + sprout::complex const& x, + T const& i2, + T const& z, + T const& num, + T const& den + ) + { + using std::atan2; + using std::log; + return sprout::complex( + T(0.25) * (log(i2 + num * num) - log(i2 + den * den)), + T(0.5) * atan2(T(2) * x.imag(), z) + ); + } + template + SPROUT_CONSTEXPR sprout::complex atanh_impl( + sprout::complex const& x, + T const& i2 + ) + { + return sprout::detail::atanh_impl_1( + x, + i2, + T(1) - i2 - x.real() * x.real(), + T(1) + x.imag(), + T(1) - x.imag() + ); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex atanh(sprout::complex const& x) { + return sprout::detail::atanh_impl(x, x.imag() * x.imag()); + } + template + SPROUT_CONSTEXPR sprout::complex cos(sprout::complex const& x) { + using std::cos; + using std::sin; + using std::cosh; + using std::sinh; + return sprout::complex( + cos(x.real()) * cosh(x.imag()), + -(sin(x.real()) * sinh(x.imag())) + ); + } + template + SPROUT_CONSTEXPR sprout::complex cosh(sprout::complex const& x) { + using std::cos; + using std::sin; + using std::cosh; + using std::sinh; + return sprout::complex( + cosh(x.real()) * cos(x.imag()), + sinh(x.real()) * sin(x.imag()) + ); + } + template + SPROUT_CONSTEXPR sprout::complex exp(sprout::complex const& x) { + using std::exp; + return sprout::polar(exp(x.real()), x.imag()); + } + template + SPROUT_CONSTEXPR sprout::complex log(sprout::complex const& x) { + return sprout::complex(sprout::log(sprout::abs(x)), sprout::arg(x)); + } + template + SPROUT_CONSTEXPR sprout::complex log10(sprout::complex const& x) { + using std::log; + return sprout::log(x) / log(T(10)); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex pow_impl(sprout::complex const& t, T const& y) { + using std::exp; + return sprout::polar(exp(y * t.real()), y * t.imag()); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, T const& y) { + using std::pow; + return x == T() ? T() + : x.imag() == T() && x.real() > T() ? pow(x.real(), y) + : sprout::detail::pow_impl(sprout::log(x), y) + ; + } + template + SPROUT_CONSTEXPR sprout::complex pow(sprout::complex const& x, sprout::complex const& y) { + return x == T() ? T() + : sprout::exp(y * sprout::log(x)) + ; + } + template + SPROUT_CONSTEXPR sprout::complex pow(T const& x, sprout::complex const& y) { + using std::log; + return x > T() ? sprout::polar(sprout::pow(x, y.real()), y.imag() * log(x)) + : sprout::pow(sprout::complex(x), y) + ; + } + template + SPROUT_CONSTEXPR sprout::complex sin(sprout::complex const& x) { + using std::cos; + using std::sin; + using std::cosh; + using std::sinh; + return sprout::complex( + sin(x.real()) * cosh(x.imag()), + cos(x.real()) * sinh(x.imag()) + ); + } + template + SPROUT_CONSTEXPR sprout::complex sinh(sprout::complex const& x) { + using std::cos; + using std::sin; + using std::cosh; + using std::sinh; + return sprout::complex( + sinh(x.real()) * cos(x.imag()), + cosh(x.real()) * sin(x.imag()) + ); + } + namespace detail { + template + SPROUT_CONSTEXPR sprout::complex sqrt_impl_1(sprout::complex const& x, T const& t) { + return sprout::complex(t, x.imag() < T() ? -t : t); + } + template + SPROUT_CONSTEXPR sprout::complex sqrt_impl_2_1(sprout::complex const& x, T const& t, T const& u) { + using std::abs; + return x.real() > T() ? sprout::complex(u, x.imag() / t) + : sprout::complex(abs(x.imag()) / t, x.imag() < T() ? -u : u) + ; + } + template + SPROUT_CONSTEXPR sprout::complex sqrt_impl_2(sprout::complex const& x, T const& t) { + return sqrt_impl_2(x, t, t / 2); + } + } // namespace detail + template + SPROUT_CONSTEXPR sprout::complex sqrt(sprout::complex const& x) { + using std::sqrt; + using std::abs; + return x.real() == T() ? sprout::detail::sqrt_impl_1(x, sqrt(abs(x.imag()) / 2)) + : sprout::detail::sqrt_impl_2(x, sqrt(2 * (sprout::abs(x) + abs(x.real())))) + ; + } + template + SPROUT_CONSTEXPR sprout::complex tan(sprout::complex const& x) { + return sprout::sin(x) / sprout::cos(x); + } + template + SPROUT_CONSTEXPR sprout::complex tanh(sprout::complex const& x) { + return sprout::sinh(x) / sprout::cosh(x); + } +} // namespace sprout + +#endif // #ifndef SPROUT_COMPLEX_HPP diff --git a/sprout/string.hpp b/sprout/string.hpp index e3f09f90..061fa3f5 100644 --- a/sprout/string.hpp +++ b/sprout/string.hpp @@ -901,7 +901,27 @@ namespace sprout { sprout::make_array::type>( sprout::forward(t), sprout::forward(args)..., - T() + typename std::decay::type() + ), + typename sprout::index_range<0, 1 + sizeof...(Types)>::type() + ); + } + + // + // make_string_as + // + template + SPROUT_CONSTEXPR inline sprout::basic_string::type, 0> + make_string_as() { + return sprout::basic_string::type, 0>{}; + } + template + SPROUT_CONSTEXPR inline sprout::basic_string::type, sizeof...(Types)> + make_string_as(Types&&... args) { + return sprout::detail::make_string_impl( + sprout::make_array::type>( + sprout::forward(args)..., + typename std::decay::type() ), typename sprout::index_range<0, 1 + sizeof...(Types)>::type() ); diff --git a/sprout/type.hpp b/sprout/type.hpp index 34e2206a..ed428b39 100644 --- a/sprout/type.hpp +++ b/sprout/type.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/sprout/type/boost/mpl/string.hpp b/sprout/type/boost/mpl/string.hpp index 977c87be..6a7b5cfc 100644 --- a/sprout/type/boost/mpl/string.hpp +++ b/sprout/type/boost/mpl/string.hpp @@ -6,9 +6,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include namespace sprout { namespace types { @@ -49,6 +53,7 @@ namespace sprout { struct next > : public boost::mpl::next > {}; + // // prev // @@ -56,6 +61,22 @@ namespace sprout { struct prev > : public boost::mpl::prior > {}; + + // + // push_back + // + template + struct push_back, T> + : public boost::mpl::push_back, T> + {}; + + // + // push_front + // + template + struct push_front, T> + : public boost::mpl::push_back, T> + {}; } // namespace types } // namespace sprout diff --git a/sprout/type/string/to_string.hpp b/sprout/type/string/to_string.hpp index 85d961ef..f6949d11 100644 --- a/sprout/type/string/to_string.hpp +++ b/sprout/type/string/to_string.hpp @@ -18,10 +18,10 @@ namespace sprout { // // to_string // - template + template struct to_string { private: - typedef decltype(StringClass()()) string_type; + typedef decltype(Proxy()()) string_type; typedef sprout::fixed_container_traits traits_type; private: template @@ -31,12 +31,12 @@ namespace sprout { public: typedef sprout::types::basic_string< typename traits_type::value_type, - (*sprout::next(sprout::begin(StringClass()()), Indexes))... + (*sprout::next(sprout::begin(Proxy()()), Indexes))... > type; }; public: typedef typename impl< - typename sprout::index_range<0, sprout::size(StringClass()())>::type + typename sprout::index_range<0, sprout::size(Proxy()())>::type >::type type; }; namespace detail { @@ -63,7 +63,7 @@ namespace sprout { // SPROUT_TYPES_STRING_TYPEDEF // # define SPROUT_TYPES_STRING_TYPEDEF(SOURCE, TYPE) \ - struct SPROUT_PP_CAT(SPROUT_TYPES_STRING_TYPEDEF_IMPL_, __LINE__) { \ + struct SPROUT_PP_CAT(SPROUT_TYPES_STRING_TYPEDEF_PROXY_, __LINE__) { \ private: \ typedef typename std::remove_reference::type src_type; \ typedef sprout::types::detail::string_typedef_impl::value> impl_type; \ @@ -74,7 +74,7 @@ namespace sprout { return impl_type()(SOURCE); \ } \ }; \ - typedef typename sprout::types::to_string::type TYPE + typedef typename sprout::types::to_string::type TYPE } // namespace types } // namespace sprout diff --git a/sprout/type/string/to_string_constant.hpp b/sprout/type/string/to_string_constant.hpp index ccbf3fca..b9961287 100644 --- a/sprout/type/string/to_string_constant.hpp +++ b/sprout/type/string/to_string_constant.hpp @@ -42,14 +42,9 @@ namespace sprout { typename Sequence::value_type, sprout::types::detail::str_length::value > to_string_constant_impl(sprout::index_tuple) { - typedef sprout::basic_string< - typename Sequence::value_type, - sprout::types::detail::str_length::value - > type; - return type{ - {sprout::types::tuple_element::type::value...}, - sprout::types::detail::str_length::value - }; + return sprout::make_string_as( + sprout::types::tuple_element::type::value... + ); } } // namespace detail template diff --git a/sprout/weed.hpp b/sprout/weed.hpp index a8fe356e..a0e185cf 100644 --- a/sprout/weed.hpp +++ b/sprout/weed.hpp @@ -1,6 +1,7 @@ #ifndef SPROUT_WEED_HPP #define SPROUT_WEED_HPP +#include #include #include #include