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