Assuming I have a 2 tuples of representing coefficients of two polynomials, how do I compute there multiplication coefficients. I want to accomplish this using template.
mul_scalar() multiplies value of tuple to a with the scalar.
I am trying to use this function to extend to polynomial case. By iterating over one tuple and using mul_scalar()
#include <tuple>
#include <utility>
#include <iostream>
template<std::size_t I = 0, typename T, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
mul_scalar(const T& lhs, const std::tuple<Tp...> rhs ) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename T, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
mul_scalar(const T& lhs, const std::tuple<Tp...> rhs)
{
std::cout << (std::get<I>(rhs))*lhs << " ";
mul_scalar<I + 1, T, Tp...>(lhs, rhs);
}
template <std::size_t I = 0, template <typename ...> class Tup1, template <typename ...> class Tup2, typename ...A, typename ...B>
inline typename std::enable_if<I < sizeof...(A), void>::type
mul_poly(const Tup1<A...>& lhs, const Tup2<B...> rhs)
{
mul_scalar(std::get<I>(lhs), rhs);
//mul_poly(lhs, rhs); with I = I + 1
// However I can't figure how to give other template args
}
int main(){
auto poly_1 = std::make_tuple(2,1);
auto poly_2 = std::make_tuple(3,4,5);
mul_scalar(3,poly_1);
std::cout << "\n";
// Expected output 6 8 10 3 4 5
mul_poly(poly_1, poly_2);
}
The recursive call is simple
mul_poly<I+1u>(lhs, rhs);
but you have to add the ground case
template <std::size_t I = 0, template <typename ...> class Tup1,
template <typename ...> class Tup2, typename ...A, typename ...B>
inline typename std::enable_if<I == sizeof...(A), void>::type
mul_poly (const Tup1<A...> &, const Tup2<B...> &)
{ }
would be great if you could tell me other approaches as well
Bonus suggestion: if you can use C++17, you can avoid SFINAE and recursion, for mul_scalar(), using std::index_sequence/std::make_index_sequence (or std::index_sequence_for) and template folding as follows
template <typename T, typename ... Tp, std::size_t ... Is>
void mul_scalar_helper (T const & lhs, std::tuple<Tp...> const & rhs,
std::index_sequence<Is...> const &)
{ ((std::cout << (std::get<Is>(rhs))*lhs << ' '), ...); }
template <typename T, typename ... Tp>
void mul_scalar (T const & lhs, std::tuple<Tp...> const & rhs)
{ mul_scalar_helper(lhs, rhs, std::index_sequence_for<Tp...>{}); }
For mul_poly() there isn't a great difference
template <template <typename ...> class Tup1,
template <typename ...> class Tup2,
typename ... A, typename ... B, std::size_t ... Is>
void mul_poly_helper (Tup1<A...> const & lhs, Tup2<B...> const & rhs,
std::index_sequence<Is...> const &)
{ (mul_scalar(std::get<Is>(lhs), rhs), ...); }
template <template <typename ...> class Tup1,
template <typename ...> class Tup2,
typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
{ mul_poly_helper(lhs, rhs, std::index_sequence_for<A...>{}); }
Anyway... are you sure that std::tuple is the right container? Have you considered std::array?
--- EDIT ---
Following the liliscent's suggestion (thanks!) you can avoid the helper functions and std::index_sequence/std::index_sequence_for using std::apply() simply writing
template <typename T, typename ... Tp>
void mul_scalar (T const & lhs, std::tuple<Tp...> const & rhs)
{ std::apply([&](auto const & ... x){ ((std::cout << x*lhs << ' '), ...); }, rhs); }
template <template <typename ...> class Tup1,
template <typename ...> class Tup2,
typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
{ std::apply([&](auto const & ... x){ (mul_scalar(x, rhs), ...); }, lhs); }
You can also write mul_poly() with a couple of std::apply(), without calling mul_scalar()
template <template <typename ...> class Tup1,
template <typename ...> class Tup2,
typename ...A, typename ...B>
void mul_poly (Tup1<A...> const & lhs, Tup2<B...> const & rhs)
{ std::apply([&](auto const & ... x){
(std::apply([x](auto const & ... y){ ((std::cout << x*y << ' '), ...); },
rhs), ...); }, lhs); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With