#ifndef CORE_NUMERIC_HPP #define CORE_NUMERIC_HPP #include #include namespace core { inline namespace v2 { template auto iota (Range&& rng, T&& value) -> enable_if_t::value> { auto range = make_range(::std::forward(rng)); constexpr auto is_forward = decltype(range)::is_forward; static_assert(is_forward, "iota requires ForwardIterators"); return ::std::iota( ::std::begin(range), ::std::end(range), ::std::forward(value) ); } template auto accumulate (Range&& rng, T&& init) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "accumulate requires InputIterators"); return ::std::accumulate( ::std::begin(range), ::std::end(range), ::std::forward(init) ); } template auto accumulate (Range&& rng, T&& init, BinaryOp&& op) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "accumulate requires InputIterators"); return ::std::accumulate( ::std::begin(range), ::std::end(range), ::std::forward(init), ::std::forward(op) ); } template auto inner_product (Range&& rng, InputIt&& it, T&& value) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "inner_product requires InputIterators"); return ::std::inner_product( ::std::begin(range), ::std::end(range), ::std::forward(it), ::std::forward(value) ); } template auto inner_product ( Range&& rng, InputIt&& it, T&& value, BinaryOp&& op, BinaryOp2&& op2 ) -> enable_if_t::value, decay_t> { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "inner_product requires InputIterators"); return ::std::inner_product( ::std::begin(range), ::std::end(range), ::std::forward(it), ::std::forward(value), ::std::forward(op), ::std::forward(op2) ); } template auto adjacent_difference (Range&& rng, OutputIt&& it) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "adjacent_difference requires InputIterators"); return ::std::adjacent_difference( ::std::begin(range), ::std::end(range), ::std::forward(it) ); } template auto adjacent_difference ( Range&& rng, OutputIt&& it, BinaryOp&& op ) -> enable_if_t::value, decay_t> { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "adjacent_difference requires InputIterators"); return ::std::adjacent_difference( ::std::begin(range), ::std::end(range), ::std::forward(it), ::std::forward(op) ); } template auto partial_sum (Range&& rng, OutputIt&& it) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "partial_sum requires InputIterators"); return ::std::partial_sum( ::std::begin(range), ::std::end(range), ::std::forward(it) ); } template auto partial_sum (Range&& rng, OutputIt&& it, BinaryOp&& op) -> enable_if_t< is_range::value, decay_t > { auto range = make_range(::std::forward(rng)); constexpr auto is_input = decltype(range)::is_input; static_assert(is_input, "partial_sum requires InputIterators"); return ::std::partial_sum( ::std::begin(range), ::std::end(range), ::std::forward(it), ::std::forward(op) ); } /* Because they need to be constexpr, these are EXTREMELY ineffecient */ template constexpr auto gcd (M m, N n) -> meta::when< meta::all_of, ::std::is_integral>(), common_type_t > { return m % n ? gcd(m, m % n) : n; } template constexpr auto lcm (M m, N n) -> meta::when< meta::all_of, std::is_integral>(), common_type_t > { return m / gcd(m, n) * n; } }} /* namespace core::v2 */ #endif /* CORE_NUMERIC_HPP */