polynomial.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. // (C) Copyright John Maddock 2006.
  2. // (C) Copyright Jeremy William Murphy 2015.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_MATH_TOOLS_POLYNOMIAL_HPP
  7. #define BOOST_MATH_TOOLS_POLYNOMIAL_HPP
  8. #ifdef _MSC_VER
  9. #pragma once
  10. #endif
  11. #include <boost/math/tools/assert.hpp>
  12. #include <boost/math/tools/config.hpp>
  13. #include <boost/math/tools/cxx03_warn.hpp>
  14. #include <boost/math/tools/rational.hpp>
  15. #include <boost/math/tools/real_cast.hpp>
  16. #include <boost/math/policies/error_handling.hpp>
  17. #include <boost/math/special_functions/binomial.hpp>
  18. #include <boost/math/tools/detail/is_const_iterable.hpp>
  19. #include <vector>
  20. #include <ostream>
  21. #include <algorithm>
  22. #include <initializer_list>
  23. #include <type_traits>
  24. #include <iterator>
  25. namespace boost{ namespace math{ namespace tools{
  26. template <class T>
  27. T chebyshev_coefficient(unsigned n, unsigned m)
  28. {
  29. BOOST_MATH_STD_USING
  30. if(m > n)
  31. return 0;
  32. if((n & 1) != (m & 1))
  33. return 0;
  34. if(n == 0)
  35. return 1;
  36. T result = T(n) / 2;
  37. unsigned r = n - m;
  38. r /= 2;
  39. BOOST_MATH_ASSERT(n - 2 * r == m);
  40. if(r & 1)
  41. result = -result;
  42. result /= n - r;
  43. result *= boost::math::binomial_coefficient<T>(n - r, r);
  44. result *= ldexp(1.0f, m);
  45. return result;
  46. }
  47. template <class Seq>
  48. Seq polynomial_to_chebyshev(const Seq& s)
  49. {
  50. // Converts a Polynomial into Chebyshev form:
  51. typedef typename Seq::value_type value_type;
  52. typedef typename Seq::difference_type difference_type;
  53. Seq result(s);
  54. difference_type order = s.size() - 1;
  55. difference_type even_order = order & 1 ? order - 1 : order;
  56. difference_type odd_order = order & 1 ? order : order - 1;
  57. for(difference_type i = even_order; i >= 0; i -= 2)
  58. {
  59. value_type val = s[i];
  60. for(difference_type k = even_order; k > i; k -= 2)
  61. {
  62. val -= result[k] * chebyshev_coefficient<value_type>(static_cast<unsigned>(k), static_cast<unsigned>(i));
  63. }
  64. val /= chebyshev_coefficient<value_type>(static_cast<unsigned>(i), static_cast<unsigned>(i));
  65. result[i] = val;
  66. }
  67. result[0] *= 2;
  68. for(difference_type i = odd_order; i >= 0; i -= 2)
  69. {
  70. value_type val = s[i];
  71. for(difference_type k = odd_order; k > i; k -= 2)
  72. {
  73. val -= result[k] * chebyshev_coefficient<value_type>(static_cast<unsigned>(k), static_cast<unsigned>(i));
  74. }
  75. val /= chebyshev_coefficient<value_type>(static_cast<unsigned>(i), static_cast<unsigned>(i));
  76. result[i] = val;
  77. }
  78. return result;
  79. }
  80. template <class Seq, class T>
  81. T evaluate_chebyshev(const Seq& a, const T& x)
  82. {
  83. // Clenshaw's formula:
  84. typedef typename Seq::difference_type difference_type;
  85. T yk2 = 0;
  86. T yk1 = 0;
  87. T yk = 0;
  88. for(difference_type i = a.size() - 1; i >= 1; --i)
  89. {
  90. yk2 = yk1;
  91. yk1 = yk;
  92. yk = 2 * x * yk1 - yk2 + a[i];
  93. }
  94. return a[0] / 2 + yk * x - yk1;
  95. }
  96. template <typename T>
  97. class polynomial;
  98. namespace detail {
  99. /**
  100. * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
  101. * Chapter 4.6.1, Algorithm D: Division of polynomials over a field.
  102. *
  103. * @tparam T Coefficient type, must be not be an integer.
  104. *
  105. * Template-parameter T actually must be a field but we don't currently have that
  106. * subtlety of distinction.
  107. */
  108. template <typename T, typename N>
  109. typename std::enable_if<!std::numeric_limits<T>::is_integer, void >::type
  110. division_impl(polynomial<T> &q, polynomial<T> &u, const polynomial<T>& v, N n, N k)
  111. {
  112. q[k] = u[n + k] / v[n];
  113. for (N j = n + k; j > k;)
  114. {
  115. j--;
  116. u[j] -= q[k] * v[j - k];
  117. }
  118. }
  119. template <class T, class N>
  120. T integer_power(T t, N n)
  121. {
  122. switch(n)
  123. {
  124. case 0:
  125. return static_cast<T>(1u);
  126. case 1:
  127. return t;
  128. case 2:
  129. return t * t;
  130. case 3:
  131. return t * t * t;
  132. }
  133. T result = integer_power(t, n / 2);
  134. result *= result;
  135. if(n & 1)
  136. result *= t;
  137. return result;
  138. }
  139. /**
  140. * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
  141. * Chapter 4.6.1, Algorithm R: Pseudo-division of polynomials.
  142. *
  143. * @tparam T Coefficient type, must be an integer.
  144. *
  145. * Template-parameter T actually must be a unique factorization domain but we
  146. * don't currently have that subtlety of distinction.
  147. */
  148. template <typename T, typename N>
  149. typename std::enable_if<std::numeric_limits<T>::is_integer, void >::type
  150. division_impl(polynomial<T> &q, polynomial<T> &u, const polynomial<T>& v, N n, N k)
  151. {
  152. q[k] = u[n + k] * integer_power(v[n], k);
  153. for (N j = n + k; j > 0;)
  154. {
  155. j--;
  156. u[j] = v[n] * u[j] - (j < k ? T(0) : u[n + k] * v[j - k]);
  157. }
  158. }
  159. /**
  160. * Knuth, The Art of Computer Programming: Volume 2, Third edition, 1998
  161. * Chapter 4.6.1, Algorithm D and R: Main loop.
  162. *
  163. * @param u Dividend.
  164. * @param v Divisor.
  165. */
  166. template <typename T>
  167. std::pair< polynomial<T>, polynomial<T> >
  168. division(polynomial<T> u, const polynomial<T>& v)
  169. {
  170. BOOST_MATH_ASSERT(v.size() <= u.size());
  171. BOOST_MATH_ASSERT(v);
  172. BOOST_MATH_ASSERT(u);
  173. typedef typename polynomial<T>::size_type N;
  174. N const m = u.size() - 1, n = v.size() - 1;
  175. N k = m - n;
  176. polynomial<T> q;
  177. q.data().resize(m - n + 1);
  178. do
  179. {
  180. division_impl(q, u, v, n, k);
  181. }
  182. while (k-- != 0);
  183. u.data().resize(n);
  184. u.normalize(); // Occasionally, the remainder is zeroes.
  185. return std::make_pair(q, u);
  186. }
  187. //
  188. // These structures are the same as the void specializations of the functors of the same name
  189. // in the std lib from C++14 onwards:
  190. //
  191. struct negate
  192. {
  193. template <class T>
  194. T operator()(T const &x) const
  195. {
  196. return -x;
  197. }
  198. };
  199. struct plus
  200. {
  201. template <class T, class U>
  202. T operator()(T const &x, U const& y) const
  203. {
  204. return x + y;
  205. }
  206. };
  207. struct minus
  208. {
  209. template <class T, class U>
  210. T operator()(T const &x, U const& y) const
  211. {
  212. return x - y;
  213. }
  214. };
  215. } // namespace detail
  216. /**
  217. * Returns the zero element for multiplication of polynomials.
  218. */
  219. template <class T>
  220. polynomial<T> zero_element(std::multiplies< polynomial<T> >)
  221. {
  222. return polynomial<T>();
  223. }
  224. template <class T>
  225. polynomial<T> identity_element(std::multiplies< polynomial<T> >)
  226. {
  227. return polynomial<T>(T(1));
  228. }
  229. /* Calculates a / b and a % b, returning the pair (quotient, remainder) together
  230. * because the same amount of computation yields both.
  231. * This function is not defined for division by zero: user beware.
  232. */
  233. template <typename T>
  234. std::pair< polynomial<T>, polynomial<T> >
  235. quotient_remainder(const polynomial<T>& dividend, const polynomial<T>& divisor)
  236. {
  237. BOOST_MATH_ASSERT(divisor);
  238. if (dividend.size() < divisor.size())
  239. return std::make_pair(polynomial<T>(), dividend);
  240. return detail::division(dividend, divisor);
  241. }
  242. template <class T>
  243. class polynomial
  244. {
  245. public:
  246. // typedefs:
  247. typedef typename std::vector<T>::value_type value_type;
  248. typedef typename std::vector<T>::size_type size_type;
  249. // construct:
  250. polynomial()= default;
  251. template <class U>
  252. polynomial(const U* data, unsigned order)
  253. : m_data(data, data + order + 1)
  254. {
  255. normalize();
  256. }
  257. template <class Iterator>
  258. polynomial(Iterator first, Iterator last)
  259. : m_data(first, last)
  260. {
  261. normalize();
  262. }
  263. template <class Iterator>
  264. polynomial(Iterator first, unsigned length)
  265. : m_data(first, std::next(first, length + 1))
  266. {
  267. normalize();
  268. }
  269. polynomial(std::vector<T>&& p) : m_data(std::move(p))
  270. {
  271. normalize();
  272. }
  273. template <class U, typename std::enable_if<std::is_convertible<U, T>::value, bool>::type = true>
  274. explicit polynomial(const U& point)
  275. {
  276. if (point != U(0))
  277. m_data.push_back(point);
  278. }
  279. // move:
  280. polynomial(polynomial&& p) noexcept
  281. : m_data(std::move(p.m_data)) { }
  282. // copy:
  283. polynomial(const polynomial& p)
  284. : m_data(p.m_data) { }
  285. template <class U>
  286. polynomial(const polynomial<U>& p)
  287. {
  288. m_data.resize(p.size());
  289. for(unsigned i = 0; i < p.size(); ++i)
  290. {
  291. m_data[i] = boost::math::tools::real_cast<T>(p[i]);
  292. }
  293. }
  294. #ifdef BOOST_MATH_HAS_IS_CONST_ITERABLE
  295. template <class Range, typename std::enable_if<boost::math::tools::detail::is_const_iterable<Range>::value, bool>::type = true>
  296. explicit polynomial(const Range& r)
  297. : polynomial(r.begin(), r.end())
  298. {
  299. }
  300. #endif
  301. polynomial(std::initializer_list<T> l) : polynomial(std::begin(l), std::end(l))
  302. {
  303. }
  304. polynomial&
  305. operator=(std::initializer_list<T> l)
  306. {
  307. m_data.assign(std::begin(l), std::end(l));
  308. normalize();
  309. return *this;
  310. }
  311. // access:
  312. size_type size() const { return m_data.size(); }
  313. size_type degree() const
  314. {
  315. if (size() == 0)
  316. BOOST_MATH_THROW_EXCEPTION(std::logic_error("degree() is undefined for the zero polynomial."));
  317. return m_data.size() - 1;
  318. }
  319. value_type& operator[](size_type i)
  320. {
  321. return m_data[i];
  322. }
  323. const value_type& operator[](size_type i) const
  324. {
  325. return m_data[i];
  326. }
  327. T evaluate(T z) const
  328. {
  329. return this->operator()(z);
  330. }
  331. T operator()(T z) const
  332. {
  333. return m_data.size() > 0 ? boost::math::tools::evaluate_polynomial((m_data).data(), z, m_data.size()) : T(0);
  334. }
  335. std::vector<T> chebyshev() const
  336. {
  337. return polynomial_to_chebyshev(m_data);
  338. }
  339. std::vector<T> const& data() const
  340. {
  341. return m_data;
  342. }
  343. std::vector<T> & data()
  344. {
  345. return m_data;
  346. }
  347. polynomial<T> prime() const
  348. {
  349. #ifdef _MSC_VER
  350. // Disable int->float conversion warning:
  351. #pragma warning(push)
  352. #pragma warning(disable:4244)
  353. #endif
  354. if (m_data.size() == 0)
  355. {
  356. return polynomial<T>({});
  357. }
  358. std::vector<T> p_data(m_data.size() - 1);
  359. for (size_t i = 0; i < p_data.size(); ++i) {
  360. p_data[i] = m_data[i+1]*static_cast<T>(i+1);
  361. }
  362. return polynomial<T>(std::move(p_data));
  363. #ifdef _MSC_VER
  364. #pragma warning(pop)
  365. #endif
  366. }
  367. polynomial<T> integrate() const
  368. {
  369. std::vector<T> i_data(m_data.size() + 1);
  370. // Choose integration constant such that P(0) = 0.
  371. i_data[0] = T(0);
  372. for (size_t i = 1; i < i_data.size(); ++i)
  373. {
  374. i_data[i] = m_data[i-1]/static_cast<T>(i);
  375. }
  376. return polynomial<T>(std::move(i_data));
  377. }
  378. // operators:
  379. polynomial& operator =(polynomial&& p) noexcept
  380. {
  381. m_data = std::move(p.m_data);
  382. return *this;
  383. }
  384. polynomial& operator =(const polynomial& p)
  385. {
  386. m_data = p.m_data;
  387. return *this;
  388. }
  389. template <class U>
  390. typename std::enable_if<std::is_constructible<T, U>::value, polynomial&>::type operator +=(const U& value)
  391. {
  392. addition(value);
  393. normalize();
  394. return *this;
  395. }
  396. template <class U>
  397. typename std::enable_if<std::is_constructible<T, U>::value, polynomial&>::type operator -=(const U& value)
  398. {
  399. subtraction(value);
  400. normalize();
  401. return *this;
  402. }
  403. template <class U>
  404. typename std::enable_if<std::is_constructible<T, U>::value, polynomial&>::type operator *=(const U& value)
  405. {
  406. multiplication(value);
  407. normalize();
  408. return *this;
  409. }
  410. template <class U>
  411. typename std::enable_if<std::is_constructible<T, U>::value, polynomial&>::type operator /=(const U& value)
  412. {
  413. division(value);
  414. normalize();
  415. return *this;
  416. }
  417. template <class U>
  418. typename std::enable_if<std::is_constructible<T, U>::value, polynomial&>::type operator %=(const U& /*value*/)
  419. {
  420. // We can always divide by a scalar, so there is no remainder:
  421. this->set_zero();
  422. return *this;
  423. }
  424. template <class U>
  425. polynomial& operator +=(const polynomial<U>& value)
  426. {
  427. addition(value);
  428. normalize();
  429. return *this;
  430. }
  431. template <class U>
  432. polynomial& operator -=(const polynomial<U>& value)
  433. {
  434. subtraction(value);
  435. normalize();
  436. return *this;
  437. }
  438. template <typename U, typename V>
  439. void multiply(const polynomial<U>& a, const polynomial<V>& b) {
  440. if (!a || !b)
  441. {
  442. this->set_zero();
  443. return;
  444. }
  445. std::vector<T> prod(a.size() + b.size() - 1, T(0));
  446. for (unsigned i = 0; i < a.size(); ++i)
  447. for (unsigned j = 0; j < b.size(); ++j)
  448. prod[i+j] += a.m_data[i] * b.m_data[j];
  449. m_data.swap(prod);
  450. }
  451. template <class U>
  452. polynomial& operator *=(const polynomial<U>& value)
  453. {
  454. this->multiply(*this, value);
  455. return *this;
  456. }
  457. template <typename U>
  458. polynomial& operator /=(const polynomial<U>& value)
  459. {
  460. *this = quotient_remainder(*this, value).first;
  461. return *this;
  462. }
  463. template <typename U>
  464. polynomial& operator %=(const polynomial<U>& value)
  465. {
  466. *this = quotient_remainder(*this, value).second;
  467. return *this;
  468. }
  469. template <typename U>
  470. polynomial& operator >>=(U const &n)
  471. {
  472. BOOST_MATH_ASSERT(n <= m_data.size());
  473. m_data.erase(m_data.begin(), m_data.begin() + n);
  474. return *this;
  475. }
  476. template <typename U>
  477. polynomial& operator <<=(U const &n)
  478. {
  479. m_data.insert(m_data.begin(), n, static_cast<T>(0));
  480. normalize();
  481. return *this;
  482. }
  483. // Convenient and efficient query for zero.
  484. bool is_zero() const
  485. {
  486. return m_data.empty();
  487. }
  488. // Conversion to bool.
  489. inline explicit operator bool() const
  490. {
  491. return !m_data.empty();
  492. }
  493. // Fast way to set a polynomial to zero.
  494. void set_zero()
  495. {
  496. m_data.clear();
  497. }
  498. /** Remove zero coefficients 'from the top', that is for which there are no
  499. * non-zero coefficients of higher degree. */
  500. void normalize()
  501. {
  502. m_data.erase(std::find_if(m_data.rbegin(), m_data.rend(), [](const T& x)->bool { return x != T(0); }).base(), m_data.end());
  503. }
  504. private:
  505. template <class U, class R>
  506. polynomial& addition(const U& value, R op)
  507. {
  508. if(m_data.size() == 0)
  509. m_data.resize(1, 0);
  510. m_data[0] = op(m_data[0], value);
  511. return *this;
  512. }
  513. template <class U>
  514. polynomial& addition(const U& value)
  515. {
  516. return addition(value, detail::plus());
  517. }
  518. template <class U>
  519. polynomial& subtraction(const U& value)
  520. {
  521. return addition(value, detail::minus());
  522. }
  523. template <class U, class R>
  524. polynomial& addition(const polynomial<U>& value, R op)
  525. {
  526. if (m_data.size() < value.size())
  527. m_data.resize(value.size(), 0);
  528. for(size_type i = 0; i < value.size(); ++i)
  529. m_data[i] = op(m_data[i], value[i]);
  530. return *this;
  531. }
  532. template <class U>
  533. polynomial& addition(const polynomial<U>& value)
  534. {
  535. return addition(value, detail::plus());
  536. }
  537. template <class U>
  538. polynomial& subtraction(const polynomial<U>& value)
  539. {
  540. return addition(value, detail::minus());
  541. }
  542. template <class U>
  543. polynomial& multiplication(const U& value)
  544. {
  545. std::transform(m_data.begin(), m_data.end(), m_data.begin(), [&](const T& x)->T { return x * value; });
  546. return *this;
  547. }
  548. template <class U>
  549. polynomial& division(const U& value)
  550. {
  551. std::transform(m_data.begin(), m_data.end(), m_data.begin(), [&](const T& x)->T { return x / value; });
  552. return *this;
  553. }
  554. std::vector<T> m_data;
  555. };
  556. template <class T>
  557. inline polynomial<T> operator + (const polynomial<T>& a, const polynomial<T>& b)
  558. {
  559. polynomial<T> result(a);
  560. result += b;
  561. return result;
  562. }
  563. template <class T>
  564. inline polynomial<T> operator + (polynomial<T>&& a, const polynomial<T>& b)
  565. {
  566. a += b;
  567. return std::move(a);
  568. }
  569. template <class T>
  570. inline polynomial<T> operator + (const polynomial<T>& a, polynomial<T>&& b)
  571. {
  572. b += a;
  573. return b;
  574. }
  575. template <class T>
  576. inline polynomial<T> operator + (polynomial<T>&& a, polynomial<T>&& b)
  577. {
  578. a += b;
  579. return a;
  580. }
  581. template <class T>
  582. inline polynomial<T> operator - (const polynomial<T>& a, const polynomial<T>& b)
  583. {
  584. polynomial<T> result(a);
  585. result -= b;
  586. return result;
  587. }
  588. template <class T>
  589. inline polynomial<T> operator - (polynomial<T>&& a, const polynomial<T>& b)
  590. {
  591. a -= b;
  592. return a;
  593. }
  594. template <class T>
  595. inline polynomial<T> operator - (const polynomial<T>& a, polynomial<T>&& b)
  596. {
  597. b -= a;
  598. return -b;
  599. }
  600. template <class T>
  601. inline polynomial<T> operator - (polynomial<T>&& a, polynomial<T>&& b)
  602. {
  603. a -= b;
  604. return a;
  605. }
  606. template <class T>
  607. inline polynomial<T> operator * (const polynomial<T>& a, const polynomial<T>& b)
  608. {
  609. polynomial<T> result;
  610. result.multiply(a, b);
  611. return result;
  612. }
  613. template <class T>
  614. inline polynomial<T> operator / (const polynomial<T>& a, const polynomial<T>& b)
  615. {
  616. return quotient_remainder(a, b).first;
  617. }
  618. template <class T>
  619. inline polynomial<T> operator % (const polynomial<T>& a, const polynomial<T>& b)
  620. {
  621. return quotient_remainder(a, b).second;
  622. }
  623. template <class T, class U>
  624. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator + (polynomial<T> a, const U& b)
  625. {
  626. a += b;
  627. return a;
  628. }
  629. template <class T, class U>
  630. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator - (polynomial<T> a, const U& b)
  631. {
  632. a -= b;
  633. return a;
  634. }
  635. template <class T, class U>
  636. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator * (polynomial<T> a, const U& b)
  637. {
  638. a *= b;
  639. return a;
  640. }
  641. template <class T, class U>
  642. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator / (polynomial<T> a, const U& b)
  643. {
  644. a /= b;
  645. return a;
  646. }
  647. template <class T, class U>
  648. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator % (const polynomial<T>&, const U&)
  649. {
  650. // Since we can always divide by a scalar, result is always an empty polynomial:
  651. return polynomial<T>();
  652. }
  653. template <class U, class T>
  654. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator + (const U& a, polynomial<T> b)
  655. {
  656. b += a;
  657. return b;
  658. }
  659. template <class U, class T>
  660. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator - (const U& a, polynomial<T> b)
  661. {
  662. b -= a;
  663. return -b;
  664. }
  665. template <class U, class T>
  666. inline typename std::enable_if<std::is_constructible<T, U>::value, polynomial<T> >::type operator * (const U& a, polynomial<T> b)
  667. {
  668. b *= a;
  669. return b;
  670. }
  671. template <class T>
  672. bool operator == (const polynomial<T> &a, const polynomial<T> &b)
  673. {
  674. return a.data() == b.data();
  675. }
  676. template <class T>
  677. bool operator != (const polynomial<T> &a, const polynomial<T> &b)
  678. {
  679. return a.data() != b.data();
  680. }
  681. template <typename T, typename U>
  682. polynomial<T> operator >> (polynomial<T> a, const U& b)
  683. {
  684. a >>= b;
  685. return a;
  686. }
  687. template <typename T, typename U>
  688. polynomial<T> operator << (polynomial<T> a, const U& b)
  689. {
  690. a <<= b;
  691. return a;
  692. }
  693. // Unary minus (negate).
  694. template <class T>
  695. polynomial<T> operator - (polynomial<T> a)
  696. {
  697. std::transform(a.data().begin(), a.data().end(), a.data().begin(), detail::negate());
  698. return a;
  699. }
  700. template <class T>
  701. bool odd(polynomial<T> const &a)
  702. {
  703. return a.size() > 0 && a[0] != static_cast<T>(0);
  704. }
  705. template <class T>
  706. bool even(polynomial<T> const &a)
  707. {
  708. return !odd(a);
  709. }
  710. template <class T>
  711. polynomial<T> pow(polynomial<T> base, int exp)
  712. {
  713. if (exp < 0)
  714. return policies::raise_domain_error(
  715. "boost::math::tools::pow<%1%>",
  716. "Negative powers are not supported for polynomials.",
  717. base, policies::policy<>());
  718. // if the policy is ignore_error or errno_on_error, raise_domain_error
  719. // will return std::numeric_limits<polynomial<T>>::quiet_NaN(), which
  720. // defaults to polynomial<T>(), which is the zero polynomial
  721. polynomial<T> result(T(1));
  722. if (exp & 1)
  723. result = base;
  724. /* "Exponentiation by squaring" */
  725. while (exp >>= 1)
  726. {
  727. base *= base;
  728. if (exp & 1)
  729. result *= base;
  730. }
  731. return result;
  732. }
  733. template <class charT, class traits, class T>
  734. inline std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& os, const polynomial<T>& poly)
  735. {
  736. os << "{ ";
  737. for(unsigned i = 0; i < poly.size(); ++i)
  738. {
  739. if(i) os << ", ";
  740. os << poly[i];
  741. }
  742. os << " }";
  743. return os;
  744. }
  745. } // namespace tools
  746. } // namespace math
  747. } // namespace boost
  748. //
  749. // Polynomial specific overload of gcd algorithm:
  750. //
  751. #include <boost/math/tools/polynomial_gcd.hpp>
  752. #endif // BOOST_MATH_TOOLS_POLYNOMIAL_HPP