TrickmanOff

Untitled

Oct 4th, 2020
1,041
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.21 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <vector>
  4.  
  5. template <typename ValueType>
  6. class Polynomial {
  7. private:
  8.     std::vector<ValueType> coeffs;
  9.     ValueType ZERO;
  10.  
  11.     void delete_leading_zeros();
  12.  
  13. public:
  14.     explicit Polynomial(const std::vector<ValueType>&);
  15.     explicit Polynomial(const ValueType& = ValueType());
  16.     template <typename Iter>
  17.     Polynomial(Iter first, Iter last);
  18.  
  19.     int Degree() const;
  20.  
  21.     const ValueType& operator[](size_t index) const;
  22.     // ValueType& operator[](size_t index);
  23.  
  24.     ValueType operator()(const ValueType&) const;
  25.  
  26.     typename std::vector<ValueType>::const_iterator begin() const;
  27.     typename std::vector<ValueType>::const_iterator end() const;
  28.  
  29.     Polynomial<ValueType>& operator+=(const Polynomial<ValueType>&);
  30.     Polynomial<ValueType>& operator+=(const ValueType&);
  31.  
  32.     Polynomial<ValueType>& operator-=(const Polynomial<ValueType>&);
  33.     Polynomial<ValueType>& operator-=(const ValueType&);
  34.  
  35.     Polynomial<ValueType>& operator*=(const Polynomial<ValueType>&);
  36.     Polynomial<ValueType>& operator*=(const ValueType&);
  37.  
  38.     Polynomial<ValueType> operator-() const;
  39. };
  40.  
  41. template<typename ValueType>
  42. void Polynomial<ValueType>::delete_leading_zeros() {
  43.     while (!coeffs.empty() && coeffs.back() == ValueType(0)) {
  44.         coeffs.pop_back();
  45.     }
  46. }
  47.  
  48. template<typename ValueType>
  49. Polynomial<ValueType>::Polynomial(const std::vector<ValueType>& coeffs_vec):
  50.         coeffs(coeffs_vec.begin(), coeffs_vec.end()), ZERO(ValueType(0)) {
  51.     delete_leading_zeros();
  52. }
  53.  
  54. template<typename ValueType>
  55. Polynomial<ValueType>::Polynomial(const ValueType& coeff): coeffs{coeff}, ZERO(ValueType(0)) {
  56.     delete_leading_zeros();
  57. }
  58.  
  59. template<typename ValueType>
  60. template<typename Iter>
  61. Polynomial<ValueType>::Polynomial(Iter first, Iter last): coeffs(first, last), ZERO(ValueType(0)) {
  62.     delete_leading_zeros();
  63. }
  64.  
  65. template<typename ValueType>
  66. int Polynomial<ValueType>::Degree() const {
  67.     return static_cast<int>(coeffs.size()) - 1;
  68. }
  69.  
  70. template<typename ValueType>
  71. ValueType Polynomial<ValueType>::operator()(const ValueType& arg) const {
  72.     ValueType res(0);
  73.     ValueType cur_pow(1);
  74.  
  75.     for (int deg = 0; deg <= this->Degree(); ++deg) {
  76.         res += coeffs[deg] * cur_pow;
  77.         cur_pow *= arg;
  78.     }
  79.     return res;
  80. }
  81.  
  82. template<typename ValueType>
  83. const ValueType& Polynomial<ValueType>::operator[](size_t index) const {
  84.     if (static_cast<int>(index) > Degree()) {
  85.         return ZERO;
  86.     } else {
  87.         return coeffs[index];
  88.     }
  89. }
  90.  
  91. template<typename ValueType>
  92. typename std::vector<ValueType>::const_iterator Polynomial<ValueType>::begin() const {
  93.     return coeffs.begin();
  94. }
  95.  
  96. template<typename ValueType>
  97. typename std::vector<ValueType>::const_iterator Polynomial<ValueType>::end() const {
  98.     return coeffs.end();
  99. }
  100.  
  101. template<typename ValueType>
  102. Polynomial<ValueType> &Polynomial<ValueType>::operator+=(const Polynomial<ValueType>& add) {
  103.     return (*this = *this + add);
  104. }
  105.  
  106. template<typename ValueType>
  107. Polynomial<ValueType> &Polynomial<ValueType>::operator+=(const ValueType& add) {
  108.     return (*this = *this + add);
  109. }
  110.  
  111. template<typename ValueType>
  112. Polynomial<ValueType> &Polynomial<ValueType>::operator-=(const Polynomial<ValueType>& add) {
  113.     return (*this = *this - add);
  114. }
  115.  
  116. template<typename ValueType>
  117. Polynomial<ValueType> &Polynomial<ValueType>::operator-=(const ValueType& add) {
  118.     return (*this = *this - add);
  119. }
  120.  
  121. template<typename ValueType>
  122. Polynomial<ValueType>& Polynomial<ValueType>::operator*=(const Polynomial<ValueType>& rhs) {
  123.     return (*this = *this * rhs);
  124. }
  125.  
  126. template<typename ValueType>
  127. Polynomial<ValueType>& Polynomial<ValueType>::operator*=(const ValueType& rhs) {
  128.     return (*this = *this * rhs);
  129. }
  130.  
  131. template<typename ValueType>
  132. Polynomial<ValueType> Polynomial<ValueType>::operator-() const {
  133.     std::vector<ValueType> res(coeffs);
  134.     for (auto& coeff : res) {
  135.         coeff = -coeff;
  136.     }
  137.     return Polynomial(res);
  138. }
  139.  
  140. template<typename ValueType>
  141. Polynomial<ValueType> operator+(const Polynomial<ValueType>& lhs,
  142.         const Polynomial<ValueType>& rhs) {
  143.     std::vector<ValueType> res;
  144.     for (int deg = 0; deg <= std::max(lhs.Degree(), rhs.Degree()); ++deg) {
  145.         res.push_back(lhs[deg] + rhs[deg]);
  146.     }
  147.     return Polynomial(res);
  148. }
  149.  
  150. template<typename ValueType>
  151. Polynomial<ValueType> operator+(const Polynomial<ValueType>& lhs, const ValueType& rhs) {
  152.     if (lhs.Degree() == -1) {
  153.         return Polynomial(ValueType(0) + rhs);
  154.     }
  155.     std::vector<ValueType> res(lhs.begin(), lhs.end());
  156.     res[0] += rhs;
  157.     return Polynomial(res);
  158. }
  159.  
  160. template<typename ValueType>
  161. Polynomial<ValueType> operator+(const ValueType& lhs, const Polynomial<ValueType>& rhs) {
  162.     return rhs + lhs;
  163. }
  164.  
  165. template<typename ValueType>
  166. Polynomial<ValueType> operator-(const Polynomial<ValueType>& lhs,
  167.         const Polynomial<ValueType>& rhs) {
  168.     return lhs + (-rhs);
  169. }
  170.  
  171. template<typename ValueType>
  172. Polynomial<ValueType> operator-(const Polynomial<ValueType>& lhs, const ValueType& rhs) {
  173.     return lhs + (-rhs);
  174. }
  175.  
  176. template<typename ValueType>
  177. Polynomial<ValueType> operator-(const ValueType& lhs, const Polynomial<ValueType>& rhs) {
  178.     return lhs + (-rhs);
  179. }
  180.  
  181. template<typename ValueType>
  182. Polynomial<ValueType> operator*(const Polynomial<ValueType>& lhs,
  183.         const Polynomial<ValueType>& rhs) {
  184.     const int LDEG = lhs.Degree(), RDEG = rhs.Degree();
  185.     if (LDEG == -1 || RDEG == -1) {
  186.         return (LDEG == -1 ? lhs : rhs);
  187.     }
  188.  
  189.     std::vector<ValueType> res(LDEG + RDEG + 1, ValueType(0));
  190.  
  191.     for (int ldeg = 0; ldeg <= LDEG; ++ldeg) {
  192.         for (int rdeg = 0; rdeg <= RDEG; ++rdeg) {
  193.             res[ldeg + rdeg] += lhs[ldeg] * rhs[rdeg];
  194.         }
  195.     }
  196.     return Polynomial(res);
  197. }
  198.  
  199. template<typename ValueType>
  200. Polynomial<ValueType> operator*(const Polynomial<ValueType>& lhs, const ValueType& rhs) {
  201.     std::vector<ValueType> res(lhs.begin(), lhs.end());
  202.     for (auto& coeff : res) {
  203.         coeff *= rhs;
  204.     }
  205.     return Polynomial(res);
  206. }
  207.  
  208. template<typename ValueType>
  209. Polynomial<ValueType> operator*(const ValueType& lhs, const Polynomial<ValueType>& rhs) {
  210.     return rhs * lhs;
  211. }
  212.  
  213. template<typename ValueType>
  214. bool operator==(const Polynomial<ValueType>& lhs, const Polynomial<ValueType>& rhs) {
  215.     return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  216. }
  217.  
  218. template<typename ValueType>
  219. bool operator==(const Polynomial<ValueType>& lhs, const ValueType& rhs) {
  220.     return (lhs.Degree() <= 0) && (lhs[0] == rhs);
  221. }
  222.  
  223. template<typename ValueType>
  224. bool operator==(const ValueType& lhs, const Polynomial<ValueType>& rhs) {
  225.     return (rhs == lhs);
  226. }
  227.  
  228. template<typename ValueType>
  229. bool operator!=(const Polynomial<ValueType>& lhs, const Polynomial<ValueType>& rhs) {
  230.     return !(lhs == rhs);
  231. }
  232.  
  233. template<typename ValueType>
  234. bool operator!=(const Polynomial<ValueType>& lhs, const ValueType& rhs) {
  235.     return !(lhs == rhs);
  236. }
  237.  
  238. template<typename ValueType>
  239. bool operator!=(const ValueType& lhs, const Polynomial<ValueType>& rhs) {
  240.     return !(lhs == rhs);
  241. }
  242.  
  243. template<typename ValueType>
  244. ValueType abs(const ValueType& num) {
  245.     if (num > ValueType(0)) {
  246.         return num;
  247.     } else {
  248.         return -num;
  249.     }
  250. }
  251.  
  252. template<typename ValueType>
  253. std::ostream& operator<<(std::ostream& out, const Polynomial<ValueType>& poly) {
  254.     if (poly.Degree() == -1) {
  255.         out << ValueType(0);
  256.     } else {
  257.         for (int deg = poly.Degree(); deg >= 0; --deg) {
  258.             if (poly[deg] == ValueType(0)) {
  259.                 continue;
  260.             }
  261.  
  262.             ValueType abs_coeff = abs(poly[deg]);
  263.  
  264.             if (abs_coeff == poly[deg]) {  // +
  265.                 if (deg != poly.Degree()) {
  266.                     out << '+';
  267.                 }
  268.             } else {  // -
  269.                 out << '-';
  270.             }
  271.  
  272.             if (deg == 0 || abs_coeff != ValueType(1)) {
  273.                 out << abs_coeff;
  274.                 if (deg != 0) {
  275.                     out << '*';
  276.                 }
  277.             }
  278.  
  279.             if (deg != 0) {
  280.                 out << 'x';
  281.                 if (deg > 1) {
  282.                     out << '^' << deg;
  283.                 }
  284.             }
  285.         }
  286.     }
  287.     return out;
  288. }
  289.  
  290. // returns f(g(x))
  291. template <typename ValueType>
  292. Polynomial<ValueType> operator&(const Polynomial<ValueType>& f, const Polynomial<ValueType>& g) {
  293.     Polynomial<ValueType> cur_pow(ValueType(1));
  294.     Polynomial<ValueType> res(ValueType(0));
  295.  
  296.     for (int deg = 0; deg <= f.Degree(); ++deg) {
  297.         res += f[deg] * cur_pow;
  298.         cur_pow *= g;
  299.     }
  300.     return res;
  301. }
  302.  
  303. template <typename ValueType>
  304. Polynomial<ValueType> x_pow(size_t pow) {
  305.     std::vector<ValueType> vec(pow + 1, ValueType(0));
  306.     vec[pow] = ValueType(1);
  307.     return Polynomial(vec);
  308. }
  309.  
  310. template <typename ValueType>
  311. Polynomial<ValueType> operator/(Polynomial<ValueType> dividend,
  312.         const Polynomial<ValueType>& divisor) {
  313.     Polynomial<ValueType> res(ValueType(0));
  314.     if (dividend.Degree() < divisor.Degree()) {
  315.         return res;
  316.     }
  317.  
  318.     for (int cur_pow = dividend.Degree() - divisor.Degree(); cur_pow >= 0; ) {
  319.         Polynomial<ValueType> cur_mult =
  320.                 (dividend[dividend.Degree()] / divisor[divisor.Degree()])
  321.                 * x_pow<ValueType>(cur_pow);
  322.  
  323.         if (cur_mult == Polynomial<ValueType>(ValueType(0))) {
  324.             break;
  325.         }
  326.  
  327.         dividend -= cur_mult * divisor;
  328.         res += cur_mult;
  329.  
  330.         cur_pow = dividend.Degree() - divisor.Degree();
  331.     }
  332.  
  333.     return res;
  334. }
  335.  
  336. template <typename ValueType>
  337. Polynomial<ValueType> operator%(const Polynomial<ValueType>& dividend,
  338.         const Polynomial<ValueType>& divisor) {
  339.     return dividend - (dividend / divisor) * divisor;
  340. }
  341.  
  342. template <typename ValueType>
  343. Polynomial<ValueType> operator,(Polynomial<ValueType> a, Polynomial<ValueType> b) {
  344.     while (a.Degree() != -1 && b.Degree() != -1) {
  345.         if (a.Degree() > b.Degree() ||
  346.                 (a.Degree() == b.Degree() && a[a.Degree()] > b[b.Degree()])) {
  347.             a = a % b;
  348.         } else {
  349.             b = b % a;
  350.         }
  351.     }
  352.     Polynomial<ValueType> res = a + b;
  353.     return res / Polynomial(res[res.Degree()]);
  354. }
  355.  
Advertisement
Add Comment
Please, Sign In to add comment