diff --git a/poly.h b/poly.h index b5b5c30..b739e45 100644 --- a/poly.h +++ b/poly.h @@ -1,78 +1,32 @@ #ifndef POLY_H #define POLY_H -#endif #include #include +#include #include -#include - -#define DEBUG 1 - -#if DEBUG -#define DBG_PRINT(x) \ - if (!std::is_constant_evaluated()) { \ - std::cout << x << std::endl; \ - } -#else -#define DBG_PRINT(x) -#endif template concept PolyConvertible = (M <= N) && std::is_convertible_v; -// To be able to use the "poly" type name before its definition +// To be able to use the "poly" type name before its definition. template class poly; // For recursive deduction of the base type of poly<...>. -template -struct BaseType { +template struct BaseType { using type = T; }; -template -struct BaseType> { +template struct BaseType> { using type = typename BaseType::type; }; -template -using base_type = typename BaseType::type; +template using base_type = typename BaseType::type; template class poly { private: std::array coefs{}; - std::ostringstream oss(int var) const { - std::ostringstream res; - for (std::size_t i = 0; i < N; ++i) { - const T& a = this->coefs[i]; - if constexpr (requires { typename T::value_type; }) { - res << "(" << a.oss(var+1).str() << ")"; - } - else { - res << a; - } - if (i > 0) { - res << "*x" << var; - } - if (i > 1) { - res << "^" << i; - } - if (i < N-1) { - res << " + "; - } - } - return res; - } - public: - std::string to_string() const { - return this->oss(1).str(); - } - - friend std::ostream& operator<<(std::ostream& os, const poly& p) { - return os << "poly<" << typeid(T).name() << ", " << N << ">"; - } - constexpr poly() = default; template @@ -99,9 +53,10 @@ template class poly { } template - requires(sizeof...(Args) >= 2 && sizeof...(Args) <= N && (std::convertible_to && ...)) - constexpr poly(Args&&... args) : coefs{static_cast(std::forward(args))...} { - } + requires(sizeof...(Args) >= 2 && sizeof...(Args) <= N && + (std::convertible_to && ...)) + constexpr poly(Args&&... args) + : coefs{static_cast(std::forward(args))...} {} constexpr std::size_t size() const { return N; } @@ -212,7 +167,7 @@ template class poly { return result; } - // Multiplication of a poly object with a scalar + // Multiplication of a poly object with a scalar. template requires std::convertible_to constexpr auto operator*(const U& value) const { @@ -223,7 +178,7 @@ template class poly { return result; } - // Addition of a poly object with a scalar + // Addition of a poly object with a scalar. template requires std::convertible_to constexpr auto operator+(const U& value) const { @@ -232,7 +187,7 @@ template class poly { return result; } - // Subtraction of a poly object with a scalar + // Subtraction of a poly object with a scalar. template requires std::convertible_to constexpr auto operator-(const U& value) const { @@ -242,120 +197,101 @@ template class poly { } template - requires std::convertible_to - static constexpr std::common_type_t eval_term(const T& coef, const U& pow_base, std::size_t pow_exp) { - std::common_type_t res = coef; - for (std::size_t i = 1; i <= pow_exp; ++i) { - res *= pow_base; - } - return res; - } - - constexpr const poly& at() const { - return *this; + requires std::convertible_to + static constexpr U eval_term(const T& coef, const U& pow_base, + std::size_t pow_exp) { + U res = coef; + for (std::size_t i = 1; i <= pow_exp; ++i) { + res *= pow_base; + } + return res; } - template - requires std::convertible_to - constexpr std::common_type_t at(const U& arg) const { - if (N == 0) { - return T{}; - } - - std::common_type_t res = this->coefs[0]; - - for (std::size_t i = 1; i < N; ++i) { - std::common_type_t term = eval_term(this->coefs[i], arg, i); - res += term; - } - - return res; - } + constexpr const poly& at() const { return *this; } + + template + requires std::convertible_to + constexpr auto at(const U& arg) const { + using R = decltype(coefs[0] * arg); + if (N == 0) { + return R{}; + } + + R res = coefs[N - 1]; + for (std::size_t i = N - 1; i > 0; --i) { + res = res * arg + coefs[i - 1]; + } + + return res; + } + template - requires std::convertible_to, T> + requires std::convertible_to, T> constexpr auto at(const poly& arg) const { - constexpr std::size_t res_size = (N-1)*(M-1) + 1; + constexpr std::size_t res_size = (N - 1) * (M - 1) + 1; using res_type = poly, res_size>; - + if (N == 0) { - return res_type(); - } + return res_type(); + } res_type res(this->coefs[0]); - - for (std::size_t i = 1; i < N; ++i) { - res_type term(arg); - - for (std::size_t exp = 1; exp < i; ++exp) { - res_type temp_result{}; - for (std::size_t k = 0; k < term.size(); ++k) { - for (std::size_t j = 0; j < arg.size(); ++j) { - if (k + j < temp_result.size()) { - temp_result[k + j] += term[k] * arg[j]; - } - } - } - term = temp_result; - } - - for (std::size_t k = 0; k < term.size(); ++k) { - term[k] *= this->coefs[i]; - } - - res += term; - } - - return res; - } - - template - constexpr auto at(const U& first, Args&&... args) const - requires (std::convertible_to, T> && (std::convertible_to, T> && ...)) { - if (N <= 1) { - return this->at(first); - } - - using result_type = decltype(this->coefs[0].at(args...)); - result_type result = this->coefs[0].at(args...); - - for (std::size_t i = 1; i < N; ++i) { - result += this->coefs[i].at(args...) * pow(first, i); - } - - return result; - } - - template - static constexpr auto at_array(const P& p, const std::array& arr) { - return at_array_impl(p, arr, std::make_index_sequence{}); - } - template - static constexpr auto at_array_impl(const P& p, const std::array& arr, std::index_sequence) { - return p.at(arr[Is]...); + for (std::size_t i = N - 1; i > 0; --i) { + res = res * arg + res_type(this->coefs[i - 1]); + /*res_type term(arg); + + for (std::size_t exp = 1; exp < i; ++exp) { + res_type temp_result{}; + for (std::size_t k = 0; k < term.size(); ++k) { + for (std::size_t j = 0; j < arg.size(); ++j) { + if (k + j < temp_result.size()) { + temp_result[k + j] += term[k] * arg[j]; + } + } + } + term = temp_result; + } + + for (std::size_t k = 0; k < term.size(); ++k) { + term[k] *= this->coefs[i]; + } + + res += term;*/ + } + + return res; } - - template - constexpr auto at(const std::array& arr) const { - return at_array(*this, arr); + + template + constexpr auto at(const A& a, const Args&... rest) const { + using R = decltype(this->coefs[0].at(rest...) * a); + if (N == 0) { + return R{}; + } + R res = coefs[N-1].at(rest...); + for (std::size_t i = N - 1; i > 0; --i) { + res = res * a + this->coefs[i - 1].at(rest...); + } + return res; } }; -// Non-member operator* for scalar multiplication. +// Non-member operator* for scalar multiplication. template requires std::convertible_to constexpr auto operator*(const U& value, const poly& p) { return p * value; } -// Non-member operator+ for scalar addition. +// Non-member operator+ for scalar addition. template requires std::convertible_to constexpr auto operator+(const U& value, const poly& p) { return p + value; } -// Non-member operator- for scalar subtraction. +// Non-member operator- for scalar subtraction. template requires std::convertible_to constexpr auto operator-(const U& value, const poly& p) { @@ -364,9 +300,9 @@ constexpr auto operator-(const U& value, const poly& p) { template constexpr auto const_poly(const poly& p) { - DBG_PRINT("const_poly constructor called"); return poly, 1>{p}; } + namespace detail { template struct is_poly_impl : std::false_type {}; @@ -374,11 +310,9 @@ template struct is_poly_impl : std::false_type {}; template struct is_poly_impl> : std::true_type {}; -template -struct is_poly : is_poly_impl> {}; +template struct is_poly : is_poly_impl> {}; -template -inline constexpr bool is_poly_v = is_poly::value; +template inline constexpr bool is_poly_v = is_poly::value; } // namespace detail // std::common_type specialization for poly. @@ -390,17 +324,16 @@ struct common_type, poly> { }; template - requires (!detail::is_poly_v) + requires(!detail::is_poly_v) struct common_type, U> { using type = poly, N>; }; template - requires (!detail::is_poly_v) + requires(!detail::is_poly_v) struct common_type> { using type = poly, M>; }; - } // namespace std template @@ -439,3 +372,5 @@ template constexpr auto cross(const T1& a, const T2& b) { return a * b; } + +#endif // POLY_H