annotate DEPENDENCIES/generic/include/boost/math/tools/polynomial.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // (C) Copyright John Maddock 2006.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #ifndef BOOST_MATH_TOOLS_POLYNOMIAL_HPP
Chris@16 7 #define BOOST_MATH_TOOLS_POLYNOMIAL_HPP
Chris@16 8
Chris@16 9 #ifdef _MSC_VER
Chris@16 10 #pragma once
Chris@16 11 #endif
Chris@16 12
Chris@16 13 #include <boost/assert.hpp>
Chris@16 14 #include <boost/math/tools/rational.hpp>
Chris@16 15 #include <boost/math/tools/real_cast.hpp>
Chris@16 16 #include <boost/math/special_functions/binomial.hpp>
Chris@16 17
Chris@16 18 #include <vector>
Chris@16 19 #include <ostream>
Chris@16 20 #include <algorithm>
Chris@16 21
Chris@16 22 namespace boost{ namespace math{ namespace tools{
Chris@16 23
Chris@16 24 template <class T>
Chris@16 25 T chebyshev_coefficient(unsigned n, unsigned m)
Chris@16 26 {
Chris@16 27 BOOST_MATH_STD_USING
Chris@16 28 if(m > n)
Chris@16 29 return 0;
Chris@16 30 if((n & 1) != (m & 1))
Chris@16 31 return 0;
Chris@16 32 if(n == 0)
Chris@16 33 return 1;
Chris@16 34 T result = T(n) / 2;
Chris@16 35 unsigned r = n - m;
Chris@16 36 r /= 2;
Chris@16 37
Chris@16 38 BOOST_ASSERT(n - 2 * r == m);
Chris@16 39
Chris@16 40 if(r & 1)
Chris@16 41 result = -result;
Chris@16 42 result /= n - r;
Chris@16 43 result *= boost::math::binomial_coefficient<T>(n - r, r);
Chris@16 44 result *= ldexp(1.0f, m);
Chris@16 45 return result;
Chris@16 46 }
Chris@16 47
Chris@16 48 template <class Seq>
Chris@16 49 Seq polynomial_to_chebyshev(const Seq& s)
Chris@16 50 {
Chris@16 51 // Converts a Polynomial into Chebyshev form:
Chris@16 52 typedef typename Seq::value_type value_type;
Chris@16 53 typedef typename Seq::difference_type difference_type;
Chris@16 54 Seq result(s);
Chris@16 55 difference_type order = s.size() - 1;
Chris@16 56 difference_type even_order = order & 1 ? order - 1 : order;
Chris@16 57 difference_type odd_order = order & 1 ? order : order - 1;
Chris@16 58
Chris@16 59 for(difference_type i = even_order; i >= 0; i -= 2)
Chris@16 60 {
Chris@16 61 value_type val = s[i];
Chris@16 62 for(difference_type k = even_order; k > i; k -= 2)
Chris@16 63 {
Chris@16 64 val -= result[k] * chebyshev_coefficient<value_type>(static_cast<unsigned>(k), static_cast<unsigned>(i));
Chris@16 65 }
Chris@16 66 val /= chebyshev_coefficient<value_type>(static_cast<unsigned>(i), static_cast<unsigned>(i));
Chris@16 67 result[i] = val;
Chris@16 68 }
Chris@16 69 result[0] *= 2;
Chris@16 70
Chris@16 71 for(difference_type i = odd_order; i >= 0; i -= 2)
Chris@16 72 {
Chris@16 73 value_type val = s[i];
Chris@16 74 for(difference_type k = odd_order; k > i; k -= 2)
Chris@16 75 {
Chris@16 76 val -= result[k] * chebyshev_coefficient<value_type>(static_cast<unsigned>(k), static_cast<unsigned>(i));
Chris@16 77 }
Chris@16 78 val /= chebyshev_coefficient<value_type>(static_cast<unsigned>(i), static_cast<unsigned>(i));
Chris@16 79 result[i] = val;
Chris@16 80 }
Chris@16 81 return result;
Chris@16 82 }
Chris@16 83
Chris@16 84 template <class Seq, class T>
Chris@16 85 T evaluate_chebyshev(const Seq& a, const T& x)
Chris@16 86 {
Chris@16 87 // Clenshaw's formula:
Chris@16 88 typedef typename Seq::difference_type difference_type;
Chris@16 89 T yk2 = 0;
Chris@16 90 T yk1 = 0;
Chris@16 91 T yk = 0;
Chris@16 92 for(difference_type i = a.size() - 1; i >= 1; --i)
Chris@16 93 {
Chris@16 94 yk2 = yk1;
Chris@16 95 yk1 = yk;
Chris@16 96 yk = 2 * x * yk1 - yk2 + a[i];
Chris@16 97 }
Chris@16 98 return a[0] / 2 + yk * x - yk1;
Chris@16 99 }
Chris@16 100
Chris@16 101 template <class T>
Chris@16 102 class polynomial
Chris@16 103 {
Chris@16 104 public:
Chris@16 105 // typedefs:
Chris@16 106 typedef typename std::vector<T>::value_type value_type;
Chris@16 107 typedef typename std::vector<T>::size_type size_type;
Chris@16 108
Chris@16 109 // construct:
Chris@16 110 polynomial(){}
Chris@16 111 template <class U>
Chris@16 112 polynomial(const U* data, unsigned order)
Chris@16 113 : m_data(data, data + order + 1)
Chris@16 114 {
Chris@16 115 }
Chris@16 116 template <class U>
Chris@16 117 polynomial(const U& point)
Chris@16 118 {
Chris@16 119 m_data.push_back(point);
Chris@16 120 }
Chris@16 121
Chris@16 122 // copy:
Chris@16 123 polynomial(const polynomial& p)
Chris@16 124 : m_data(p.m_data) { }
Chris@16 125
Chris@16 126 template <class U>
Chris@16 127 polynomial(const polynomial<U>& p)
Chris@16 128 {
Chris@16 129 for(unsigned i = 0; i < p.size(); ++i)
Chris@16 130 {
Chris@16 131 m_data.push_back(boost::math::tools::real_cast<T>(p[i]));
Chris@16 132 }
Chris@16 133 }
Chris@16 134
Chris@16 135 // access:
Chris@16 136 size_type size()const { return m_data.size(); }
Chris@16 137 size_type degree()const { return m_data.size() - 1; }
Chris@16 138 value_type& operator[](size_type i)
Chris@16 139 {
Chris@16 140 return m_data[i];
Chris@16 141 }
Chris@16 142 const value_type& operator[](size_type i)const
Chris@16 143 {
Chris@16 144 return m_data[i];
Chris@16 145 }
Chris@16 146 T evaluate(T z)const
Chris@16 147 {
Chris@16 148 return boost::math::tools::evaluate_polynomial(&m_data[0], z, m_data.size());;
Chris@16 149 }
Chris@16 150 std::vector<T> chebyshev()const
Chris@16 151 {
Chris@16 152 return polynomial_to_chebyshev(m_data);
Chris@16 153 }
Chris@16 154
Chris@16 155 // operators:
Chris@16 156 template <class U>
Chris@16 157 polynomial& operator +=(const U& value)
Chris@16 158 {
Chris@16 159 if(m_data.size() == 0)
Chris@16 160 m_data.push_back(value);
Chris@16 161 else
Chris@16 162 {
Chris@16 163 m_data[0] += value;
Chris@16 164 }
Chris@16 165 return *this;
Chris@16 166 }
Chris@16 167 template <class U>
Chris@16 168 polynomial& operator -=(const U& value)
Chris@16 169 {
Chris@16 170 if(m_data.size() == 0)
Chris@16 171 m_data.push_back(-value);
Chris@16 172 else
Chris@16 173 {
Chris@16 174 m_data[0] -= value;
Chris@16 175 }
Chris@16 176 return *this;
Chris@16 177 }
Chris@16 178 template <class U>
Chris@16 179 polynomial& operator *=(const U& value)
Chris@16 180 {
Chris@16 181 for(size_type i = 0; i < m_data.size(); ++i)
Chris@16 182 m_data[i] *= value;
Chris@16 183 return *this;
Chris@16 184 }
Chris@16 185 template <class U>
Chris@16 186 polynomial& operator +=(const polynomial<U>& value)
Chris@16 187 {
Chris@16 188 size_type s1 = (std::min)(m_data.size(), value.size());
Chris@16 189 for(size_type i = 0; i < s1; ++i)
Chris@16 190 m_data[i] += value[i];
Chris@16 191 for(size_type i = s1; i < value.size(); ++i)
Chris@16 192 m_data.push_back(value[i]);
Chris@16 193 return *this;
Chris@16 194 }
Chris@16 195 template <class U>
Chris@16 196 polynomial& operator -=(const polynomial<U>& value)
Chris@16 197 {
Chris@16 198 size_type s1 = (std::min)(m_data.size(), value.size());
Chris@16 199 for(size_type i = 0; i < s1; ++i)
Chris@16 200 m_data[i] -= value[i];
Chris@16 201 for(size_type i = s1; i < value.size(); ++i)
Chris@16 202 m_data.push_back(-value[i]);
Chris@16 203 return *this;
Chris@16 204 }
Chris@16 205 template <class U>
Chris@16 206 polynomial& operator *=(const polynomial<U>& value)
Chris@16 207 {
Chris@16 208 // TODO: FIXME: use O(N log(N)) algorithm!!!
Chris@16 209 BOOST_ASSERT(value.size());
Chris@16 210 polynomial base(*this);
Chris@16 211 *this *= value[0];
Chris@16 212 for(size_type i = 1; i < value.size(); ++i)
Chris@16 213 {
Chris@16 214 polynomial t(base);
Chris@16 215 t *= value[i];
Chris@16 216 size_type s = size() - i;
Chris@16 217 for(size_type j = 0; j < s; ++j)
Chris@16 218 {
Chris@16 219 m_data[i+j] += t[j];
Chris@16 220 }
Chris@16 221 for(size_type j = s; j < t.size(); ++j)
Chris@16 222 m_data.push_back(t[j]);
Chris@16 223 }
Chris@16 224 return *this;
Chris@16 225 }
Chris@16 226
Chris@16 227 private:
Chris@16 228 std::vector<T> m_data;
Chris@16 229 };
Chris@16 230
Chris@16 231 template <class T>
Chris@16 232 inline polynomial<T> operator + (const polynomial<T>& a, const polynomial<T>& b)
Chris@16 233 {
Chris@16 234 polynomial<T> result(a);
Chris@16 235 result += b;
Chris@16 236 return result;
Chris@16 237 }
Chris@16 238
Chris@16 239 template <class T>
Chris@16 240 inline polynomial<T> operator - (const polynomial<T>& a, const polynomial<T>& b)
Chris@16 241 {
Chris@16 242 polynomial<T> result(a);
Chris@16 243 result -= b;
Chris@16 244 return result;
Chris@16 245 }
Chris@16 246
Chris@16 247 template <class T>
Chris@16 248 inline polynomial<T> operator * (const polynomial<T>& a, const polynomial<T>& b)
Chris@16 249 {
Chris@16 250 polynomial<T> result(a);
Chris@16 251 result *= b;
Chris@16 252 return result;
Chris@16 253 }
Chris@16 254
Chris@16 255 template <class T, class U>
Chris@16 256 inline polynomial<T> operator + (const polynomial<T>& a, const U& b)
Chris@16 257 {
Chris@16 258 polynomial<T> result(a);
Chris@16 259 result += b;
Chris@16 260 return result;
Chris@16 261 }
Chris@16 262
Chris@16 263 template <class T, class U>
Chris@16 264 inline polynomial<T> operator - (const polynomial<T>& a, const U& b)
Chris@16 265 {
Chris@16 266 polynomial<T> result(a);
Chris@16 267 result -= b;
Chris@16 268 return result;
Chris@16 269 }
Chris@16 270
Chris@16 271 template <class T, class U>
Chris@16 272 inline polynomial<T> operator * (const polynomial<T>& a, const U& b)
Chris@16 273 {
Chris@16 274 polynomial<T> result(a);
Chris@16 275 result *= b;
Chris@16 276 return result;
Chris@16 277 }
Chris@16 278
Chris@16 279 template <class U, class T>
Chris@16 280 inline polynomial<T> operator + (const U& a, const polynomial<T>& b)
Chris@16 281 {
Chris@16 282 polynomial<T> result(b);
Chris@16 283 result += a;
Chris@16 284 return result;
Chris@16 285 }
Chris@16 286
Chris@16 287 template <class U, class T>
Chris@16 288 inline polynomial<T> operator - (const U& a, const polynomial<T>& b)
Chris@16 289 {
Chris@16 290 polynomial<T> result(a);
Chris@16 291 result -= b;
Chris@16 292 return result;
Chris@16 293 }
Chris@16 294
Chris@16 295 template <class U, class T>
Chris@16 296 inline polynomial<T> operator * (const U& a, const polynomial<T>& b)
Chris@16 297 {
Chris@16 298 polynomial<T> result(b);
Chris@16 299 result *= a;
Chris@16 300 return result;
Chris@16 301 }
Chris@16 302
Chris@16 303 template <class charT, class traits, class T>
Chris@16 304 inline std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& os, const polynomial<T>& poly)
Chris@16 305 {
Chris@16 306 os << "{ ";
Chris@16 307 for(unsigned i = 0; i < poly.size(); ++i)
Chris@16 308 {
Chris@16 309 if(i) os << ", ";
Chris@16 310 os << poly[i];
Chris@16 311 }
Chris@16 312 os << " }";
Chris@16 313 return os;
Chris@16 314 }
Chris@16 315
Chris@16 316 } // namespace tools
Chris@16 317 } // namespace math
Chris@16 318 } // namespace boost
Chris@16 319
Chris@16 320 #endif // BOOST_MATH_TOOLS_POLYNOMIAL_HPP
Chris@16 321
Chris@16 322
Chris@16 323