/// @addtogroup dynsys
/// @{

/////////////////////////////////////////////////////////////////////////////
/// @file BasicC2Taylor.h
///
/// @author Daniel Wilczak
/////////////////////////////////////////////////////////////////////////////

// Copyright (C) 2000-2012 by the CAPD Group.
//
// This file constitutes a part of the CAPD library,
// distributed under the terms of the GNU General Public License.
// Consult  http://capd.ii.uj.edu.pl/ for details.

#ifndef _CAPD_DYNSYS_BASICC2TAYLOR_H_
#define _CAPD_DYNSYS_BASICC2TAYLOR_H_

#include <string>
#include "capd/diffAlgebra/BasicC2Curve.h"
#include "capd/diffAlgebra/C2Curve.h"
#include "capd/dynsys/BasicTaylor.h"

namespace capd{
namespace dynsys{

template <
  typename MapT,
  typename StepControlT = capd::dynsys::DLastTermsStepControl,
  typename CurveT = capd::diffAlgebra::C2Curve< capd::diffAlgebra::BasicC2Curve<typename MapT::MatrixType> >
>
class BasicC2Taylor : public virtual BasicTaylor<MapT, StepControlT, CurveT>{
public:
  typedef MapT MapType;
  typedef StepControlT StepControlType;
  typedef typename MapT::FunctionType FunctionType;
  typedef typename MapType::MatrixType MatrixType;
  typedef typename MatrixType::RowVectorType VectorType;
  typedef typename MatrixType::ScalarType ScalarType;
  typedef typename MapType::HessianType HessianType;
  typedef BasicTaylor<MapT, StepControlT, CurveT> BaseTaylor;
  typedef CurveT SolutionCurve;
  typedef typename MatrixType::size_type size_type;

  BasicC2Taylor(MapType& vectorField, size_type order, const StepControlT& stepControl = StepControlT());

  /// Computes next point on the trajectory,
  /// first and second order derivatives with respect to initial conditions.
  /// Initial conditions for variational equations are Id and zero, respectively.
  VectorType operator()(VectorType, MatrixType&, HessianType&);

  /// Computes next point on the trajectory of a nonautonomous system,
  /// first and second order derivatives with respect to initial conditions.
  /// Initial conditions for variational equations are Id and zero, respectively.
  VectorType operator()(ScalarType& t, const VectorType&, MatrixType&, HessianType&);


  /// The routine computes next point, derivatives and second order derivatives of a flow.
  /// Initial conditions for variational equations are V and H, respectively.
  VectorType operator()(VectorType, const MatrixType& V, const HessianType& H, MatrixType&, HessianType&);

  /// The routine computes next point, derivatives and second order derivatives of a nonautonomous flow.
  /// Initial conditions for variational equations are V and H, respectively.
  VectorType operator()(ScalarType& t, const VectorType& x, const MatrixType& V, const HessianType& H, MatrixType&, HessianType&);

  /// it computes image of the set (in given representation) using set.move function, see capd/dynsys/Move.h for details
  template <typename JetT>
  void operator()(JetT& jet){
    C2JetMove<BasicC2Taylor,JetT>::move(jet,*this);
  }

  using BaseTaylor::getVectorField;
  using BaseTaylor::dimension;
  using BaseTaylor::getCurve;
  using BaseTaylor::setStep;
  using BaseTaylor::getStep;
  using BaseTaylor::getOrder;
  using BaseTaylor::setOrder;
  using BaseTaylor::setCurrentTime;
  using BaseTaylor::getCurrentTime;
  using BaseTaylor::operator();

protected:
  BasicC2Taylor(const BasicC2Taylor& t) : BaseTaylor(t){}
  void operator=(const BasicC2Taylor&){}

  using BaseTaylor::m_vField;
  using BaseTaylor::m_step;

  void sumTaylorSeries(
      VectorType& v,
      MatrixType& der,
      HessianType& hessian,
      VectorType* coeff,
      MatrixType* matrixCoeff,
      HessianType* hessianCoeff,
      size_type order
    );
}; // the end of class BasicC2Taylor


// ------------------ inline definitions -------------

template <typename MapType, typename StepControlType,typename CurveT>
inline typename BasicC2Taylor<MapType, StepControlType,CurveT>::VectorType
BasicC2Taylor<MapType, StepControlType,CurveT>::operator()(ScalarType& t, const VectorType &v, MatrixType& der, HessianType& coeff)
{
  this->setCurrentTime(t);
  VectorType r = this->operator()(v,der,coeff);
  t += this->getStep();
  return r;
}

//###########################################################//

template <typename MapType, typename StepControlType,typename CurveT>
inline typename BasicC2Taylor<MapType,StepControlType,CurveT>::VectorType
BasicC2Taylor<MapType,StepControlType,CurveT>::operator()(
      ScalarType& t, const VectorType& x, const MatrixType& D, const HessianType& H,
      MatrixType& out_der, HessianType& out_hessian
    )
{
  this->setCurrentTime(t);
  VectorType r = this->operator()(x,D,H,out_der,out_hessian);
  t += this->getStep();
  return r;
}

}} // the end of the namespace capd::dynsys

#endif // _CAPD_DYNSYS_BASICC2TAYLOR_H_

/// @}
