#include "AdvFuncComb.hh"
#include <cmath>

const std::string AdvFuncComb::className=std::string("AdvFuncComb");

AdvFuncComb::AdvFuncComb() {
    std::string memberName = std::string("AdvFuncComb()");
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}
/*
*/

AdvFuncComb::AdvFuncComb(const std::vector<AdvFuncBase*> funcList) {
    setFuncList(funcList);
}

/**
 *  constructor
 */

AdvFuncComb::AdvFuncComb(const std::vector<AdvFuncBase*> funcList,const std::string lk, const std::vector<Double> linklist) {
/*
    std::cout << "koko-set-FC, "<< std::endl;
    for (UInt4 i=0; i<funcList.size(); ++i) {
        std::cout << "koko-set-FC, "<< funcList.at(i)->getSymbol() << std::endl;
           }
    for (UInt4 i=0; i<linklist.size(); ++i) {
        cout << "koko-set-LK, "<< linklist.at(i) << endl;
           }
*/
    setFuncList(funcList);
    setLinkList(linklist);
}

/*
*/

AdvFuncComb::AdvFuncComb(const std::string expr) {
    std::string memberName = std::string("AdvFuncComb(const std::string)");
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    setFuncList(expr);
    //setParamList();
    //setErrorList();
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}

/**
 *  constructor
 *
 *  \param[in] funcList  a list of pointers to functionas
 *  \param[in] paramList a list of parameters for the functions
 */
AdvFuncComb::AdvFuncComb(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> paramList) {
    std::string memberName = std::string("AdvFuncComb(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> paramList)");
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");

    set(funcList, paramList);

    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}
/*
*/

AdvFuncComb::AdvFuncComb(const std::string expr, PyObject *paramList) {
    setFuncList(expr);
    setParamList(paramList);
    setErrorList();
}

/**
 *  constructor
 *
 *  \param[in] funcList  a list of pointers to functionas
 *  \param[in] paramList a list of parameters for the functions
 *  \param[in] covar     the covariance matrix for the parameters
 */
AdvFuncComb::AdvFuncComb(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> paramList, const std::vector< std::vector<Double> > &covar) {
    set(funcList, paramList, covar);
}

/**
 *  constructor
 *
 *  \param[in] funcList  a list of pointers to functionas
 *  \param[in] paramList a list of parameters for the functions
 *  \param[in] errorList a list of parameter errors for the parameters
 */
AdvFuncComb::AdvFuncComb(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> paramList, const std::vector<Double> errorList) {
    set(funcList, paramList, errorList);
}

AdvFuncComb::AdvFuncComb(const std::string expr, PyObject *paramList, PyObject *errorList) {
    setFuncList(expr);
    setParamList(paramList);
    setErrorList(errorList);
}

/**
 *  destructor
 */
AdvFuncComb::~AdvFuncComb() {
    std::string memberName = std::string("~AdvFuncComb");
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    DebugMessage(className, memberName, __FILE__, __LINE__, "size of param array: %d\n", this->paramArray.size());
    for (UInt4 i=0; i<this->paramArray.size(); ++i) {
        this->paramArray.at(i).clear();
    }
    paramArray.clear();
    DebugMessage(className, memberName, __FILE__, __LINE__, "size of error array: %d\n", this->errorArray.size());
    for (UInt4 i=0; i<this->errorArray.size(); ++i) {
        this->errorArray.at(i).clear();
    }
    errorArray.clear();
    DebugMessage(className, memberName, __FILE__, __LINE__, "size of func list: %d\n", this->funcList.size());
    this->funcList.erase(this->funcList.begin(), this->funcList.end());
    this->funcList.clear();
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}

void AdvFuncComb::set(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> paramList) {
    std::string memberName=std::string("set(const std::vector<AdvFuncBase*>, const std::vector<Double> &, std::vector< std::vector<Double> > &)");
    setFuncList(funcList);
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of functions: %d\n", this->funcList.size());
    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters: %d\n", getNumberOfRequiredParam());
    if (! checkNumberOfParam(paramList)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of parameters dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of given parameters    %d\n", paramList.size());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters %d\n", getNumberOfRequiredParam());
        return ;
    }
    setParamList(paramList);
    setErrorList();
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}

/**
 *  set
 *
 *  \param[in] funcList  a list of pointers to functionas
 *  \param[in] paramList a list of parameters for the functions
 *  \param[in] covar     the covariance matrix for the parameters
 */
void AdvFuncComb::set(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> &paramList, const std::vector< std::vector<Double> > &covar) {
    std::string memberName=std::string("set(const std::vector<AdvFuncBase*>, const std::vector<Double> &, std::vector< std::vector<Double> > &)");

    setFuncList(funcList);
    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of functions: %d\n", this->funcList.size());
    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters: %d\n", getNumberOfRequiredParam());
    if (! checkNumberOfParam(paramList)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of parameters dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of given parameters    %d\n", paramList.size());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters %d\n", getNumberOfRequiredParam());
        return ;
    }
    if ( ! checkNumberOfParam(covar)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the row or column size of parameters dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the row size of the given covariance matix    %d\n", covar.size());
        for (std::vector< std::vector<Double> >::const_iterator i=covar.begin(); i != covar.end(); ++i) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the column size of the given parameters" );
            std::cerr << " " << (*i).size();
        }
        std::cerr << std::endl;
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters %d\n", getNumberOfRequiredParam());
        return ;
    }
    setParamList(paramList);
    setErrorList(covar);
}

/**
 *  set
 *
 *  \param[in] funcList  a list of pointers to functionas
 *  \param[in] paramList a list of parameters for the functions
 *  \param[in] errorList a list of parameter errors for the parameters
 */
void AdvFuncComb::set(const std::vector<AdvFuncBase*> funcList, const std::vector<Double> &paramList, const std::vector<Double> &errorList) {
    std::string memberName=std::string("set(const std::vector<AdvFuncBase*>, const std::vector<Double>, std::vector<Double> &)");

    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of functions: %d\n", this->funcList.size());
    DebugMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters: %d\n", getNumberOfRequiredParam());
    setFuncList(funcList);
    if (! checkNumberOfParam(paramList)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of parameters dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of given parameters    %d\n", paramList.size());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters %d\n", getNumberOfRequiredParam());
        return ;
    }
    if (! checkNumberOfParam(errorList)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of parameter errors dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of given parameter errors    %d\n", errorList.size());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameter errors %d\n", getNumberOfRequiredParam());
        return ;
    }
    setParamList(paramList);
    setErrorList(errorList);
}

void AdvFuncComb::set(const std::string expr, PyObject *paramList, PyObject *errorList) {
    setFuncList(expr);
    setParamList(paramList);
    setParamList(errorList);
}

void AdvFuncComb::set(const std::vector<Double> &paramList)  {
    std::string memberName=std::string("set(const std::vector<Double>&)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setParamList(paramList);
}

void AdvFuncComb::set(const std::vector<Double> &paramList, const std::vector<Double> &errorList)  {
    std::string memberName=std::string("set(const std::vector<Double>&, const std::vector<Double>&)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setParamList(paramList);
    setErrorList(errorList);
}

void AdvFuncComb::set( PyObject *paramList)  {
    std::string memberName=std::string("set(const PyObject&*)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setParamList(paramList);
}

void AdvFuncComb::set(PyObject *paramList, PyObject *errorList)  {
    std::string memberName=std::string("set(PyObject&*, PyObject*)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setParamList(paramList);
    setErrorList(errorList);

}

void AdvFuncComb::setError(const std::vector<Double> &errorList)  {
    std::string memberName=std::string("setError(const std::vector<Double>&)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    if (this->paramArray.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setErrorList(errorList);
}

void AdvFuncComb::setError(PyObject *errorList)  {
    std::string memberName=std::string("setError(PyObject*)");

    if (this->funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    if (this->paramArray.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    setErrorList(errorList);
}

/**
 *  set a list of primitive functions
 *
 *  \paam[in] funcList a list of build-in functions
 */
void AdvFuncComb::setFuncList(const std::vector<AdvFuncBase*> funcList)  {
    std::string memberName=std::string("setFuncList(const std::vector<AdvFuncBase*>)");

    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    if (funcList.empty()) {
        throw std::invalid_argument(className+": "+memberName+": " + "empty list\n");
    }
    this->funcList=funcList;
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}


/**
 *
 */
void AdvFuncComb::setFuncList(const std::string expr) {
    AdvFuncParser *parser = new AdvFuncParser(expr);

    std::vector<AdvFuncBase*> flist = parser->parse();
    if (! flist.empty()) {
        setFuncList(flist);
    }

}
/**
 *
 */
void AdvFuncComb::setLinkList(const std::vector<Double> linklist){
/*
    std::cout << "koko-set-LKB"<<std::endl;

    for (UInt4 i=0; i<linklist.size(); ++i) {
        cout << "koko-set-LKB, "<< linklist.at(i) << endl;
           }
*/
    if (! linklist.empty()) {
    this->linkList=linklist;
    }
}


/*
void AdvFuncComb::setParamList() {
    //this->paramArray=*(new std::vector< std::vector<Double> >());
    //for (std::vector<AdvFuncBase*>::const_iterator fp=this->funcList.begin(); fp != this->funcList.end(); ++fp) {
    //    this->paramArray.push_back(*(new std::vector<Double>((*fp)->getNumberOfParam(), 0.0)));
    //}
}
*/

/**
 *  set a list of paameters for build-in functins
 *
 *  \param[in] paramList a list of parameters for build-in functions
 */
void AdvFuncComb::setParamList(const std::vector<Double> &paramList) {
    std::string memberName=std::string("setParamList(const std::vector<Double> &)");

    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    if ( this->funcList.empty() ) {
        errorMessage(className, memberName, __FILE__, __LINE__, "no function list given\n");
        return;
    } else if ( paramList.empty()) {
        errorMessage(className, memberName, __FILE__, __LINE__, "no parameter value given\n");
        return;
    } else if (! checkNumberOfParam(paramList)) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of parameters dose not agree with that the function requires\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of given parameters    %d\n", paramList.size());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of required parameters %d\n", getNumberOfRequiredParam());
        return ;
    } else {
        this->paramArray=vectorToArray(paramList);
    }
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
}

void AdvFuncComb::setParamList(PyObject *PyList) {
    std::string memberName = std::string("setParamList(PyObject *)");
    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "enter");
    CppToPython *cp = new CppToPython();

    std::vector<Double> vec = cp->ListToDoubleVector(PyList);
    this->paramArray=vectorToArray(vec);
    delete cp;
    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "exit");
}

/**
 * set lists of paramete errors
 */
void AdvFuncComb::setErrorList() {
    std::string memberName = std::string("setErrorList()");

    if ( this->funcList.size() != this->paramArray.size() ) {
        errorMessage(className, memberName, __FILE__, __LINE__, "parameters is not consistent with functions\n");
        return;
    }

    //this->errorArray=*(new std::vector< std::vector<Double> >(this->funcList.size(), *(new std::vector<Double>)));
    //for (UInt4 i=0; this->funcList.size(); ++i) {
    //    this->errorArray.at(i).assign(this->funcList.at(i)->getNumberOfParam(), 0.0);
    //}
    this->errorArray=*(new std::vector< std::vector<Double> >());
    for(std::vector<AdvFuncBase*>::const_iterator fp=this->funcList.begin(); fp != this->funcList.end(); ++fp) {
        this->errorArray.push_back(*(new std::vector<Double>((*fp)->getNumberOfParam(), 0.0)));
    }
}

/**
 *  set lists of parameter errors
 *
 *  \param[in] errorList a list of error of parameters for build-in functions
 */
void AdvFuncComb::setErrorList(const std::vector<Double> &errorList) {
    this->errorArray=vectorToArray(errorList);
}

void AdvFuncComb::setErrorList(PyObject *list) {

    CppToPython *cp = new CppToPython();
    std::vector<Double> vec = cp->ListToDoubleVector(list);
    this->errorArray=vectorToArray(vec);
    delete cp;
}

/**
 *  set lists of paramete errors from the covariance matrix
 *
 *  \param[in] covar the covariance matrix for parameters for build-in functions
 */
void AdvFuncComb::setErrorList(const std::vector< std::vector<Double> > &covar) {
    std::string memberName=std::string("setErrorList(const std::vector< std::vector<Double> >&)");

    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "enter");
    DebugMessage(className, memberName, __FILE__, __LINE__, "size of covar %u*%u\n", covar.size(), covar.at(0).size());
    std::vector<Double> errorList = *(new std::vector<Double>());
    for (UInt4 i=0; i<covar.size(); ++i) {
        errorList.push_back(sqrt(covar.at(i).at(i)));
        DebugMessage(className, memberName, __FILE__, __LINE__, "%u error=%23.15e\n", i, errorList.at(i));
    }
    this->errorArray=vectorToArray(errorList);
    errorList.clear();
    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "exit");
}

/**
 *
 */
void AdvFuncComb::add(AdvFuncBase *func, const std::vector<Double> &paramList) {
    std::string memberName=std::string("add(AdvFuncBase *, std::vector<Double>&)");

    if ( func->getNumberOfParam() > paramList.size() ) {
        errorMessage(className, memberName, __FILE__, __LINE__, "the function and paremters not registered.\n");
        errorMessage(className, memberName, __FILE__, __LINE__, "the given function requires more pramters than specified those.\n");
        //errorMessage(className, memberName, "%s requires %u parameters\n", func->getName(), func->getNumberOfParam());
        errorMessage(className, memberName, __FILE__, __LINE__, "the number of specified paramters: %d\n", paramList.size());
    } else {
        this->funcList.push_back(func);
        std::vector<Double>::const_iterator b=paramList.begin();
        std::vector<Double>::const_iterator e=paramList.begin();
        for (UInt4 i=0; i<func->getNumberOfParam(); ++i) {
            ++e;
        }
        this->paramArray.push_back(*(new std::vector<Double>(b, e)));
        this->errorArray.push_back(*(new std::vector<Double>(func->getNumberOfParam(), 0.0)));
    }
}

/*
void AdvFuncComb::add(std::string &funcName, PyObject *paramList) {
    std::string memberName=std::string("add(std::string, PyObject*)");

    FuncParser parser = new FuncParser(funcName);
    std::vector<AdvFuncBase*> addList = parser.parse();
    if ( ! addList.empty() ) {
        CppToPython *cp = new CppToPython();
        for (std::vector<AdvFuncBase*>::iterator f=addList.begin(); f != addList.end(); ++i) {
        }
    }
}
*/

/**
 *
 */
void AdvFuncComb::add(AdvFuncBase *func, const std::vector<Double> &paramList, const std::vector<Double> &errorList) {
    std::string memberName=std::string("add(AdvFuncBase *, const std::vector<Double>&, const std::vector<Double>&)");

    this->add(func, paramList);
    if ( (func->getNumberOfParam() > errorList.size()) || (paramList.size() > errorList.size()) ) {
        errorMessage(className, memberName, __FILE__, __LINE__, "a list of parameter errors not registered.\n");
        //errorMessage(className, memberName, "%s requires %u parameter errors\n", func->getName(), func->getNumberOfParam());
        errorMessage(className, memberName, __FILE__, __LINE__, "%u paramter errors given.\n", errorList.size());
    } else {
        std::vector<Double>::const_iterator b=errorList.begin();
        std::vector<Double>::const_iterator e=errorList.begin();
        for (UInt4 i=0; i<func->getNumberOfParam(); ++i) {
            ++e;
        }
        this->errorArray.at(this->errorArray.size()-1).assign(b, e);
    }
}

/**
 *
 */
void AdvFuncComb::erase(const UInt4 i) {
    std::string memberName=std::string("erase(const UInt4)");

    if ( i < this->funcList.size() ) {
        this->errorArray.at(i).clear();
        this->paramArray.at(i).clear();

        std::vector<AdvFuncBase*>::iterator f=this->funcList.begin();
        std::vector< std::vector<Double> >::iterator p=this->paramArray.begin();
        std::vector< std::vector<Double> >::iterator e=this->errorArray.begin();
        for (UInt4 j=0; j<i; ++j) {
            ++f;
            ++p;
            ++e;
        }
        this->errorArray.erase(e);
        this->paramArray.erase(p);
        this->funcList.erase(f);
    }
}


/**
 *  compere the number of the given parameters to the number of parameters which functions requires.
 *
 *  \param[in] list  a list of parameters
 *  \retval    true  if the number of the given parameters is equal to the number of parameters that functions requires.
 */
Bool AdvFuncComb::checkNumberOfParam(const std::vector<Double> &list) const {
    return list.size() == getNumberOfRequiredParam();
}

/**
 *  comare the size of covariance matrix for parameters to the number of parameters which functions requires.
 *
 *  \param[in] covar the covariance matirx for prameters
 *  \retval    true  if the size of the given matrix is equal to the number of parameters that functions requires.
 */
Bool AdvFuncComb::checkNumberOfParam(const std::vector< std::vector<Double> > &covar) const {

    Bool retval = (covar.size() == getNumberOfRequiredParam());
    for (UInt4 i=0; i< covar.size(); ++i) {
        retval = retval && (covar.at(i).size() == getNumberOfRequiredParam());
    }
    return retval;
}

/**
 *  \returen the number of parameters that the functions require
 */
UInt4 AdvFuncComb::getNumberOfRequiredParam() const {
    UInt4 sum=0U;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        sum += this->funcList.at(i)->getNumberOfParam();
    }
    return sum;
}

/**
 *  decomposite a list to original parameters to a list of subsequences of paramters
 *  in according to the a list of functions
 *  the i-th. row of the array is a list of parameters that i-th. function component requires
 *
 *  \param[in] i    the index of the i-th. function component
 *  \param[in] list a list of parameters
 */
std::vector< std::vector<Double> > AdvFuncComb::vectorToArray(const std::vector<Double> &list) {
    std::string memberName=std::string("vectorToArray(const std::vector<Double> &)");

    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "enter");
    DebugMessage(className, memberName, __FILE__, __LINE__, "size of list=%u\n", list.size());
    /*
    UInt4 ct=0;
    for (std::vector<Double>::const_iterator i=list.begin(); i!=list.end(); ++i) {
        //DebugMessage(className, memberName, __FILE__, __LINE__, "entry of list: %5u %g\n", ct, *i);
        ++ct;
    }
    */

    std::vector< std::vector<Double> > *retval = new std::vector< std::vector<Double> >();
//    for (UInt4 i =0; i<this->linkList.size();i++)
//       {
//        std::cout << "koko-main-"<<i<<", "<<this->linkList.at(i)<<std::endl;
//        }


    std::vector<Double> listCopy = list;
    //std::vector<Double>::const_iterator it = listCopy.begin();

    if (this->linkList.size()!=0)
        {
        for (UInt4 i=0; i<this->linkList.size(); i++)
            {
            if(this->linkList.at(i)-1==i)
                {
                //std::cout << " " << std::endl;
                }
            else
                {
                listCopy.erase(listCopy.begin()+i);
                listCopy.insert(listCopy.begin()+i,list.at(this->linkList.at(i)-1));
                }

            }
        }

    //std::vector<Double>::const_iterator b=list.begin();
    //std::vector<Double>::const_iterator e=list.begin();

    std::vector<Double>::const_iterator b=listCopy.begin(); // 20130125 change
    std::vector<Double>::const_iterator e=listCopy.begin(); // 20130125 change


    //for (UInt4 i=0; i<this->funcList.size(); ++i) {
    for (std::vector<AdvFuncBase*>::const_iterator fp=this->funcList.begin(); fp != this->funcList.end(); ++fp) {
        //for (UInt4 j=0; j < this->funcList.at(i)->getNumberOfParam(); ++j) {
        for (UInt4 j=0; j < (*fp)->getNumberOfParam(); ++j) {
            ++e;
        }
        /*
        DebugMessage(className, memberName, __FILE__, __LINE__, "");
        for (std::vector<Double>::const_iterator d=b; d != e; ++d) {
            std::cerr << " v=" << *d;
        }
        std::cerr << std::endl;
        */
        retval->push_back(*(new std::vector<Double>(b, e)));

        //for (UInt4 j=0; j < this->funcList.at(i)->getNumberOfParam(); ++j) {
        for (UInt4 j=0; j < (*fp)->getNumberOfParam(); ++j) {
            ++b;
        }
    }
    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n", "exit");
/*
    for (UInt4 i=0;i<retval->size();i++)
        {
        for (UInt4 j=0;j<retval->at(i).size();j++)
                {
                std::cout << "koko-sub-" << i << "," << j <<","<<retval->at(i).at(j)<< std::endl;
                }
        }
*/
    return *retval;
}

/**
 *  dump function compoments
 */
void AdvFuncComb::dump() {

    //UInt4 ct=0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        std::cout << this->funcList.at(i)->getName();
        std::cout << ", ";
        std::cout << this->funcList.at(i)->getSymbol();
        std::cout << ", ";
        std::cout << this->funcList.at(i)->getNumberOfParam();
        //std::cout << ", ";
        //std::cout << this->offset.at(i);
        //for (UInt4 j=0; j<this->funcList.at(i)->getNumberOfParam(); ++j) {
        if ( paramArray.empty() ) {
            std::cout << " no parameter";
        } else {
            std::cout << " (";
            if ( paramArray.size() == errorArray.size() ) {
                for (UInt4 j=0; j<paramArray.at(i).size(); ++j) {
                    std::cout << " ";
                    //std::cout << this->paramList.at(ct);
                    std::cout << this->paramArray.at(i).at(j);
                    std::cout << "+-";
                    //std::cout << this->errorList.at(ct);
                    std::cout << this->errorArray.at(i).at(j);
                    //++ct;
                }
            } else {
                for (UInt4 j=0; j<paramArray.at(i).size(); ++j) {
                    std::cout << " ";
                    //std::cout << this->paramList.at(ct);
                    std::cout << this->paramArray.at(i).at(j);
                    std::cout << "+-";
                    //std::cout << this->errorList.at(ct);
                    std::cout << this->errorArray.at(i).at(j);
                    //++ct;
                }
            }
            std::cout << ")";
        }
        /*
        */
        std::cout << std::endl;

    }
}

/**
 *  get the number of function compoments
 */
UInt4 AdvFuncComb::getNumberOfComponents() const {
    return this->funcList.size();
}

/**
 *
 */
std::string AdvFuncComb::getName(UInt4 i) const {
    if ( i< this->funcList.size()) {
        return this->funcList.at(i)->getName();
    } else {
        return std::string("");
    }
}

std::string AdvFuncComb::getSymbol(UInt4 i) const {
    if ( i< this->funcList.size()) {
        return this->funcList.at(i)->getSymbol();
    } else {
        return std::string("");
    }
}

UInt4 AdvFuncComb::getNumberOfRequiredParam(UInt4 i) const {
    if ( i < this->funcList.size() ) {
        return this->funcList.at(i)->getNumberOfParam();
    } else {
        return 0;
    }
}

/**
 *  get parameters for the i-th. compoment of the function
 *
 *  \param[in] i No. of a compoment of the function
 */
std::vector<Double> AdvFuncComb::getSubsequenceOfParam(UInt4 i) {
    return *(new std::vector<Double>(this->paramArray.at(i).begin(), this->paramArray.at(i).end()));
}

/**
 *  get parameter error for the i-th. compoment of the function
 *
 *  \param[in] i No. of a compoment of the function
 */
std::vector<Double> AdvFuncComb::getSubsequenceOfParamError(UInt4 i) {
    return *(new std::vector<Double>(this->errorArray.at(i).begin(), this->errorArray.at(i).end()));
}

/**
 *  evaluate the value of the speified function component
 *
 *  \param[in] x the value of argument of the function
 *  \param[in] i the index of the function component
 */
Double AdvFuncComb::evalComponent(const Double x, const UInt4 i) {

    //std::string memberName=std::string("evalComponent(const Double, UInt4)");
    Double retval=0.0;
    if ( i < this->funcList.size() ) {
        retval = this->funcList.at(i)->eval(x, this->paramArray.at(i));
    /*
    */
    }
    return retval;
}


#ifdef HAVE_DIFFERENTIAL_MEMBER
/**
 *  evaluate the 1st. derivative coefficient of the function component at the given point
 *
 *  \param[in] x the value of argument of the function
 *  \param[in] i the index of the function component
 */
Double AdvFuncComb::der1stComponent(const Double x, const UInt4 i) {
    std::string memberName=std::string("der1st(const Double, UInt4)");

    Double retval=0.0;
    if ( i < this->funcList.size() ) {
        retval = this->funcList.at(i)->der1st(x, this->paramArray.at(i));
    }
    return retval;
}

/**
 *  evaluate the 2nd. derivative coefficient of the function component at the given point
 *
 *  \param[in] x the value of argument of the function
 *  \param[in] i the index of the function component
 */
Double AdvFuncComb::der2ndComponent(const Double x, const UInt4 i) {
    std::string memberName=std::string("der1st(const Double, UInt4)");

    Double retval=0.0;
    if ( i < this->funcList.size() ) {
        retval = this->funcList.at(i)->der2nd(x, this->paramArray.at(i));
    }
    return retval;
}

/**
 *  evaluate the gradient of the function component for parameters at the given point
 *
 *  \param[in] x the value of argument of the function
 *  \param[in] i the index of the function component
 */
std::vector<Double> AdvFuncComb::gradientComponent(const Double x, const UInt4 i) {

    if ( i < this->funcList.size() ) {
        return this->funcList.at(i)->gradient(x, this->paramArray.at(i));
    } else {
        return *(new std::vector<Double>());
    }
}

/**
 *  evaluate the error of the specified function component at x
 *
 *  \param[in] x
 *  \parma[in] i the index of the function component
 */
Double AdvFuncComb::evalErrorComponent
(const Double x, const UInt4 i) {

    Double retval=0.0;
    for (UInt4 j=0; j<this->funcList.at(i)->getNumberOfParam(); ++j) {
        retval = this->innerProduct(
            this->funcList.at(i)->gradient(x, this->paramArray.at(i)), this->errorArray.at(i));
    }
    return retval;
}

#endif  // HAVE_DIFFERENTIAL_MEMBER

/**
 *  evaluate the value of the function
 *
 *  \param[in] x x coordinate of the function
 */
Double AdvFuncComb::eval(const Double x) {

    Double sum=0.0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        sum += this->evalComponent(x, i);
    }
    return sum;
}

#ifdef HAVE_DIFFERENTIAL_MEMBER

Double AdvFuncComb::der1st(const Double x) {
    Double sum=0.0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        sum += this->der1stComponent(x, i);
    }
    return sum;
}

Double AdvFuncComb::der2nd(const Double x) {
    Double sum=0.0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        sum += this->der2ndComponent(x, i);
    }
    return sum;
}

std::vector<Double> AdvFuncComb::gradient(const Double x) {

    std::string memberName=std::string("gradient");

    std::vector<Double> *retval = new std::vector<Double>();
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        std::vector<Double> g=this->gradientComponent(x, i);
        //debugMessage(className, memberName, "i=%u: size of g: %u\n", i, g.size());
        for (std::vector<double>::const_iterator d=g.begin(); d != g.end(); ++d) {
            retval->push_back(*d);
        }
        g.clear();
    }
    //std::cerr << std::endl;
    return *retval;
}

/**
 *  evaluate the error of the function at the given point
 *
 *  \param[in] x x coordinate of the function
 */
Double AdvFuncComb::evalError(const Double x) {

    Double sum=0.0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        sum += this->evalErrorComponent(x, i);
    }
    return sum;
}

#endif // HAVE_DIFFERENTIAL_MENBER
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 *  evaluate the value of the speified function component
 *
 *  \param[in] x a list of values of x coorduinate for the function
 *  \param[in] i the index of the function component
 *  \return    the list of values of the function at given points
 */
std::vector<Double> AdvFuncComb::evalComponent(const std::vector<Double> &x, const UInt4 i) {

    std::vector<Double> *retval=new std::vector<Double>();

    if ( i < this->funcList.size() ) {
        for (UInt4 j=0; j<x.size(); ++j) {
            retval->push_back(this->funcList.at(i)->eval(x.at(j), this->paramArray.at(i)));
        }
    }
    return *retval;
}

#ifdef HAVE_DIFFERENTIAL_MEMBER

std::vector<Double> AdvFuncComb::der1stComponent(const std::vector<Double> &x, const UInt4 i) {

    std::vector<Double> *retval = new std::vector<Double>();

    if ( i < this->funcList.size() ) {
        for (UInt4 j=0; j<x.size(); ++j) {
            retval->push_back(this->funcList.at(i)->der1st(x.at(j), this->paramArray.at(i)));
        }
    }
    return *retval;
}

std::vector<Double> AdvFuncComb::der2ndComponent(const std::vector<Double> &x, const UInt4 i) {

    std::vector<Double> *retval = new std::vector<Double>();
    if ( i < this->funcList.size() ) {
        for (UInt4 j=0; j<x.size(); ++j) {
            retval->push_back(this->funcList.at(i)->der2nd(x.at(j), this->paramArray.at(i)));
        }
    }
    return *retval;
}

std::vector< std::vector<Double> > AdvFuncComb::gradientComponent(const std::vector<Double> &x, const UInt4 i) {
    std::vector< std::vector<Double> > *retval=new std::vector< std::vector<Double> >();

    if ( i < this->funcList.size() ) {
        for (UInt4 j=0; j<x.size(); ++j) {
            retval->push_back(this->funcList.at(i)->gradient(x.at(j), this->paramArray.at(i)));
        }
    }
    return *retval;

}

/**
 *  evaluate the error of the specified function component at the given points
 *
 *  \param[in] x
 *  \parma[in] i the index of the function component
 */
std::vector<Double> AdvFuncComb::evalErrorComponent(const std::vector<Double> &x, const UInt4 i) {

    std::vector<Double> *retval=new std::vector<Double>();

    if (i < this->funcList.size()) {
        for (UInt4 j=0; j<x.size(); ++j) {
            retval->push_back(innerProduct(this->funcList.at(i)->gradient(x.at(j), this->paramArray.at(i)), errorArray.at(i)));
        }
    }
    return *retval;
}

#endif // HAVE_DIFFERENTIAL_MEMBER


/**
 *  evaluate the value of the function
 *
 *  \param[in] x x coordinate of the function
 *  \return    the list of values of the function at given points
 */
std::vector<Double> AdvFuncComb::eval(const std::vector<Double> &x) {
    std::string memberName = std::string("eval(const std::vector<Double> &)");
    DebugMessage(className, memberName, __FILE__, __LINE__, "enter\n");
    DebugMessage(className, memberName, __FILE__, __LINE__, "x.size(): %u\n", x.size());
    //DebugMessage(className, memberName, __FILE__, __LINE__, "funcList empty: %u \n", this->funcList.empty());
    //DebugMessage(className, memberName, __FILE__, __LINE__, "funcList: %u \n", this->funcList.size());
    //this->dump();

    std::vector<Double> *sum=new std::vector<Double>(x.size(), 0.0);
    DebugMessage(className, memberName, __FILE__, __LINE__, "sum.size: %u\n", sum->size());
    //if ( this->funcList.size() < x.size() ) {
    //    DebugMessage(className, memberName, __FILE__, __LINE__, "loop1\n");
    //    for (UInt4 i=0; i<this->funcList.size(); ++i) {
    //        std::vector<Double> v=evalComponent(x, i);
    //        DebugMessage(className, memberName, __FILE__, __LINE__, "v.size: %u\n", v.size());
    //        for (UInt4 j=0; j<x.size(); ++j) {
    //            sum->at(j) += v.at(j);
    //        }
    //        v.clear();
    //    }
    //} else {
        DebugMessage(className, memberName, __FILE__, __LINE__, "loop2\n");
        for (UInt4 i=0; i<x.size(); ++i) {
            sum->at(i) = eval(x.at(i));
            DebugMessage(className, memberName, __FILE__, __LINE__, "%d\n", i);
        }
    //}
    DebugMessage(className, memberName, __FILE__, __LINE__, "exit\n");
    return *sum;
}


#ifdef HAVE_DIFFERENTIAL_MEMBER

std::vector<Double> AdvFuncComb::der1st(const std::vector<Double> &x) {

    std::vector<Double> *sum=new std::vector<Double>(x.size(), 0.0);
    if ( this->funcList.size() < x.size() ) {
        for (UInt4 i=0; i<this->funcList.size(); ++i) {
            std::vector<Double> v=der1stComponent(x, i);
            for (UInt4 j=0; j<x.size(); ++j) {
                sum->at(j) += v.at(j);
            }
            v.clear();
        }
    } else {
        for (UInt4 i=0; i<x.size(); ++i) {
            sum->at(i) += der1st(x.at(i));
        }
    }
    return *sum;
}

std::vector<Double> AdvFuncComb::der2nd(const std::vector<Double> &x) {
    std::vector<Double> *sum=new std::vector<Double>(x.size(), 0.0);
    if ( this->funcList.size() < x.size() ) {
        for (UInt4 i=0; i<this->funcList.size(); ++i) {
            std::vector<Double> v=der2ndComponent(x, i);
            for (UInt4 j=0; j<x.size(); ++j) {
                sum->at(j) += v.at(j);
            }
            v.clear();
        }
    } else {
        for (UInt4 i=0; i<x.size(); ++i) {
            sum->at(i) += der2nd(x.at(i));
        }
    }
    return *sum;
}

std::vector< std::vector<Double> > AdvFuncComb::gradient(const std::vector<Double> &x) {
    std::vector< std::vector<Double> > *retval = new std::vector< std::vector<Double> >(x.size(), *(new std::vector<Double>));
    if ( this->funcList.size() < x.size() ) {
        for (UInt4 i=0; i<this->funcList.size(); ++i) {
            std::vector< std::vector<Double> > g=gradientComponent(x, i);
            for (UInt4 j=0; j<x.size(); ++j) {
                retval->at(j).insert(retval->at(j).end(), g.at(j).begin(), g.at(j).end());
                g.at(j).clear();
            }
            g.clear();
        }
    }
    return *retval;
}

std::vector<Double> AdvFuncComb::evalError(const std::vector<Double> &x) {

    std::vector<Double> *sum=new std::vector<Double>(x.size(), 0.0);
    if ( this->funcList.size() < x.size() ) {
        for (UInt4 i=0; i<this->funcList.size(); ++i) {
            std::vector<Double> v=evalErrorComponent(x, i);
            for (UInt4 j=0; j<x.size(); ++j) {
                sum->at(j) += v.at(j);
            }
            v.clear();
        }
    } else {
        for (UInt4 i=0; i<x.size(); ++i) {
            sum->at(i) += evalError(x.at(i));
        }
    }
    return *sum;
}

#endif // HAVE_DIFFERENTIAL_MENBER

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 *  get the subsequence of a vector for the specified function component
 *
 *  \param[in] i
 *  \param[in] v
 */
//std::vector<Double> AdvFuncComb::getSubsequence(const UInt4 i, const std::vector<Double> &v) {
//
//    std::string memberName=std::string("getSubsequence(const UInt4, const std::vector<Double> &)");
//
//    std::vector<Double>::const_iterator b=v.begin();
//    for (UInt4 ct=0; ct<this->offset.at(i); ++ct) {
//        ++b;
//    }
//    std::vector<Double>::const_iterator e=v.begin();
//    for (UInt4 ct=0; ct<this->offset.at(i)+this->funcList.at(i)->getNumberOfParam(); ++ct) {
//        ++e;
//    }
//    std::vector<Double> *p=new std::vector<Double>(b, e);
//
//    return *p;
//}

/**
 *  inner product for two vectors
 */
Double AdvFuncComb::innerProduct(const std::vector<Double> &x, const std::vector<Double> &y) {
    Double sum=0.0;
    if ( x.size() == y.size()) {
        for (UInt4 i=0; i<x.size(); ++i) {
            sum += x.at(i)*y.at(i);
        }
    }
    return sum;
}
