00001
00002
00003
00004
00005
00006
00007
00008
00015 #ifndef __ARAGELI_polynom_hpp__
00016 #define __ARAGELI_polynom_hpp__
00017
00018 #include <cstddef>
00019 #include <iostream>
00020 #include <vector>
00021 #include <iomanip>
00022 #include <algorithm>
00023 #include <cmath>
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "config.hpp"
00034 #include "refcntr.hpp"
00035 #include "iteradapt.hpp"
00036 #include "factory.hpp"
00037 #include "powerest.hpp"
00038 #include "exception.hpp"
00039 #include "_utility.hpp"
00040
00041 namespace Arageli
00042 {
00043
00048 template <typename F>
00049 class polynom
00050 {
00051 public:
00053 typedef F coef_type;
00055 typedef std::pair<polynom<F>, polynom<F> > div_result_type;
00056 protected:
00057 template <typename F>
00058 void fixLeadingZeroes()
00059 {
00060 std::size_t k = c.size()-1;
00061 while (c[k] == factory<coef_type>::null() && k > 0)
00062 k--;
00063 c.resize(k+1);
00064 }
00065
00066 public:
00068 std::size_t size() const { return c.size(); }
00070 std::size_t deg() const { return size()-1; }
00071
00072 void setLe(const std::vector<F> &coefficients)
00073 {
00074 std::size_t k = coefficients.size()-1;
00075 while (coefficients[k] == factory<coef_type>::null() && k > 0)
00076 k--;
00077 c.reserve(k + 1);
00078 for (std::size_t i = 0; i <= k; i++)
00079 c.push_back(coefficients[i]);
00080 }
00081
00082 void setLe(const vector<F> &coefficients)
00083 {
00084 std::size_t k = coefficients.get_n()-1;
00085 while (coefficients[k] == factory<coef_type>::null() && k > 0)
00086 k--;
00087 c.reserve(k + 1);
00088 for (std::size_t i = 0; i <= k; i++)
00089 c.push_back(coefficients[i]);
00090 }
00091
00092 void setBe(const std::vector<F> &coefficients)
00093 {
00094
00095 int k = 0;
00096 while (coefficients[k] == factory<coef_type>::null() && k < (int)coefficients.size()-1)
00097 k++;
00098 c.reserve((int)coefficients.size() - k);
00099 for (int i = (int)coefficients.size() - 1; i >= k; i--)
00100 c.push_back(coefficients[i]);
00101 }
00102
00103 void setBe(const vector<F> &coefficients)
00104 {
00105
00106 int k = 0;
00107 while (coefficients[k] == factory<coef_type>::null() && k < (int)coefficients.get_n()-1)
00108 k++;
00109 c.reserve((int)coefficients.get_n() - k);
00110 for (int i = (int)coefficients.get_n() - 1; i >= k; i--)
00111 c.push_back(coefficients[i]);
00112 }
00113
00114 const std::vector<F> &getData() const
00115 {
00116 return c;
00117 }
00118
00124 div_result_type div (const polynom<F>& a) const
00125 {
00126 if ((*this).size() < a.size())
00127 return div_result_type(polynom<F>(), *this);
00128 polynom<F> q;
00129 q.c.resize((*this).size() - a.size() + 1, factory<coef_type>::null());
00130 polynom<F> r;
00131 r.c = (*this).c;
00132 std::size_t rSize = r.size();
00133
00134 while (rSize >= a.size())
00135 {
00136 F qValue = r.c[rSize - 1] / a[a.size()-1];
00137 q.c[rSize - a.size()] = qValue;
00138 for (std::size_t i = 0, j = rSize - a.size(); i < a.size(); i++, j++)
00139 r.c[j] -= qValue * a[i];
00140 if (factory<coef_type>::null() != r.c[rSize - 1])
00141 throw "can't divide";
00142 rSize--;
00143 }
00144 q.fixLeadingZeroes<F>();
00145 r.fixLeadingZeroes<F>();
00146
00147 return div_result_type(q, r);
00148 }
00149
00150 polynom<F>& operator = (const polynom<F>& copy)
00151 {
00152 c = copy.c;
00153 return *this;
00154 }
00155
00156 F& operator [] (std::size_t i)
00157 {
00158 return c[i];
00159 }
00160
00161 const F& operator [] (std::size_t i) const
00162 {
00163 return c[i];
00164 }
00165
00166 polynom<F> operator - ( ) const
00167 {
00168 polynom<F> res(*this);
00169 for (std::size_t i = 0; i < res.size(); i++)
00170 res[i] = -res[i];
00171 return res;
00172 }
00173
00174 template <typename F>
00175 bool operator < (const polynom<F>& a) const
00176 {
00177 if ((*this).size() < a.size())
00178 return true;
00179 if ((*this).size() == a.size())
00180 return (*this)[(*this).size() - 1] < a[a.size()-1];
00181 return false;
00182 }
00183
00184 template <typename F>
00185 bool operator <= (const polynom<F>& a) const
00186 {
00187 if ((*this).size() < a.size())
00188 return true;
00189 if ((*this).size() == a.size())
00190 return (*this)[(*this).size() - 1] <= a[a.size()-1];
00191 return false;
00192 }
00193
00194 template <typename F>
00195 bool operator > (const polynom<F>& a) const
00196 {
00197 if ((*this).size() > a.size())
00198 return true;
00199 if ((*this).size() == a.size())
00200 return (*this)[(*this).size() - 1] > a[a.size()-1];
00201 return false;
00202 }
00203
00204 template <typename F>
00205 bool operator >= (const polynom<F>& a) const
00206 {
00207 if ((*this).size() > a.size())
00208 return true;
00209 if ((*this).size() == a.size())
00210 return (*this)[(*this).size() - 1] >= a[a.size()-1];
00211 return false;
00212 }
00213
00214 template <typename F>
00215 polynom<F> operator + (const polynom<F>& a) const
00216 {
00217 polynom<F> res;
00218 const polynom<F> *op;
00219
00220 if (a.size() > (*this).size())
00221 {
00222 res = polynom<F>(a);
00223 op = this;
00224 }
00225 else
00226 {
00227 res = polynom<F>(*this);
00228 op = &a;
00229 }
00230
00231 for (std::size_t i = 0; i < op->size(); i++)
00232 res[i] += (*op)[i];
00233
00234 res.fixLeadingZeroes<F>();
00235 return res;
00236 }
00237
00238 template <typename F>
00239 polynom<F> operator - (const polynom<F>& a) const
00240 {
00241 return *this + (-a);
00242 }
00243
00244 template <typename F>
00245 polynom<F> operator * (const polynom<F>& a) const
00246 {
00247 std::size_t i, j;
00248 std::vector<F> res(a.size() + (*this).size() - 1, factory<coef_type>::null());
00249
00250 for (i = 0; i < a.size(); i++)
00251 for (j = 0; j < (*this).size(); j++)
00252 {
00253 res[i+j] += a[i] * (*this)[j];
00254 }
00255
00256 std::size_t k = res.size() - 1;
00257 while (res[k] == factory<coef_type>::null() && k > 0)
00258 k--;
00259 res.resize(k + 1);
00260
00261 for (i = 0; i < res.size()/2; i++)
00262 std::swap(res[i], res[res.size() - i - 1]);
00263
00264 return polynom<F>(res);
00265 }
00266
00267 template <typename F>
00268 polynom<F> operator / (const polynom<F>& a) const
00269 {
00270 return div(a).first;
00271 }
00272
00273 template <typename F>
00274 polynom<F> operator % (const polynom<F>& a) const
00275 {
00276 return div(a).second;
00277 }
00278
00279 polynom<F>& operator += (const polynom<F>& a)
00280 {
00281 *this = *this + a;
00282 return *this;
00283 }
00284
00285 polynom<F>& operator -= (const polynom<F>& a)
00286 {
00287 *this = *this - a;
00288 return *this;
00289 }
00290
00291 polynom<F>& operator *= (const polynom<F>& a)
00292 {
00293 *this = *this * a;
00294 return *this;
00295 }
00296
00297 polynom<F>& operator /= (const polynom<F>& a)
00298 {
00299 *this = *this / a;
00300 return *this;
00301 }
00302
00303 int operator == (const polynom<F>& a) const
00304 {
00305 return (*this).c == a.c;
00306 }
00307
00308 int operator != (const polynom<F>& a) const
00309 {
00310 return !((*this) == a);
00311 }
00312
00313 protected:
00314 std::vector<F> c;
00315 public:
00317 polynom<F>()
00318 {
00319 c.push_back(factory<coef_type>::null());
00320 }
00321
00327 polynom<F>(const F& value, std::size_t deg = 0)
00328 {
00329 c.resize(deg+1, factory<coef_type>::null());
00330 c[deg] = value;
00331 }
00332
00337 polynom<F>(const polynom<F>& copy)
00338 {
00339 c = copy.c;
00340 }
00341
00347 polynom<F>(const std::vector<F> &coeff, bool le = false)
00348 {
00349 if (le)
00350 setLe(coeff);
00351 else
00352 setBe(coeff);
00353 }
00354
00355 polynom<F>(const vector<F> &coefficients, bool le = false)
00356 {
00357 if (le)
00358 setLe(coefficients);
00359 else
00360 setBe(coefficients);
00361 }
00362
00363 polynom<F>(const F *coefficients, std::size_t count, bool le = false)
00364 {
00365 std::vector<F> vCoeff;
00366 vCoeff.reserve(count);
00367 for (std::size_t i = 0; i < count; i++)
00368 vCoeff.push_back(coefficients[i]);
00369 if (le)
00370 setLe(vCoeff);
00371 else
00372 setBe(vCoeff);
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00385 ~polynom<F>()
00386 {
00387 }
00388 public:
00389 static polynom<F> constant(const F& value)
00390 {
00391 return polynom<F>(value, 0);
00392 }
00393 };
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 template <typename F, typename FT>
00413 std::ostream& operator << (std::ostream & s, const polynom<F> &v)
00414 {
00415 std::size_t i = v.deg() + 1;
00416 s << "(";
00417 do {
00418 i--;
00419 s << v[i] << ", ";
00420 } while(i != 0);
00421 s << ")";
00422
00423
00424
00425
00426 return s;
00427 }
00428
00429 template <typename F, typename FT>
00430 polynom<F> abs(const polynom<F> &maxVal)
00431 {
00432 polynom<F> res(factory<coef_type>::unit(), maxVal.deg());
00433 for (std::size_t i = 0; i < res.size(); i++)
00434 res[i] = abs(maxVal[i]);
00435 return res;
00436 }
00437
00444 template <typename F, typename FT>
00445 polynom<F> normalize(const polynom<F> &val)
00446 {
00447 polynom<F> res(val);
00448 F d = val[val.size()-1];
00449 for (std::size_t i = 0; i < val.size(); i++)
00450 res[i] = val[i] / d;
00451 return res;
00452 }
00453
00454
00455 }
00456
00457
00458 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00459 #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYNOM
00460 #include "polynom.cpp"
00461 #undef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_POLYNOM
00462 #endif
00463
00464 #endif
00465