/* Fesslix - Stochastic Analysis
 * Copyright (C) 2010-2016 Wolfgang Betz
 *
 * Fesslix is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fesslix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Fesslix.  If not, see <http://www.gnu.org/licenses/>. 
 */

#ifndef fesslix_flxfem_legendrePolyH_H
#define fesslix_flxfem_legendrePolyH_H

#include "flxfem_legendrePolyH_hard.h"

#include <vector>


class flxLegendrePoly {
  private:
    size_t size;
    std::vector<pdouble*> LPvec;
  public:
    flxLegendrePoly();
    ~flxLegendrePoly();
    
    void resize(size_t new_size);
    tdouble* get_hierarchic(size_t nth) const;
};


class FLXFEM_EXPORT flxLegendrePolyH {
  private:
    /**
    * @brief the number of initizalized polynomials
    */
    size_t size;
    /**
    * @brief the Legendre polynomials
    */
    flxLegendrePoly LPbase;
    /**
    * @brief the hierarchic Legendre polynomials
    */
    std::vector<tdouble*> LPHvec;
    
    void code_Pn_single(const tuint i, std::ostream& os);
    void code_dPn_single(const tuint i, std::ostream& os);
  public:
    flxLegendrePolyH();
    ~flxLegendrePolyH();
    
    /**
    * @brief makes sure that enough polynomials are initialized
    */
    void resize(size_t new_size);
    /**
    * @brief calculates P_n(x)
    * You have to make sure beforehand that enough polynomials ase initialized!!!
    */
    const tdouble comp_Pn(const tuint nth, const tdouble& x);
    /**
    * @brief calculates d/dx P_n(x)
    * @param n starts from 0
    * You have to make sure beforehand that enough polynomials ase initialized!!!
    */
    const tdouble comp_dPn(const tuint nth, const tdouble& x);
    /**
    * @brief prints P_n
    * You have to make sure beforehand that enough polynomials ase initialized!!!
    */
    void print_Pn(const tuint nth, std::ostream& os);
    /**
    * @brief code P_n
    */
    void code_Pn(const tuint uptoN, std::ostream& os);
    /**
    * @brief code dP_n
    */
    void code_dPn(const tuint uptoN, std::ostream& os);
};

/*
 * Generation rule fo the Gegenbauer polynomials (with alpha=2.5)
 * 
 * phi_0 = 1
 * phi_1 = 5*x
 * phi_n = 1/n*( 2*x*(n+1.5)*phi_{n-1}(x) - (n+3)*phi_{n-2}(x) );
 * 
 */

class FLXFEM_EXPORT flxGegenbauerPolyH {
  private:
    /**
    * @brief the number of initizalized polynomials
    */
    size_t size;
    /**
    * @brief the Gegenbauer polynomials (for alpha=2.5)
    */
    std::vector<pdouble*> GBPvec;
    
    void code_GBP_single(const tuint i, std::ostream& os);
    pdouble* get_hierarchic(size_t nth) const;
  public:
    flxGegenbauerPolyH(size_t new_size);
    ~flxGegenbauerPolyH();

    /**
    * @brief generate code for the hierarchic Gegenbauer polynomials
    */
    void code_hGBP(const tuint uptoN, std::ostream& os);
};






#endif // fesslix_flxfem_legendrePolyH_H

