polynomial.hpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Ifdefs
00010 *****************************************************************************/
00011 
00012 #ifndef ECL_GEOMETRY_POLYNOMIALS_HPP_
00013 #define ECL_GEOMETRY_POLYNOMIALS_HPP_
00014 
00015 /*****************************************************************************
00016 ** Includes
00017 *****************************************************************************/
00018 
00019 #include <cmath>
00020 #include "cartesian_point.hpp"
00021 #include "function_math.hpp"
00022 #include "pascals_triangle.hpp"
00023 #include <ecl/config/macros.hpp>
00024 #include <ecl/concepts/macros.hpp>
00025 #include <ecl/concepts/streams.hpp>
00026 #include <ecl/containers/array.hpp>
00027 #include <ecl/exceptions/standard_exception.hpp>
00028 #include <ecl/errors/compile_time_assert.hpp>
00029 #include <ecl/utilities/blueprints.hpp>
00030 #include <ecl/formatters/floats.hpp>
00031 #include <iostream>
00032 
00033 /*****************************************************************************
00034 ** Namespaces
00035 *****************************************************************************/
00036 
00037 namespace ecl {
00038 
00039 /*****************************************************************************
00040 ** Interface [Polynomial]
00041 *****************************************************************************/
00080 template <unsigned int N>
00081 class ECL_PUBLIC Polynomial : public BluePrintFactory< Polynomial<N> >, public FunctionMath< Polynomial<N> > {
00082     public:
00083         /*********************
00084         ** Convenience
00085         **********************/
00086         typedef Array<double,N+1> Coefficients; 
00088         /*********************
00089         ** C&D
00090         **********************/
00098         Polynomial() : coeff(Coefficients::Constant(0.0)) {};
00099 
00124         template<typename Derived>
00125         Polynomial(const BluePrint< Derived > &blueprint) {
00126             blueprint.implementApply(*this);
00127         }
00128         virtual ~Polynomial() {}
00129 
00130         /*********************
00131         ** Transform
00132         **********************/
00147         void shift_horizontal(const double &shift);
00148 //        void stretch_horizontal(double multiplier);
00149 
00150         /*********************
00151         ** Derivatives
00152         **********************/
00160         Polynomial<N-1> derivative() const {
00161             Polynomial<N-1> derivative_polynomial;
00162             typename Polynomial<N-1>::Coefficients &derivative_coefficients = derivative_polynomial.coefficients();
00163             for ( unsigned int i = 0; i < N; ++i ) {
00164                 derivative_coefficients[i] = (i+1)*coeff[i+1];
00165             }
00166             return derivative_polynomial;
00167         }
00176         double derivative(const double &x) const;
00185         double dderivative(const double &x) const;
00186 
00187         /*********************
00188         ** Accessors
00189         **********************/
00204         Coefficients& coefficients() { return coeff; };
00210         const Coefficients& coefficients() const { return coeff; };
00211 
00220         double operator ()(const double &x) const;
00221 
00234         template <typename OutputStream, unsigned int Degree>
00235         friend OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial);
00236 
00237     private:
00238         Coefficients coeff;
00239 };
00240 
00249 template <>
00250 class ECL_PUBLIC Polynomial<0> {
00251     public:
00252         /*********************
00253         ** Convenience
00254         **********************/
00255         typedef Array<double,1> Coefficients; 
00257         /*********************
00258         ** C&D
00259         **********************/
00266         Polynomial() : coeff(Coefficients::Constant(0.0)) {};
00267         virtual ~Polynomial() {};
00268 
00269         /*********************
00270         ** Transform
00271         **********************/
00278         void shift_horizontal(const double& /* shift */) {}; // Does nothing.
00279 
00280         /*********************
00281         ** Derivatives
00282         **********************/
00290         Polynomial<0> derivative() const {
00291             return Polynomial<0>();
00292         }
00300         double derivative(const double& /* x */ ) const {
00301             return 0.0;
00302         };
00310         double dderivative(const double& /* x */) const {
00311             return 0.0;
00312         };
00313 
00314         /*********************
00315         ** Accessors
00316         **********************/
00331         Coefficients& coefficients() { return coeff; };
00337         const Coefficients& coefficients() const { return coeff; };
00338 
00346         double operator ()(const double& /* x */) const {
00347             return coeff[0];
00348         };
00349 
00350     private:
00351         Coefficients coeff;
00352 };
00353 
00354 /*****************************************************************************
00355 ** Typedefs
00356 *****************************************************************************/
00357 
00358 typedef Polynomial<1> LinearFunction;            
00359 typedef Polynomial<2> QuadraticPolynomial;   
00360 typedef Polynomial<3> CubicPolynomial;       
00361 typedef Polynomial<5> QuinticPolynomial;     
00363 /*****************************************************************************
00364  * Implementation [Polynomial - Transform]
00365  ****************************************************************************/
00366 template <unsigned int N>
00367 void Polynomial<N>::shift_horizontal(const double &shift)
00368 {
00369     PascalsTriangle<N> pascals_triangle;
00370     typename PascalsTriangle<N>::const_iterator iter;
00371     double tmp;
00372 
00373     for ( unsigned int i = 0; i < N; ++i ) {
00374         tmp = -1*shift;
00375         int j = i+1;
00376         for ( iter = (pascals_triangle.begin(i)+1); iter != pascals_triangle.end(i); ++iter ) { // skip the first one
00377             coeff[i] += (*iter)*tmp*coeff[j];
00378             tmp *= (-1*shift);
00379             ++j;
00380         }
00381     }
00382 }
00383 /*****************************************************************************
00384  * Implementation [Polynomial - Access]
00385  ****************************************************************************/
00386 template <unsigned int N>
00387 double Polynomial<N>::operator()(const double &x) const
00388 {
00389     double tmp = x;
00390     double value = coeff[0];
00391     for ( unsigned int i = 1; i <= N; ++i ) {
00392          value += coeff[i]*tmp;
00393          tmp *= x;
00394     }
00395     return value;
00396 }
00397 template <unsigned int N>
00398 double Polynomial<N>::derivative(const double &x) const {
00399 
00400     if ( N > 0 ) {
00401         return derivative()(x);
00402     } else {
00403         return 0.0;
00404     }
00405 }
00406 
00407 template <unsigned int N>
00408 double Polynomial<N>::dderivative(const double &x) const {
00409 
00410     if ( N > 1 ) {
00411         return derivative().derivative()(x);
00412     } else {
00413         return 0.0;
00414     }
00415 }
00416 
00417 /*****************************************************************************
00418 ** Streaming Operator [Polynomial]
00419 *****************************************************************************/
00420 
00421 template <typename OutputStream, unsigned int Degree>
00422 OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial)
00423 {
00424         ecl_compile_time_concept_check(StreamConcept<OutputStream>);
00425 
00426         Format<double> format;
00427     format.precision(2);
00428 
00429     ostream << format(polynomial.coeff[0]);
00430     for (unsigned int i = 1; i <= Degree; ++i) {
00431         ostream << " + " << format(polynomial.coeff[i]) << "x^" << i;
00432     }
00433     ostream.flush();
00434 
00435     return ostream;
00436 }
00437 
00438 /*****************************************************************************
00439 ** BluePrints
00440 *****************************************************************************/
00441 
00442 namespace blueprints {
00443 
00444 /*****************************************************************************
00445 ** Interface [LinearInterpolation]
00446 *****************************************************************************/
00447 
00462 class LinearInterpolation : public ecl::BluePrint<LinearInterpolation> {
00463     public:
00467         typedef ecl::LinearFunction base_type;
00478         LinearInterpolation(const double x_i, const double y_i, const double x_f, const double y_f) :
00479                     x_initial(x_i),
00480                     y_initial(y_i),
00481                     x_final(x_f),
00482                     y_final(y_f)
00483         {}
00484 
00485         virtual ~LinearInterpolation() {}
00486 
00494         ecl::LinearFunction instantiate();
00495 
00502         void apply(ecl::LinearFunction& function) const;
00503 
00504     private:
00505         double x_initial, y_initial;
00506         double x_final, y_final;
00507 };
00508 
00509 /*****************************************************************************
00510 ** Interface [LinearPointSlope]
00511 *****************************************************************************/
00525 class LinearPointSlopeForm : public ecl::BluePrint<LinearPointSlopeForm> {
00526     public:
00530         typedef ecl::LinearFunction base_type;
00540         LinearPointSlopeForm(const double x_f, const double y_f, const double s) :
00541                     slope(s),
00542                     x_final(x_f),
00543                     y_final(y_f)
00544         {}
00545 
00546         virtual ~LinearPointSlopeForm() {}
00547 
00555         ecl::LinearFunction instantiate();
00556 
00563         void apply(ecl::LinearFunction& function) const;
00564 
00565     private:
00566         double slope;
00567         double x_final, y_final;
00568 };
00569 
00570 
00571 /*****************************************************************************
00572 ** Interface [CubicDerivativeInterpolation]
00573 *****************************************************************************/
00574 
00591 class CubicDerivativeInterpolation : public ecl::BluePrint<CubicDerivativeInterpolation> {
00592     public:
00596         typedef ecl::CubicPolynomial base_type;
00609         CubicDerivativeInterpolation(const double x_i, const double y_i, const double ydot_i,
00610                 const double x_f, const double y_f, const double ydot_f) :
00611                     x_initial(x_i),
00612                     y_initial(y_i),
00613                     ydot_initial(ydot_i),
00614                     x_final(x_f),
00615                     y_final(y_f),
00616                     ydot_final(ydot_f)
00617         {}
00618 
00619         virtual ~CubicDerivativeInterpolation() {}
00627         ecl::CubicPolynomial instantiate();
00628 
00635         void apply(ecl::CubicPolynomial& polynomial) const;
00636 
00637     private:
00638         double x_initial, y_initial, ydot_initial;
00639         double x_final, y_final, ydot_final;
00640 };
00641 /*****************************************************************************
00642 ** Interface [CubicSecondDerivativeInterpolation]
00643 *****************************************************************************/
00644 
00661 class CubicSecondDerivativeInterpolation : public ecl::BluePrint<CubicSecondDerivativeInterpolation>  {
00662     public:
00666         typedef ecl::CubicPolynomial base_type;
00679         CubicSecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i,
00680                 const double x_f, const double y_f, const double yddot_f) :
00681                     x_initial(x_i),
00682                     y_initial(y_i),
00683                     yddot_initial(yddot_i),
00684                     x_final(x_f),
00685                     y_final(y_f),
00686                     yddot_final(yddot_f)
00687         {}
00688 
00689         virtual ~CubicSecondDerivativeInterpolation() {}
00690 
00698         base_type instantiate();
00699 
00706         void apply(base_type& polynomial) const;
00707 
00708     private:
00709         double x_initial, y_initial, yddot_initial;
00710         double x_final, y_final, yddot_final;
00711 };
00712 
00713 /*****************************************************************************
00714 ** Interface [QuinticInterpolation]
00715 *****************************************************************************/
00716 
00735 class QuinticInterpolation : public ecl::BluePrint<QuinticInterpolation> {
00736     public:
00740         typedef ecl::QuinticPolynomial base_type;
00755         QuinticInterpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i,
00756                 const double x_f, const double y_f, const double ydot_f, const double yddot_f) :
00757                     x_initial(x_i),
00758                     y_initial(y_i),
00759                     ydot_initial(ydot_i),
00760                     yddot_initial(yddot_i),
00761                     x_final(x_f),
00762                     y_final(y_f),
00763                     ydot_final(ydot_f),
00764                     yddot_final(yddot_f)
00765         {}
00766 
00767         virtual ~QuinticInterpolation() {}
00768 
00776         ecl::QuinticPolynomial instantiate();
00777 
00784         void apply(ecl::QuinticPolynomial& polynomial) const;
00785 
00786     private:
00787         double x_initial, y_initial, ydot_initial, yddot_initial;
00788         double x_final, y_final, ydot_final, yddot_final;
00789 };
00790 
00791 }; // namespace blueprints
00792 
00793 /*****************************************************************************
00794 ** BluePrintFactory
00795 *****************************************************************************/
00796 
00797 using blueprints::LinearInterpolation;
00798 using blueprints::LinearPointSlopeForm;
00799 using blueprints::CubicDerivativeInterpolation;
00800 using blueprints::CubicSecondDerivativeInterpolation;
00801 using blueprints::QuinticInterpolation;
00802 
00814 template<unsigned int N>
00815 class BluePrintFactory< Polynomial<N> > {
00816 public:
00817         BluePrintFactory() {};
00818         ~BluePrintFactory() {};
00819 };
00820 
00835 template<>
00836 class BluePrintFactory< LinearFunction > {
00837 public:
00850         static LinearInterpolation Interpolation(const double x_i, const double y_i, const double x_f, const double y_f);
00859         static LinearPointSlopeForm PointSlopeForm(const double x_f, const double y_f, const double slope);
00860         virtual ~BluePrintFactory() {}
00861 };
00862 
00878 template<>
00879 class BluePrintFactory< CubicPolynomial > {
00880 public:
00898         static CubicDerivativeInterpolation DerivativeInterpolation(const double x_i, const double y_i, const double ydot_i,
00899                         const double x_f, const double y_f, const double ydot_f);
00900 
00918         static CubicSecondDerivativeInterpolation SecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i,
00919                         const double x_f, const double y_f, const double yddot_f);
00920 
00921         virtual ~BluePrintFactory() {}
00922 };
00923 
00938 template<>
00939 class BluePrintFactory< QuinticPolynomial > {
00940     public:
00960         static QuinticInterpolation Interpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i,
00961                 const double x_f, const double y_f, const double ydot_f, const double yddot_f);
00962 
00963         virtual ~BluePrintFactory() {}
00964 };
00965 
00966 
00967 /*****************************************************************************
00968 ** Interface [Maximum|Minimum][Polynomial]
00969 *****************************************************************************/
00978 template<>
00979 class ECL_PUBLIC Maximum< LinearFunction > {
00980 public:
00991         ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function);
00992         virtual ~Maximum() {}
00993 };
00994 
01002 template<>
01003 class ECL_PUBLIC Maximum<CubicPolynomial> {
01004 public:
01015         ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic);
01016         virtual ~Maximum() {}
01017 };
01018 
01027 template<>
01028 class ECL_PUBLIC Minimum< LinearFunction > {
01029 public:
01040         ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function);
01041         virtual ~Minimum() {}
01042 };
01043 
01051 template<>
01052 class ECL_PUBLIC Minimum<CubicPolynomial> {
01053 public:
01064         ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic);
01065         virtual ~Minimum() {}
01066 };
01067 
01068 /*****************************************************************************
01069 ** Interface [Intersection][LinearFunction]
01070 *****************************************************************************/
01076 template<>
01077 class ECL_PUBLIC Intersection< LinearFunction > {
01078 public:
01079         Intersection() : last_operation_failed(false) {}
01080         virtual ~Intersection() {}
01090         ECL_PUBLIC CartesianPoint2d operator()(const LinearFunction& f, const LinearFunction& g) ecl_throw_decl(StandardException);
01091 
01098         bool fail() const { return last_operation_failed; }
01099 
01100 private:
01101         bool last_operation_failed;
01102 };
01103 
01104 /*****************************************************************************
01105 ** Interface [Synthetic Division]
01106 *****************************************************************************/
01112 template<>
01113 class ECL_PUBLIC Division<QuadraticPolynomial> {
01114 public:
01115         Division() {};
01116         virtual ~Division() {};
01124         ECL_PUBLIC LinearFunction operator()(const QuadraticPolynomial &p, const double &factor, double &remainder);
01125 };
01126 
01132 template<>
01133 class ECL_PUBLIC Division<CubicPolynomial> {
01134 public:
01135         Division() {};
01136         virtual ~Division() {};
01144         ECL_PUBLIC QuadraticPolynomial operator()(const CubicPolynomial &p, const double &factor, double &remainder);
01145 };
01146 
01147 /*****************************************************************************
01148 ** Interface [Roots]
01149 *****************************************************************************/
01155 template<>
01156 class ECL_PUBLIC Roots<LinearFunction> {
01157 public:
01158         Roots() {}
01159         virtual ~Roots() {}
01166         ECL_PUBLIC Array<double> operator()(const LinearFunction& p);
01167 };
01168 
01174 template<>
01175 class ECL_PUBLIC Roots<QuadraticPolynomial> {
01176 public:
01177         Roots() {}
01178         virtual ~Roots() {}
01185         ECL_PUBLIC Array<double> operator()(const QuadraticPolynomial& p);
01186 };
01192 template<>
01193 class ECL_PUBLIC Roots<CubicPolynomial> {
01194 public:
01195         Roots() {}
01196         virtual ~Roots() {}
01203         ECL_PUBLIC Array<double> operator()(const CubicPolynomial& p);
01204 };
01205 
01206 /*****************************************************************************
01207 ** Interfaces [FunctionMath]
01208 *****************************************************************************/
01220 template <>
01221 class ECL_PUBLIC FunctionMath<LinearFunction> {
01222 public:
01223         FunctionMath() {}; 
01224         virtual ~FunctionMath() {};
01230         static CartesianPoint2d Intersection(const LinearFunction &f, const LinearFunction &g) ecl_throw_decl(StandardException) {
01231                 CartesianPoint2d point;
01232                 ecl_try {
01233                         ecl::Intersection< LinearFunction > intersection;
01234                         point = intersection(f,g);
01235                 } ecl_catch( const StandardException &e ) {
01236                         ecl_throw(StandardException(LOC,e));
01237                 }
01238                 return point;
01239         }
01245         static Array<double> Roots(const LinearFunction &function) {
01246                 return ecl::Roots<LinearFunction>()(function);
01247         }
01253         static double Minimum(const double& x_begin, const double& x_end, const LinearFunction &function) {
01254                 return ecl::Minimum<LinearFunction>()(x_begin, x_end, function);
01255         }
01261         static double Maximum(const double& x_begin, const double& x_end, const LinearFunction &function) {
01262                 return ecl::Maximum<LinearFunction>()(x_begin, x_end, function);
01263         }
01264 };
01272 template <>
01273 class ECL_PUBLIC FunctionMath<QuadraticPolynomial> {
01274 public:
01275         FunctionMath() {}; 
01276         virtual ~FunctionMath() {};
01282         static Array<double> Roots(const QuadraticPolynomial &p) {
01283                 return ecl::Roots<QuadraticPolynomial>()(p);
01284         }
01288         static LinearFunction Division(const QuadraticPolynomial &p, const double &factor, double &remainder) {
01289                 LinearFunction f(ecl::Division<QuadraticPolynomial>()(p,factor,remainder));
01290                 return f;
01291         }
01292 };
01293 
01301 template <>
01302 class ECL_PUBLIC FunctionMath<CubicPolynomial> {
01303 public:
01304         FunctionMath() {}; 
01305         virtual ~FunctionMath() {};
01311         static Array<double> Roots(const CubicPolynomial &p) {
01312                 return ecl::Roots<CubicPolynomial>()(p);
01313         }
01317         static QuadraticPolynomial Division(const CubicPolynomial &p, const double &factor, double &remainder) {
01318                 QuadraticPolynomial q(ecl::Division<CubicPolynomial>()(p,factor,remainder));
01319                 return q;
01320         }
01326         static double Minimum(const double& x_begin, const double& x_end, const CubicPolynomial &function) {
01327                 return ecl::Minimum<CubicPolynomial>()(x_begin, x_end, function);
01328         }
01334         static double Maximum(const double& x_begin, const double& x_end, const CubicPolynomial &function) {
01335                 return ecl::Maximum<CubicPolynomial>()(x_begin, x_end, function);
01336         }
01337 };
01338 
01339 }; // namespace ecl
01340 
01341 #endif /*ECL_GEOMETRY_POLYNOMIALS_HPP_*/


ecl_geometry
Author(s): Daniel Stonier (d.stonier@gmail.com)
autogenerated on Thu Jan 2 2014 11:13:11