/* -*- mode: C++ -*- */
//////////////////////////////////////////////////////////////////////////////
// FILE   : BaseC2.tol
// PURPOSE: Defines Class @BaseC2
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
Text _.autodoc.member.BaseC2 = 
"Base of K mutivariate arbitrary linearly independent functions R^n -> R of " 
"class C2, ie, continuous and having first and second partial derivatives "
"that are also continuous. For efficience reasons the base evaluates over "
"massive arrays of points stored as rows in a matrix.\n"
"Although all methods have a default definition this is an abstract class "
"due to there are mutual interdependence between pairs of private methods "
"_build.*.v and _build.*.m. At least a group of these methods must be "
"redefined by inherited classes. Also is possible to redefine public "
"access methods in order to not use private ones.";
Class @BaseC2
//////////////////////////////////////////////////////////////////////////////
{
  //Dimension of domain vectorial space
  Real _.n;
  //Dimension of the base
  Real _.K;

  ////////////////////////////////////////////////////////////////////////////
  //Private calculation methods.
  ////////////////////////////////////////////////////////////////////////////

  //Evaluates the k-th basic function for an 
  //array of points given as the rows of a matrix 
  VMatrix _build.function.v(Real k, VMatrix X)
  {
  //WriteLn("TRACE @BaseC2::_build.function.v");
    SubCol( _build.function.m(X),[[k]])
  };
  //Evaluates the first partial derivative of k-th basic function for an  
  //array of points given as the rows of a matrix 
  VMatrix _build.partial.derivative.1.v(Real k, VMatrix X, Real i)
  {
  //WriteLn("TRACE @BaseC2::_build.partial.derivative.1.v");
    SubCol( _build.partial.derivative.1.m(X,i),[[k]])
  };
  //Evaluates the second partial derivative of k-th basic function for an  
  //array of points given as the rows of a matrix 
  VMatrix _build.partial.derivative.2.v(Real k, VMatrix X, Real i, Real j)
  {
  //WriteLn("TRACE @BaseC2::_build.partial.derivative.2.v");
    SubCol( _build.partial.derivative.2.m(X,i,j),[[k]])
  };

  //Evaluates all basic functions, one in each returned column, for an 
  //array of points given as the rows of a matrix 
  VMatrix _build.function.m(VMatrix X)
  {
  //WriteLn("TRACE @BaseC2::_build.function.m");
    Group("ConcatColumns", For(1,_.K,VMatrix(Real k)
    {
      _build.function.v(k, X)
    }))
  };
  //Evaluates the first partial derivative of all basic functions, one in 
  //each returned column, for an  array of points given as the rows of a 
  //matrix 
  VMatrix _build.partial.derivative.1.m(VMatrix X, Real i)
  {
  //WriteLn("TRACE @BaseC2::_build.partial.derivative.1.m");
    Group("ConcatColumns", For(1,_.K,VMatrix(Real k)
    {
      _build.partial.derivative.1.v(k, X, i)
    }))
  };
  //Evaluates the second partial derivative of all basic functions, one in 
  //each returned column, for an  array of points given as the rows of a 
  //matrix 
  VMatrix _build.partial.derivative.2.m(VMatrix X, Real i, Real j)
  {
  //WriteLn("TRACE @BaseC2::_build.partial.derivative.2.m");
    Group("ConcatColumns", For(1,_.K,VMatrix(Real k)
    {
      _build.partial.derivative.2.v(k, X, i, j)
    }))
  };
  //Some bases are more efficient using cache
  Real _build.cache(VMatrix X, Real order) { False };

  ////////////////////////////////////////////////////////////////////////////
  //Public access methods call by defect to private ones
  ////////////////////////////////////////////////////////////////////////////

  //Evaluates the k-th basic function for an 
  //array of points given as the rows of a matrix 
  VMatrix function.v(Real k, VMatrix X)
  { 
  //WriteLn("TRACE @BaseC2::function.v");
    _build.function.v(k, X) 
  };
  //Evaluates the first partial derivative of k-th basic function for an  
  //array of points given as the rows of a matrix 
  VMatrix partial.derivative.1.v(Real k, VMatrix X, Real i)
  { 
  //WriteLn("TRACE @BaseC2::partial.derivative.1.v");
    _build.partial.derivative.1.v(k, X, i) 
  };
  //Evaluates the second partial derivative of k-th basic function for an  
  //array of points given as the rows of a matrix 
  VMatrix partial.derivative.2.v(Real k, VMatrix X, Real i, Real j)
  { 
  //WriteLn("TRACE @BaseC2::partial.derivative.2.v");
    _build.partial.derivative.2.v(k, X, i, j) 
  };

  //Evaluates all basic functions, one in each returned column, for an 
  //array of points given as the rows of a matrix 
  VMatrix function.m(VMatrix X)
  { 
  //WriteLn("TRACE @BaseC2::function.m");
    _build.function.m(X) 
  };
  //Evaluates the first partial derivative of all basic functions, one in 
  //each returned column, for an  array of points given as the rows of a 
  //matrix 
  VMatrix partial.derivative.1.m(VMatrix X, Real i)
  {
  //WriteLn("TRACE @BaseC2::partial.derivative.1.m");
    _build.partial.derivative.1.m(X, i) 
  };
  //Evaluates the second partial derivative of all basic functions, one in 
  //each returned column, for an  array of points given as the rows of a 
  //matrix 
  VMatrix partial.derivative.2.m(VMatrix X, Real i, Real j)
  { 
  //WriteLn("TRACE @BaseC2::partial.derivative.2.m");
    _build.partial.derivative.2.m(X, i, j) 
  };

  //Some bases are more efficient using cache
  Real upgrade.cache(VMatrix X, Real order) 
  { _build.cache(X,order) }


};

