#include "AdvLevmarArgs.hh"

const string AdvLevmarArgs::className=string("AdvLevmarArgs");

/**
 *  constructor
 */
AdvLevmarArgs::AdvLevmarArgs() {
    this->lb=NULL;
    this->ub=NULL;
#ifdef HAVE_LAPACK
    this->wghts=NULL;
    this->A=NULL;
    this->b=NULL;
    this->C=NULL;
    this->d=NULL;
#endif // HAVE_LAPACK
    this->opts=NULL;
    this->additionalData=NULL;
}

/**
 *  destructor
 */
AdvLevmarArgs::~AdvLevmarArgs() {
    string memberName=string("~AdvLevmarArgs");
    DebugMessage(className, memberName, "enter\n");

#define DeleteArray(array)  if ((array) != NULL)  { delete[] (array); (array) =NULL; }
#define DeleteVector(vector) if ((vector) != NULL) { (vector)->clear(); delete (vector);  (vector)=NULL; }

    DeleteArray(this->param);
    DeleteArray(this->linkids);
    DeleteArray(this->ref);

    DeleteArray(this->lb);
    DeleteArray(this->ub);
#ifdef HAVE_LAPACK
    DeleteArray(this->wghts);
    DeleteArray(this->A);
    DeleteArray(this->b);
    DeleteArray(this->C);
    DeleteArray(this->d);
#endif // HAVE_LAPACK
    DeleteArray(this->opts);

    //DeleteVector(this->additionalData->x);
    //if (this->additionalData->useWeight) {
    //    DeleteVector(this->additionalData->w);
    //}
    //DeleteVector(this->additionalData->funcList);
    delete this->additionalData; this->additionalData=NULL;

    DebugMessage(className, memberName, "exit\n");
}

//SingleDataOnly
/**
 *  check the consistency of the input parameters
 *
 *  \param[in] src    an element container as a source data
 *  \param[in] domain the domain
 *  \param[in] param  parameters container
 */
Bool AdvLevmarArgs::checkParam(ElementContainer &src, AdvDomain &domain, AdvParamSet &param, AdvLevmarControl &control) {
    string memberName = string("checkParam(ElementContainer &, AdvDomain &, AdvParamSet &)");

    DebugMessage(className, memberName, "enter\n");
    Bool retval=true;

    retval = retval && this->checkNumberOfFittingParam(param);

    retval = retval && this->checkConstrainParam(param, control);

    retval = retval && this->checkScalingFactor(param);
    retval = retval && this->checkThresholds(param);
    if (param.getBool(AdvLevmarConsts::USE_NUMERICAL_DIFF)) {
        retval = retval && this->checkDiffDelta(param);
    }

    DebugMessage(className, memberName, "exit\n");
    return retval;
}


/**
 *  check a list of fitting functions
 *
 *  \param[in] param a parameter container
 */
Bool AdvLevmarArgs::checkFunc(const AdvParamSet &param) {
    string memberName=string("checkFunc(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}


/**
 *  check the number of fitting parameters (the length  of a vector for fitting parameters)
 *
 *  \param[in] param a parameter container
 */
Bool AdvLevmarArgs::checkNumberOfFittingParam(const AdvParamSet &param) {
    string memberName=string("checkNumberOfFittingParam(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key   =AdvLevmarConsts::PARAMETER_VALUES;
    string key2   =AdvLevmarConsts::LINK_IDS;
    string relkey=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", relkey.c_str());
        return false;
    }
    if ( ! param.contain(key2) ) {
        errorMessage(className, memberName, "does not contain the link ids with the key \"%s\"\n", key2.c_str());
        return false;
    }

    Int4 nParam = this->setNumberOfFittingParam(param);
    Int4 nReq   = this->setNumberOfRequiredParam(param);
    if ( nParam != nReq ) {
        errorMessage(className, memberName, "the number of the fitting parmeters in not equal to the number of paramters that the fitting functions require.");
        errorMessage(className, memberName, "the number of the fitting parameters:  %d\n", nParam);
        errorMessage(className, memberName, "the number of the required parameters: %d\n", nReq  );
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}

//MultiDataOnly

/**
 *  check the consistency of the input parameters
 *
 *  \param[in] src         an element container array as source data
 *  \param[in] domainArray the domain
 *  \param[in] param       parameters container
 */
Bool AdvLevmarArgs::checkParam(ElementContainerArray &src, vector<AdvDomain> &domainArray, AdvParamSet &param, AdvLevmarControl &control) {
    string memberName = string("checkParam(ElementContainerArray &, vector<AdvDomain> &, AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    if (src.PutSize() == 0) {
        errorMessage(className, memberName, "empty source\n");
        return false;
    }
    if (domainArray.size() == 0) {
        errorMessage(className, memberName, "empty domain array\n");
        return false;
    }
    if (src.PutSize() != domainArray.size()) {
        errorMessage(className, memberName, "the size of  the source is not agree with the size of the domain array\n");
        return false;
    }

    Bool retval=true;
    retval = retval && this->checkFuncSet(param);
    retval = retval && this->checkNumberOfFittingParamForMultiFunc(param);

    retval = retval && this->checkConstrainParam(param, control);
    retval = retval && this->checkScalingFactor(param);
    retval = retval && this->checkThresholds(param);
    if (param.getBool(AdvLevmarConsts::USE_NUMERICAL_DIFF)) {
        retval = retval && this->checkDiffDelta(param);
    }


    DebugMessage(className, memberName, "exit\n");
    return retval;
}

/**
 *  check a set of fitting function list
 *
 * \param[in] param a parameter container
 * \return true if param contains a set of fitting function list.
 */
Bool AdvLevmarArgs::checkFuncSet(const AdvParamSet &param) {
    string memberName=string("checkFuncSet(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }

    DebugMessage(className, memberName, "exit\n");
    return true;
}


Bool AdvLevmarArgs::checkNumberOfFittingParamForMultiFunc(const AdvParamSet &param) {
    string memberName=string("checkNumberOfFittingParamForMultiFunc(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key   =AdvLevmarConsts::PARAMETER_VALUES;
    string key2   =AdvLevmarConsts::LINK_IDS;
    string relkey=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", relkey.c_str());
        return false;
    }
    if ( ! param.contain(key2) ) {
        errorMessage(className, memberName, "does not contain the link id with the key \"%s\"\n", key2.c_str());
        return false;
    }


    Int4 nParam = this->setNumberOfFittingParam(param);
    vector<Int4> nReq = this->setListOfNumberOfRequiredParamForMultiFunc(param);
    for (UInt4 i=0; i<nReq.size(); ++i) {
        if ( nParam != nReq[i] ) {
            errorMessage(className, memberName, "the number of the fitting parmeters in not equal to the number of paramters that the %u-th. fitting function sequence require.", i);
            errorMessage(className, memberName, "the number of the fitting parameters:  %d\n", nParam);
            errorMessage(className, memberName, "the number of the required parameters: %d\n", nReq[i]);
            return false;
        }
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}


//Common
/** check constrain parameters for levmar
 *
 * @param[in] param    the parameter container
 * @param[in] constrol control valiables for levmar
 * @retval true if the constrain parameters are consistent
 */
Bool AdvLevmarArgs::checkConstrainParam(const AdvParamSet &param, AdvLevmarControl &control) {
    string memberName = string("checkConstrainParam(AdvParamSet &, AdvLevmarControl &control)");
    DebugMessage(className, memberName, "enter\n");

    Bool retval=true;
    AdvLevmarConsts::Constrain constrain = control.getConstrain(param);
    switch (constrain) {
        case AdvLevmarConsts::BOX:
#ifdef HAVE_LAPACK
        case AdvLevmarConsts::BLEC:
        case AdvLevmarConsts::BLIC:
        case AdvLevmarConsts::BLEIC:
#endif //  HAVE_LAPACK
            retval = retval && this->checkBoxies(param);
            break;
        default:
            break;
    }
#ifdef HAVE_LAPACK
    switch (constrain) {
        case AdvLevmarConsts::BLEC:
            retval = retval && this->checkBoxWeights(param);
            break;
        default:
            break;
    }
    switch (constrain) {
        case AdvLevmarConsts::LEC:
        case AdvLevmarConsts::BLEC:
        case AdvLevmarConsts::LEIC:
        case AdvLevmarConsts::BLEIC:
            retval = retval && this->checkEquations(param);
            break;
        default:
            break;
    }
    switch (constrain) {
        case AdvLevmarConsts::LIC:
        case AdvLevmarConsts::BLIC:
        case AdvLevmarConsts::LEIC:
        case AdvLevmarConsts::BLEIC:
            retval = retval && this->checkInequalities(param);
            break;
        default:
            break;
    }
#endif //  HAVE_LAPACK

    DebugMessage(className, memberName, "exit\n");
    return retval;
}


/**
 *  check the constrain box(ies), i.e.  vectors for the lower and upper bounds.
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains required vectors
 */
Bool AdvLevmarArgs::checkBoxies(const AdvParamSet &param) {
    string memberName=string("checkBoxies(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key1  =AdvLevmarConsts::LOWER_BOUNDS;
    string key2  =AdvLevmarConsts::UPPER_BOUNDS;
    string relKey=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key1) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key1.c_str());
        return false;
    }
    if ( ! param.contain(key2) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key2.c_str());
        return false;
    }
    if ( ! param.contain(relKey) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", relKey.c_str());
        return false;
    }
    Int4 nlb =param.getVectorSize(key1);
    Int4 nub =param.getVectorSize(key2);
    Int4 nReq=this->setNumberOfRequiredParam(param);
    if ( nlb < nReq ) {
        errorMessage(className, memberName, "the number of %s is not equal to the number of parameters that functions required\n", key1.c_str());
        errorMessage(className, memberName, "the number of the %s : %u ", key1.c_str(), nlb);
        errorMessage(className, memberName, "the number of the required paameter : %u ", nReq);
        return false;
    }
    if ( nub < nReq ) {
        errorMessage(className, memberName, "the number of %s is not equal to the number of parameters that functions required\n", key2.c_str());
        errorMessage(className, memberName, "the number of the %s : %u ", key2.c_str(), nub);
        errorMessage(className, memberName, "the number of the required paameter : %u ", nReq);
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}

#ifdef HAVE_LAPACK
/**
 *  check the box weights
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the vector for the box weight
 */
Bool AdvLevmarArgs::checkBoxWeights(const AdvParamSet &param) {
    string memberName=string("checkBosWeight(paramSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key   =AdvLevmarConsts::BOX_WEIGHTS;

    if ( param.contain(key) ) {
        Int4 nReq = this->setNumberOfRequiredParam(param);
        Int4 nBoxWeights = param.getVectorSize(key);
        if ( nBoxWeights < nReq ) {
            errorMessage(className, memberName, "the number of %s is not equal to the number of parameters that functions required\n", key.c_str());
            errorMessage(className, memberName, "the number of %s : %u\n",  key.c_str(), nBoxWeights);
            errorMessage(className, memberName, "the number of required parametar : %u\n", nReq);
            return false;
        }
    } else {
        infoMessage(className, memberName, "no box specified. default weight values are used\n");
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}

/**
 *  check the linear equations for constrain (a extended matrix for the linear equations)
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the matrix
 */
Bool AdvLevmarArgs::checkEquations(const AdvParamSet &param) {
    string memberName=string("checkEquations(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key   =AdvLevmarConsts::EQUATIONS;
    string relKey=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    if ( ! param.contain(relKey) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", relKey.c_str());
        return false;
    }

    //Int4 nEq   =param.getRowSize(key);
    Int4 nParam=param.getColumnSize(key)-1;
    Int4 nReq  =this->setNumberOfRequiredParam(param);
    if ( nParam != nReq ) {
        errorMessage(className, memberName, "the number of prameters in %s is not equal to the number of parameters that functions required\n", key.c_str());
        errorMessage(className, memberName, "the number of the parameters in %s : %u ", key.c_str(), nParam);
        errorMessage(className, memberName, "the number of the required paameter : %u ", nReq);
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}

/**
 *  check the linear inequalities for constrain (a extended matrix for the linear inequalities)
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the matrix
 */
Bool AdvLevmarArgs::checkInequalities(const AdvParamSet &param) {
    string memberName=string("checkInequalities(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    string key   =AdvLevmarConsts::INEQUALITIES;
    string relKey=AdvLevmarConsts::FUNCTIONS;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    if ( ! param.contain(relKey) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", relKey.c_str());
        return false;
    }

    //Int4 nEq   =param.getRowSize(key);
    Int4 nParam=param.getColumnSize(key)-1;
    Int4 nReq  =this->setNumberOfRequiredParam(param);
    if ( nParam != nReq ) {
        errorMessage(className, memberName, "the number of prameters in %s is not equal to the number of parameters that functions required\n", key.c_str());
        errorMessage(className, memberName, "the number of the parameters in %s : %u ", key.c_str(), nParam);
        errorMessage(className, memberName, "the number of the required paameter : %u ", nReq);
        return false;
    }

    DebugMessage(className, memberName, "exit\n");
    return true;
}
#endif // HAVE_LAPACK

/**
 *  check the initial value of the scaling factor for Levmar
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the value
 */
Bool AdvLevmarArgs::checkScalingFactor(const AdvParamSet &param) {
    string memberName=string("checkScalingFactor(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key=AdvLevmarConsts::SCALING_FACTOR;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}

/**
 *  check an stop threshod
 *
 *  \param[in] param  a parameter container
 *  \param[in] key    the key for the parameter
 *  \param[in] depkey the deprecated key for the parameter
 */
Bool AdvLevmarArgs::checkSingleThreshold(const AdvParamSet &param, const string &key, const string &depKey) {
    string memberName=string("checkSingleThreshold");
    DebugMessage(className, memberName, "enter\n");

    if ( ! param.contain(key) ) {
        if ( ! param.contain(depKey) ) {
            errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
            return false;
        } else {
            warningMessage(className, memberName, "found the parameter with the key \"%s\".\n", depKey.c_str());
            warningMessage(className, memberName, "the key \"%s\" is deprecated. INSTEAD, USE the new key \"%s\".\n", depKey.c_str(), key.c_str());
        }
    }

    DebugMessage(className, memberName, "exit\n");
    return true;
}

/**
 *  check termination thresholds
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the values
 */
Bool AdvLevmarArgs::checkThresholds(const AdvParamSet &param) {
    string memberName=string("checkThresholds(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string deprecatedKey1=AdvLevmarConsts::TOLERANCE;
    string deprecatedKey2=AdvLevmarConsts::GRADIENT_TOLERANCE;
    string deprecatedKey3=AdvLevmarConsts::RELATIVE_TOLERANCE;
    string key1=AdvLevmarConsts::PARAM_DIFF_THRESH;
    string key2=AdvLevmarConsts::GRADIENT_THRESH;
    string key3=AdvLevmarConsts::RESIDU_ERR_THRESH;

    Bool retval=true;
    retval=retval && this->checkSingleThreshold(param, key1, deprecatedKey1);
    retval=retval && this->checkSingleThreshold(param, key2, deprecatedKey2);
    retval=retval && this->checkSingleThreshold(param, key3, deprecatedKey3);
    DebugMessage(className, memberName, "exit\n");
    return retval;
}


/**
 *  check the diffrence for the numerical diffrential only when control parameter "AdvLevmarConstatns::USE_NUMERICAL_DIFF" == true
 *
 *  \param[in] param a parameter container
 *  \retvrn true, if the parameter container contains the value
 */
Bool AdvLevmarArgs::checkDiffDelta(const AdvParamSet &param) {
    string memberName=string("checkDiffDelta(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");
    string key=AdvLevmarConsts::DIFF_DELTA;

    if ( ! param.contain(key) ) {
        errorMessage(className, memberName, "does not contain the parameter with the key \"%s\"\n", key.c_str());
        return false;
    }
    DebugMessage(className, memberName, "exit\n");
    return true;
}


//SingleDataOnly

/**
 *  translate parameters to inner form
 */
void AdvLevmarArgs::toInnerForm(ElementContainer &src, AdvDomain &AdvDomain, AdvParamSet &param, AdvLevmarControl &control) {
    string memberName=string("toInnerForm(ElementContainer &, AdvDomain &, AdvParamSet &, AdvLevmarControl &)");
    DebugMessage(className, memberName, "enter\n");

    this->nSeries = 1;
    this->funcList = *(new vector< vector<AdvFuncBase*> >(1));
    this->funcList.at(0) = this->setFuncList(param);

    this->nParam   = this->setNumberOfFittingParam(param);
    this->nRef     = this->setNumberOfReferenceData(src, AdvDomain);
    this->param    = this->setFittingParamArray(param);
    this->linkids  = this->setLinkIdsArray(param);
    this->ref      = this->setReferenceDataArray(src, AdvDomain, param);
    this->setConstrainParams(param, control);
    this->opts = this->setOptions(param);
    //this->additionalData = this->createAdditionalData(src, AdvDomain, param);
    this->additionalData = new AdvAdditionalData(control, src, AdvDomain, param);
    additionalData->linklist = this->linkids;
    DebugMessage(className, memberName, "exit\n");
}


/**
 *  get a list of fitting functions from a parameter container
 *
 *  \param[in] param a parameter conatainer
 */
vector<AdvFuncBase*> AdvLevmarArgs::setFuncList(const AdvParamSet &param) {
    return param.getFuncList(AdvLevmarConsts::FUNCTIONS);
}


/**
 *  get the number of parameters that the fitting function required
 *
 *  \param[in] param a parameter conatainer
 */
Int4 AdvLevmarArgs::setNumberOfRequiredParam(const AdvParamSet &param) {
    string memberName=string("setNumberOfRequiredParam(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Int4 sum=0;
    vector<AdvFuncBase*> funcList=this->setFuncList(param);
    for (std::vector<AdvFuncBase*>::const_iterator fp=funcList.begin(); fp != funcList.end(); ++fp) {
        sum += (*fp)->getNumberOfParam();
    }

    DebugMessage(className, memberName, "exit\n");
    return sum;
}


/**
 *  get the number of refrerence data for fitting
 *
 *  \param[in] param a parameter conatainer
 */
Int4 AdvLevmarArgs::setNumberOfReferenceData(ElementContainer &src, const AdvDomain &AdvDomain) {
    return AdvDomain.getNumberOfBin();
}


/**
 *  get values of reference data as an array
 *
 *  \param[in] param a parameter conatainer
 */
Double *AdvLevmarArgs::setReferenceDataArray(ElementContainer &src, const AdvDomain &AdvDomain, const AdvParamSet &param) {
    string memberName=string("setReferenceDataArray(ElementContainer & AdvDomain &, AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    string key=AdvLevmarConsts::USE_DATA_WEIGHTS;

    vector<Double> y=src.PutY();
    vector<Double> e=src.PutE();

    Double *r=new Double[AdvDomain.getNumberOfBin()];
    UInt4 AdvDomainBegin=AdvDomain.getLowerBoundID();
    UInt4 AdvDomainEnd  =AdvDomain.getUpperBoundID();
    Double c=1.0/sqrt(AdvDomain.getNumberOfBin() - this->setNumberOfRequiredParam(param));
    if ( param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS) ) {
        for (UInt4 i=AdvDomainBegin; i<=AdvDomainEnd; ++i) {
            r[i-AdvDomainBegin]=c*y.at(i)/e.at(i);
        }
    } else {
        Double sum=0.0;
        for (UInt4 i=AdvDomainBegin; i<=AdvDomainEnd; ++i) {
            sum += e.at(i)*e.at(i);
        }
        Double c=1.0/sqrt(sum);
        for (UInt4 i=AdvDomainBegin; i<=AdvDomainEnd; ++i) {
            r[i-AdvDomainBegin]=c*y.at(i);
        }
    }
    DebugMessage(className, memberName, "exit\n");
    return r;
}


/**
 *  get values of data weight for fitting with weight as an array
 *
 *  \param[in] param  a parameter conatainer
 *  \param[in] AdvDomain the AdvDomain for fitting
 */
vector<Double> *AdvLevmarArgs::setDataWeightArray(ElementContainer &src, const AdvDomain &AdvDomain, const AdvParamSet &param, const AdvLevmarControl &control) {
    string memberName=string("setDataWeightArray(ElementContainer&, AdvDomain&, AdvParamSet& AdvLevmarControl&)");
    DebugMessage(className, memberName, "enter\n");

    string key=src.PutEKey();
    UInt4 ndata=AdvDomain.getNumberOfBin();
    UInt4 lower=AdvDomain.getLowerBoundID();
    UInt4 upper=AdvDomain.getUpperBoundID();

    vector<Double> *w = new vector<Double>(ndata);
    if (control.useDataWeights) {
        UInt4 dof=ndata - this->setNumberOfFittingParam(param); // degree of freedome
        Double c=1.0/sqrt(dof);
        for (UInt4 i=lower; i<=upper; ++i) {
            w->at(i-lower)=c/src.Put(key, i);
        }
    } else {
        Double e;
        Double sum=0.0;
        for (UInt4 i=lower; i<=upper; ++i) {
            e=src.Put(key, i);
            sum += e*e;
        }
        Double c=1.0/sqrt(sum);
        for (UInt4 i=0; i<ndata; ++i) {
           w->at(i)=c;
        }
    }
    DebugMessage(className, memberName, "exit\n");
    return w;
}

/*
Double *AdvLevmarArgs::setDataWeightArray(ElementContainer &src, const AdvDomain &AdvDomain) {
    string memberName=string("setDataWeightArray(ElementContainer&, AdvDomain&)");
    DebugMessage(className, memberName, "enter\n");

    UInt4 n=AdvDomain.getNumberOfBin();
    string key=src.PutEKey();

    Double *w = new Double[n];
    UInt4 lower=AdvDomain.getLowerBoundID();
    UInt4 upper=AdvDomain.getUpperBoundID();
    for (UInt4 i=lower; i<=upper; ++i) {
        w[i-lower]=src.Put(key, i);
    }
    DebugMessage(className, memberName, "exit\n");
    return w;
}
*/

/*
Double *AdvLevmarArgs::setDataWeightArray(ElementContainer &src, const AdvDomain &AdvDomain) {
    string memberName=string("setDataWeightArray(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    UInt4 n=AdvDomain.getNumberOfBin();
    //string key=src.PutEKey();
    vector<Double> e=src.PutE();

    Double s=0.0;
    Double t;
    for (UInt4 i=AdvDomain.getLowerBoundID(), ct=0; i<=AdvDomain.getUpperBoundID(); ++i, ++ct) {
        t=e.at(i);
        s += 1.0/(t*t);
    }
    Double *w = new Double[n];
    for (UInt4 i=AdvDomain.getLowerBoundID(), ct=0; i<=AdvDomain.getUpperBoundID(); ++i, ++ct) {
        w[ct]=1.0/(s*e.at(i));
    }
    DebugMessage(className, memberName, "exit\n");
    return w;
}
*/


/**
 *  create a set of parameter for evaluateing the values and Jacobian of fitting functions
 *
 *  \param[in] src    an element conatiner as the source data
 *  \param[in] AdvDomain the AdvDomain for fitting
 *  \param[in] param  the specified parameter container
 */
//AdditionalData *AdvLevmarArgs::createAdditionalData(ElementContainer &src, AdvDomain &AdvDomain, AdvParamSet &param) {
//    string memberName=string("createAdditionalData(ElementContainer &, AdvDomain &, AdvParamSet &)");
//    DebugMessage(className, memberName, "enter\n");
//
//    //AdditionalData *adata = new AdditionalData();
//    
//    AdditionalData *adata = new AdditionalData();
//    adata->x         = AdvDomain.createXC();
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %d\n", "size of x", adata->x->size());
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "x at the first", adata->x->at(0));
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "x at the last",  adata->x->at(adata->x->size()-1));
//
//    adata->useWeight = param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS);
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %d\n", "useWeight", adata->useWeight);
//
//    if ( ! param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS) ) {
//        adata->w = NULL;
//    } else {
//        adata->w = new vector<Double>(AdvDomain.getNumberOfBin());
//        for (UInt4 i=AdvDomain.getLowerBoundID(), ct=0; i<=AdvDomain.getUpperBoundID(); ++i, ++ct) {
//            adata->w->at(ct)=(src.Put(src.PutEKey(), i));
//        }
//    }
//    //adata->w         = param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS) ? src(src.PutEKey()) : NULL;
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %u\n", "size of Weight", adata->w->size());
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "Weight at the first", adata->w->at(0));
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "Weight at the last",  adata->w->at(adata->w->size()-1));
//
//    vector<AdvFuncBase*> tmp=param.getFuncList(AdvLevmarConsts::FUNCTIONS);
//    adata->funcList  = new vector<AdvFuncBase*>(tmp.begin(), tmp.end());
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %u\n", "the Number of functions", adata->funcList->size());
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s\n",      "the names of functions");
//    for (UInt4 i=0; i<adata->funcList->size(); ++i) {
//        DebugMessage(className, memberName, __FILE__, __LINE__, "%d : %s\n", i, adata->funcList->at(0)->getName().c_str());
//    }
//
//    DebugMessage(className, memberName, "exit\n");
//    return adata;
//}
//MultiDataOnly

/**
 *  translate parameters to inner form
 */
void AdvLevmarArgs::toInnerForm(ElementContainerArray &src, vector<AdvDomain> &AdvDomainArray, AdvParamSet &param, AdvLevmarControl &control) {
    string memberName=string("toInnerForm(ElementContainerArray &, vector<AdvDomain> &, AdvParamSet &, AdvLevmarControl &)");
    DebugMessage(className, memberName, "enter\n");

    this->nSeries = src.PutSize();

    this->funcList = this->setFuncMatrix(param);

    this->nParam = this->setNumberOfFittingParam(param);
    this->nRef   = this->setNumberOfReferenceData(src, AdvDomainArray);
    this->param  = this->setFittingParamArray(param);
    this->linkids  = this->setLinkIdsArray(param);
    this->ref    = this->setReferenceDataArray(src, AdvDomainArray, param);
    this->setConstrainParams(param, control);
    this->opts = this->setOptions(param);
    //this->additionalData = this->createAdditionalData(src, AdvDomainArray, param, control);
    this->additionalData = new AdvAdditionalData(control, src, AdvDomainArray, param);
    additionalData->linklist = this->linkids;
    DebugMessage(className, memberName, "exit\n");
}

/** get a multiple list of fitting functions from a parameter container
 *
 *  \param[in] param a parameter conatainer
 */
vector< vector<AdvFuncBase*> > AdvLevmarArgs::setFuncMatrix(const AdvParamSet &param) {
    return param.getFuncMatrix(AdvLevmarConsts::FUNCTIONS);
}

/** set a list of the number of parameters that each fitting function requires
 *
 * @param[in] param the parameter container
 */
vector<Int4> AdvLevmarArgs::setListOfNumberOfRequiredParamForMultiFunc(const AdvParamSet &param) {
    string memberName=string("setNumberOfRequiredParamForMultiFunc(AdvParamSet &");
    DebugMessage(className, memberName, "enter\n");

    vector< vector<AdvFuncBase*> > multiFunc=this->setFuncMatrix(param);
    vector<Int4> retval=*(new vector<Int4>(multiFunc.size(), 0));
    for (UInt4 i=0; i<multiFunc.size(); ++i) {
        Int4 sum=0;
        for (std::vector<AdvFuncBase*>::const_iterator fp=multiFunc.at(i).begin(); fp != multiFunc.at(i).end(); ++fp) {
            sum += (*fp)->getNumberOfParam();
        }
        retval.at(i)=sum;
    }

    DebugMessage(className, memberName, "exit\n");
    return retval;
}

/** get the number of common parameters that fitting functions require
 * @param[in] param the parameter container
 */
Int4 AdvLevmarArgs::setNumberOfRequiredParamForMultiFunc(const AdvParamSet &param) {
    vector<AdvFuncBase*> fl=param.getFuncMatrix(AdvLevmarConsts::FUNCTIONS).at(0);
    Int4 sum=0;
    for (std::vector<AdvFuncBase*>::const_iterator fp=fl.begin(); fp != fl.end(); ++fp) {
        sum += (*fp)->getNumberOfParam();
    }
    return sum;
}

/** get the number of refference data for multi data fitting
 */
Int4 AdvLevmarArgs::setNumberOfReferenceData(ElementContainerArray &src, const vector<AdvDomain> &AdvDomainArray) {
    Int4 sum=0;
    if ( src.PutSize() == AdvDomainArray.size() ) {
        for (std::vector<AdvDomain>::const_iterator AdvDomain=AdvDomainArray.begin(); AdvDomain != AdvDomainArray.end(); ++AdvDomain) {
            sum += (*AdvDomain).getNumberOfBin();
        }
    }
    return sum;
}


Double *AdvLevmarArgs::setReferenceDataArray(ElementContainerArray &src, const vector<AdvDomain> &AdvDomainArray, const AdvParamSet &param) {
    string memberName=string("setReferenceDataArray(ElementContainerArray & AdvDomain &, AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    string key1=AdvLevmarConsts::USE_DATA_WEIGHTS;
    //string key2=AdvLevmarConsts::MULTI_DATA_WEIGHTS;

    //Double weightBase;
    //vector<Double> sWeight = param.getVector(key2);

    DebugMessage(className, memberName, "the number of reference data %d\n", this->setNumberOfReferenceData(src, AdvDomainArray));
    Double *r=new Double[this->setNumberOfReferenceData(src, AdvDomainArray)];
    UInt4 numberOfSeries=src.PutSize(); // src.PutSize() == AdvDomainArray.size();
    DebugMessage(className, memberName, "the number of Series %d\n", numberOfSeries);
    UInt4 offset=0;
    DebugMessage(className, memberName, "series loop begin\n");
    for (UInt4 i=0; i<src.PutSize(); ++i) {
        ElementContainer *elem=src.PutPointer(i);
        vector<Double> y=elem->PutY();
        vector<Double> e=elem->PutE();
        UInt4 AdvDomainBegin=AdvDomainArray.at(i).getLowerBoundID();
        UInt4 AdvDomainEnd  =AdvDomainArray.at(i).getUpperBoundID();
        DebugMessage(className, memberName, "i=%d offset=%d AdvDomain(%d, %d)\n", i, offset, AdvDomainBegin, AdvDomainEnd);
        if ( param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS) ) {
            UInt4 dof=AdvDomainArray.at(i).getNumberOfBin() - this->setNumberOfFittingParam(param); // defree of freedom
            DebugMessage(className, memberName, "degree of freedom=%d\n", dof);
            Double c=1.0/sqrt(numberOfSeries*dof);
            DebugMessage(className, memberName, "loop begin\n");
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                r[offset+(j-AdvDomainBegin)]=c*y.at(j)/e.at(j);
            }
            DebugMessage(className, memberName, "loop end\n");
        } else {
            // sum of squared error
            Double sum=0.0;
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                sum+=(e.at(j)*e.at(j));
            }
            Double c=1.0/sqrt(sum*numberOfSeries);
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                r[offset+(j-AdvDomainBegin)]=c*y.at(j);
            }
        }
        offset += AdvDomainEnd-AdvDomainBegin+1;;
    }
    DebugMessage(className, memberName, "size of r=%d\n", sizeof(r)/sizeof(r[0]));
    DebugMessage(className, memberName, "series loop end\n");

    DebugMessage(className, memberName, "exit\n");
    return r;
}

/** create data weight.
 * @param[in] src           element container array
 * @param[in] AdvDomainArray   a list of the AdvDomains for element-containers in the element-container-array
 * @param[in] param         the parameter set for fitting
 * @param[in] control       the control variables for fitting
 * @retval data weight (vector)
 */
vector<Double> *AdvLevmarArgs::setDataWeightArray(ElementContainerArray &src, const vector<AdvDomain> &AdvDomainArray, const AdvParamSet &param, const AdvLevmarControl &control) {
    string memberName=string("setDataWeightArray(ElementContainerArray&, vector<AdvDomain>&, AdvParamSet&, AdvLevmarControl&)");
    DebugMessage(className, memberName, "enter\n");

    vector<Double> *retval=new vector<Double>(this->setNumberOfReferenceData(src, AdvDomainArray));
    DebugMessage(className, memberName, "number of reference data %d\n",this->setNumberOfReferenceData(src, AdvDomainArray));
    //vector<Double> sWeight=param.getVector(AdvLevmarConsts::MULTI_DATA_WEIGHTS);
    //DebugMessage(className, memberName, "size of series weight%d\n", sWeight.size());
    UInt4 offset=0;
    for(UInt4 i=0; i<src.PutSize(); ++i) {
        DebugMessage(className, memberName, "i=%u: offset=%u lowerBound=%d upperBound=%d\n", i, offset, AdvDomainArray.at(i).getLowerBoundID(), AdvDomainArray.at(i).getUpperBoundID());
        vector<Double> e = src.PutPointer(i)->PutE();
        UInt4 AdvDomainBegin=AdvDomainArray.at(i).getLowerBoundID();
        UInt4 AdvDomainEnd  =AdvDomainArray.at(i).getUpperBoundID();
        if (control.useDataWeights) {
            UInt4 dof=AdvDomainArray.at(i).getNumberOfBin() - this->setNumberOfFittingParam(param); // degree of freedom
            Double c=1.0/sqrt(src.PutSize()*dof);
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                retval->at(offset+(j-AdvDomainBegin)) = c/e.at(j);
            }
        } else {
            Double sum = 0.0;
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                sum += pow(e.at(j), 2.0);
            }
            Double cw=1.0/sqrt( src.PutSize() * sum );
            for (UInt4 j=AdvDomainBegin; j<=AdvDomainEnd; ++j) {
                retval->at((offset+(j-AdvDomainBegin)))=cw;
            }
        }
        offset += (AdvDomainEnd-AdvDomainBegin+1);
        DebugMessage(className, memberName, "offset = %d\n", offset);
    }

    DebugMessage(className, memberName, "exit\n");
    return retval;
}


//AdditionalData *AdvLevmarArgs::createAdditionalData(ElementContainerArray &src, vector<AdvDomain> &AdvDomainArray, AdvParamSet &param, AdvLevmarControl &control) {
//    string memberName=string("createAdditionalData(ElementContainer &, AdvDomain &, AdvParamSet &)");
//    DebugMessage(className, memberName, "enter\n");
//
//    AdditionalData *adata = new AdditionalData();
//    adata->useWeight = param.getBool(AdvLevmarConsts::USE_DATA_WEIGHTS);
//    adata->w = this->setDataWeightArray(src, AdvDomainArray, param, control);
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %u\n", "size of Weight", adata->w->size());
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "Weight at the first", adata->w->at(0));
//    DebugMessage(className, memberName, __FILE__, __LINE__, "%s : %e\n", "Weight at the last",  adata->w->at(adata->w->size()-1));
//
//    vector< vector<AdvFuncBase*> > tmp=this->setFuncMatrix(param);
//    adata->funcMatrix = new vector< vector<AdvFuncBase*> >(tmp.begin(), tmp.end());
//    adata->funcList = NULL;
//    DebugMessage(className, memberName, "exit\n");
//    return adata;
//}

//SetterCommon
/**
 *  set constrain prameters
 */
void AdvLevmarArgs::setConstrainParams(const AdvParamSet &param, const AdvLevmarControl &control) {
    string memberName=string("setConstrainParams(AdvParamSet &, AdvLevmarControl &)");
    DebugMessage(className, memberName, "enter\n");

    /* set BOX */
    switch (control.constrain) {
        case AdvLevmarConsts::BOX:
#ifdef HAVE_LAPACK
        case AdvLevmarConsts::BLEC:
        case AdvLevmarConsts::BLIC:
        case AdvLevmarConsts::BLEIC:
#endif // HAVE_LAPACK
            this->lb = this->setLowerBounds(param);
            this->ub = this->setUpperBounds(param);
            break;
        default:
            break;
    }

#ifdef HAVE_LAPACK
    /* set BOX Weight */
    switch (control.constrain) {
        case AdvLevmarConsts::BLEC:
            this->wghts=this->setBoxWeights(param);
            break;
        default:
            break;
    }
    /* set Equations */
    switch (control.constrain) {
        case AdvLevmarConsts::LEC:
        case AdvLevmarConsts::BLEC:
        case AdvLevmarConsts::LEIC:
        case AdvLevmarConsts::BLEIC:
            this->nEq = this->setNumberOfEquations(param);
            this->A   = this->setEquationCoefficients(param);
            this->b   = this->setEquationConsts(param);
            break;
        default:
            break;
    }
    /* set Equations */
    switch (control.constrain) {
        case AdvLevmarConsts::LIC:
        case AdvLevmarConsts::BLIC:
        case AdvLevmarConsts::LEIC:
        case AdvLevmarConsts::BLEIC:
            this->nIneq = this->setNumberOfEquations(param);
            this->C     = this->setInequalityCoefficients(param);
            this->d     = this->setInequalityConsts(param);
            break;
        default:
            break;
    }
#endif // HAVE_LAPACK
    DebugMessage(className, memberName, "exit\n");
}


/**
 *  get the number of fitting parameters
 *
 *  \param[in] param a parameter conatainer
 */
Int4 AdvLevmarArgs::setNumberOfFittingParam(const AdvParamSet &param) {
    return param.getVectorSize(AdvLevmarConsts::PARAMETER_VALUES);
}



/**
 *  get (initial) values of fitting paramters as an array
 *
 *  \param[in] param a parameter conatainer
 */
Double *AdvLevmarArgs::setFittingParamArray(const AdvParamSet &param) {
    string memberName=string("setFittingParamArray(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Int4 n=this->setNumberOfFittingParam(param);

    Double *p = new Double[n];
    for (Int4 i=0; i<n; ++i) {
        p[i]=param.getDouble(AdvLevmarConsts::PARAMETER_VALUES, i);
    }
    DebugMessage(className, memberName, "exit\n");
    return p;
}

/**
 *  get (initial) values of link ids as an array
 *
 *  \param[in] param a parameter conatainer
 */
Double *AdvLevmarArgs::setLinkIdsArray(const AdvParamSet &param) {
    string memberName=string("setLinkIdsArray(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Int4 n=this->setNumberOfFittingParam(param);

    Double *p = new Double[n];
    for (Int4 i=0; i<n; ++i) {
        p[i]=param.getDouble(AdvLevmarConsts::LINK_IDS, i);
    }
    DebugMessage(className, memberName, "exit\n");
    return p;
}


/**
 *  get a vector s an array from the specified parameter container
 *
 *  \param[in] param the specified parameter container
 *  \param[in] key   the key for the wanted parameter
 */
Double *AdvLevmarArgs::set1dArray(const AdvParamSet &param, const string &key) {
    string memberName=string("get1dArray(AdvParamSet &, string &)");
    DebugMessage(className, memberName, "enter\n");
    DebugMessage(className, memberName, "key=\"%s\"\n", key.c_str());

    Double *array=NULL;
    Int4 n=static_cast<Int4>(param.getVectorSize(key));

    if ( n == (this->nSeries == 1 ? this->setNumberOfRequiredParam(param) : this->setNumberOfRequiredParamForMultiFunc(param)) ) {
    //if ( n==this->setNumberOfRequiredParam(param) ) {
        array=new Double[n];
        for (Int4 i=0; i<n; ++i) {
            array[i]=param.getDouble(key, i);
        }
    }

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get the lower bounds for fitting parameter values
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setLowerBounds(const AdvParamSet &param) {
    string memberName=string("setLowerBounds(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array=this->set1dArray(param, AdvLevmarConsts::LOWER_BOUNDS);

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get the upper bounds for fitting parameter values
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setUpperBounds(const AdvParamSet &param) {
    string memberName=string("getUpperBounds(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array=this->set1dArray(param, AdvLevmarConsts::UPPER_BOUNDS);;

    DebugMessage(className, memberName, "exit\n");
    return array;
}

#ifdef HAVE_LAPACK

/**
 *  get the box weigts for fitting boxes
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setBoxWeights(const AdvParamSet &param) {
    string memberName=string("getBoxWeights(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array=this->set1dArray(param, AdvLevmarConsts::BOX_WEIGHTS);

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get the number of linear equations for the Levmar constrain
 *
 *  \param[in] param the specified parameter container
 */
Int4 AdvLevmarArgs::setNumberOfEquations(const AdvParamSet &param) {
    return param.getRowSize(AdvLevmarConsts::EQUATIONS);
}

/**
 *  get a matrix as an array from the specified parameter container
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::set2dArray(const AdvParamSet &param, const string &key) {
    string memberName=string("get2dArray(AdvParamSet &, string &)");
    DebugMessage(className, memberName, "enter\n");
    DebugMessage(className, memberName, "key=\"%s\"\n", key.c_str());

    UInt4 m=param.getRowSize(key);
    UInt4 n=param.getColumnSize(key)-1;

    Double *array = new Double[m*n];
    for (UInt4 i=0; i<m; ++i) {
        for (UInt4 j=0; j<n; ++j) {
            array[i*n+j]=param.getDouble(key, i, j);
        }
    }
    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get constant term of linear equation or inequalities as array
 *
 *  \param[in] param the specified parameter container
 *  \param[in] key   the key for the wanted parameter
 */
Double *AdvLevmarArgs::setConstArray(const AdvParamSet &param, const string &key) {
    string memberName=string("getConstArray(AdvParamSet &, string &)");
    DebugMessage(className, memberName, "enter\n");
    DebugMessage(className, memberName, "key=\"%s\"\n", key.c_str());

    UInt4 m=param.getRowSize(key);
    UInt4 n=param.getColumnSize(key);

    Double *array = new Double[m];
    for (UInt4 i=0; i<m; ++i) {
        array[i] = param.getDouble(key, i, n-1);
    }

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get equation cefficients as an array
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setEquationCoefficients(const AdvParamSet &param) {
    string memberName=string("getEquationCoefficients(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array = this->set2dArray(param, AdvLevmarConsts::EQUATIONS);

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get constant term of linear equations as an array
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setEquationConsts(const AdvParamSet &param) {
    string memberName=string("getEquationConsts(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array = this->setConstArray(param, AdvLevmarConsts::EQUATIONS);

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get the number of linear inequalities for the Levmar constrain
 *
 *  \param[in] param the specified parameter container
 */
Int4 AdvLevmarArgs::setNumberOfInequalities(const AdvParamSet &param) {
    return param.getRowSize(AdvLevmarConsts::INEQUALITIES);
}

/**
 *  get inequality cefficients as an array
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setInequalityCoefficients(const AdvParamSet &param) {
    string memberName=string("getInequalityCoefficients(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array = this->set2dArray(param, AdvLevmarConsts::INEQUALITIES);

    DebugMessage(className, memberName, "exit\n");
    return array;
}

/**
 *  get constant term of linear inequalities as an array
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setInequalityConsts(const AdvParamSet &param) {
    string memberName=string("getInequalityConsts(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *array = this->setConstArray(param, AdvLevmarConsts::INEQUALITIES);

    DebugMessage(className, memberName, "exit\n");
    return array;
}
#endif // HAVE_LAPACK

/**
 *  get optiona paameters from the specified parameter container
 *
 *  \param[in] param the specified parameter container
 */
Double *AdvLevmarArgs::setOptions(const AdvParamSet &param) {
    string memberName=string("setOptions(AdvParamSet &)");
    DebugMessage(className, memberName, "enter\n");

    Double *opts = new Double[(param.getBool(AdvLevmarConsts::USE_NUMERICAL_DIFF) ? LM_OPTS_SZ : LM_OPTS_SZ-1)];
    opts[0] = param.getDouble(AdvLevmarConsts::SCALING_FACTOR);

    if ( param.contain(AdvLevmarConsts::GRADIENT_THRESH)    ) {
        opts[1] = param.getDouble(AdvLevmarConsts::GRADIENT_THRESH);
    } else if ( param.contain(AdvLevmarConsts::GRADIENT_TOLERANCE) ) {
        opts[1] = param.getDouble(AdvLevmarConsts::GRADIENT_TOLERANCE);
    }
    if ( param.contain(AdvLevmarConsts::PARAM_DIFF_THRESH) ) {
        opts[2] = param.getDouble(AdvLevmarConsts::PARAM_DIFF_THRESH);
    } else if ( param.contain(AdvLevmarConsts::TOLERANCE) ) {
        opts[2] = param.getDouble(AdvLevmarConsts::TOLERANCE);
    }
    if ( param.getDouble(AdvLevmarConsts::RESIDU_ERR_THRESH) ) {
        opts[3] = param.getDouble(AdvLevmarConsts::RESIDU_ERR_THRESH);
    } else if ( param.contain(AdvLevmarConsts::RELATIVE_TOLERANCE) ) {
        opts[3] = param.getDouble(AdvLevmarConsts::RELATIVE_TOLERANCE);
    }
    if ( param.getBool(AdvLevmarConsts::USE_NUMERICAL_DIFF) ) {
        Double d=abs(param.getDouble(AdvLevmarConsts::DIFF_DELTA));
        switch ( static_cast<AdvLevmarConsts::DiffMethod>(param.getInt4(AdvLevmarConsts::DIFF_METHOD)) ) {
            case AdvLevmarConsts::FORWARD:
                opts[4] = d;
                break;
            case AdvLevmarConsts::CENTRAL:
                opts[4] = -1.0*d;
                break;
        }
    }
    DebugMessage(className, memberName, "exit\n");
    return opts;
}


//GetterSingleDataOnly
/**
 *  get the file of fitting funcsions as string
 */
string *AdvLevmarArgs::getFunctionStr() {
    string *retval = new string("");
    retval->insert(retval->size(), this->funcList.at(0).at(0)->getSymbol());
    for (UInt4 i=1; i<this->funcList.at(0).size(); ++i) {
        retval->insert(retval->size(), " ");
        retval->insert(retval->size(), this->funcList.at(0).at(i)->getSymbol());
    }
    return retval;
}

//MultiDataOnly
/**
 *  get the file of fitting funcsions as string
 *
 *  @param[in] i the index of i-th data series
 *  @retval the pointer to the function expression string
 */
string *AdvLevmarArgs::getFunctionStrForMultiData(UInt4 i) {
    string *retval = new string("");
    retval->insert(retval->size(), this->funcList.at(i).at(0)->getSymbol());
    for (UInt4 j=1; j<this->funcList.at(i).size(); ++j) {
        retval->insert(retval->size(), " ");
        retval->insert(retval->size(), this->funcList.at(i).at(j)->getSymbol());
    }
    return retval;
}
//GetterCommon
/**
 *  get intial values of fitting parameters as vector
 */
vector<Double> *AdvLevmarArgs::getInitialParam() {
    return this->arrayToVector(this->param, this->nParam);
}

/**
 *  get lower bounds as a vector
 */
vector<Double> *AdvLevmarArgs::getLowerBounds() {
    return this->arrayToVector(this->lb, this->nParam);
}

/**
 *  get lower bounds as a vector
 */
vector<Double> *AdvLevmarArgs::getUpperBounds() {
    return this->arrayToVector(this->ub, this->nParam);
}

#ifdef HAVE_LAPACK
/**
 *  get Box Weights as a vector
 */
vector<Double> *AdvLevmarArgs::getBoxWeights() {
    return this->arrayToVector(this->wghts, this->nParam);
}

/**
 *  get extended coefficient matrix (i.e.  coefficients and constatnts)
 *
 *  \param[in] A      coefficient matrix of equations or inequalities
 *  \param[in] b      constant terms of equations or inequalities
 *  \param[in] nEq    the number of equations or inequalities
 *  \param[in] nparam the number of parameters (variables)
 */
vector< vector<Double> > *AdvLevmarArgs::getExtCoeffMatrix(const Double *A, const Double *b, const Int4 nEq, const Int4 nParam) {
    string memberName=string("getExtCoeffMatrix(const Double *, const Double *, const Int4, const Int4)");
    DebugMessage(className, memberName, "enter\n");

    vector< vector<Double> > *retval=new vector< vector<Double> >(nEq, *(new vector<Double>(nParam+1)));
    for (Int4 i=0; i<nEq; ++i) {
        for (Int4 j=0; j<nParam; ++j) {
            retval->at(i).at(j)=A[i*nParam+j];

        }
        retval->at(i).at(nParam)=b[i];
    }

    DebugMessage(className, memberName, "exit\n");
    return retval;
}

/**
 *  get linear equations as an extended coefficient matrix
 */
vector< vector<Double > > *AdvLevmarArgs::getEqMatrix() {
    string memberName=string("getEqfMatrix()");
    DebugMessage(className, memberName, "enter\n");
    vector< vector<Double> > *retval= this->getExtCoeffMatrix(this->A, this->b, this->nEq, this->nParam);
    DebugMessage(className, memberName, "exit\n");
    return retval;
}

/**
 *  get linear inequalites as an extended coefficient matrix
 */
vector< vector<Double > > *AdvLevmarArgs::getIneqMatrix() {
    string memberName=string("getIneqfMatrix()");
    DebugMessage(className, memberName, "enter\n");
    vector< vector<Double> > *retval= this->getExtCoeffMatrix(this->C, this->d, this->nIneq, this->nParam);
    DebugMessage(className, memberName, "exit\n");
    return retval;
}
#endif // HAVE_LAPACK

//ArgsOutput

/**
 *  output constrain boxes
 */
void AdvLevmarArgs::outputConstrainBox(AdvLevmarConsts::Constrain constrain) {
    string memberName=string("outputConstrainBox()");
    DebugMessage(className, memberName, "enter\n");

    std::cout << setw(4)  << " ";
    std::cout << setw(4)  << " ";
    std::cout << setw(5)  << setiosflags(std::ios::right) << "No.";
    std::cout << setw(23) << setiosflags(std::ios::right) << "lower";
    std::cout << setw(23) << setiosflags(std::ios::right) << "upper";
#ifdef HAVE_LAPACK
    if (constrain==AdvLevmarConsts::BLEC && this->wghts != NULL ) {
        std::cout << setw(23) << setiosflags(std::ios::right) << "weight";
    }
#endif // HAVE_LAPACK
    std::cout << endl;

    DebugMessage(className, memberName, "nParam=%u\n", this->nParam);
#ifdef HAVE_LAPACK
    DebugMessage(className, memberName, "boolean=%u\n", (constrain==AdvLevmarConsts::BLEC && this->wghts != NULL ) );
#endif // HAVE_LAPACK
    DebugMessage(className, memberName, "*lb == NULL %u\n", this->lb == NULL );
    DebugMessage(className, memberName, "*ub == NULL %u\n", this->ub == NULL );
    for (Int4 i=0; i<this->nParam; ++i) {
        DebugMessage(className, memberName, "i=%u\n", i );
        std::cout << setw(4)  << " ";
        std::cout << setw(4)  << " ";
        std::cout << setw(5)  << setiosflags(std::ios::right) << i;
        std::cout << setw(23) << setiosflags(std::ios::right) << this->lb[i];
        std::cout << setw(23) << setiosflags(std::ios::right) << this->ub[i];
#ifdef HAVE_LAPACK
        if (constrain==AdvLevmarConsts::BLEC && this->wghts != NULL ) {
            std::cout << setw(23) << setiosflags(std::ios::right) << this->wghts[i];
        }
#endif // HAVE_LAPACK
        std::cout << endl;
    }
    DebugMessage(className, memberName, "loop end\n");

    DebugMessage(className, memberName, "exit\n");
}

#ifdef HAVE_LAPACK
/**
 *  output linear expressions for constrain to  the standard output
 *
 *  \param[in] nExp   the number of linear expressions
 *  \param[in] nParam the number of fitting parameters
 *  \param[in] A      the coefficient matrix (array) of linear equations
 *  \param[in] b      the constant term of linear equations
 */
void AdvLevmarArgs::outputConstrainExpressions(const Int4 nExp, const Int4 nParam, const Double *A, const Double *b) {
    string memberName=string("outputConstrainExpressions(Int4, Int4, Double*, Double*)");
    DebugMessage(className, memberName, "enter\n");

    for (Int4 i=0; i<nExp; ++i) {
        std::cout << setw(4)  << " ";
        std::cout << setw(4)  << " ";
        std::cout << setw(5)  << i;
        for (Int4 j=0; j<nParam; ++j) {
            std::cout << setw(23) << setprecision(15) << setiosflags(std::ios::left) << A[i*nParam+j];
        }
        std::cout << setw(23) << setprecision(15) << setiosflags(std::ios::left) << b[i];
        std::cout << endl;
    }
    std::cout << endl;

}
#endif // HAVE_LAPACK
 
/**
 *  output initial values of fitting parameters to the standard output
 * 
 */
void AdvLevmarArgs::outputInitialFittingParam() {
    string memberName=string("outputInitialFittingParam(vector<AdvFuncBase*> &, Double *)");
    DebugMessage(className, memberName, "enter\n");

    Int4 offset=0;
    Int4 no=0;
    if (this->funcList.size()==1) {
        for (std::vector<AdvFuncBase*>::const_iterator fp=this->funcList.at(0).begin(); fp != this->funcList.at(0).end(); ++fp) {
            std::cout << setw(4*2) << " ";
            std::cout << string("function");
            std::cout << setw(5) << no;
            std::cout << setw(2) << ": ";
            std::cout << (*fp)->getName();
            std::cout << endl;

            std::cout << setw(4*2) << " ";
            std::cout << setw(9)   << "seq. No.";
            for (UInt4 i=offset; i< offset+(*fp)->getNumberOfParam(); ++i) {
                std::cout << setw(1) << " ";
                std::cout << setw(23) << setiosflags(std::ios::right) << i;
            }
            std::cout << endl;

            std::cout << setw(4*2) << " ";
            std::cout << setw(9)   << "parameter";
            for (UInt4 i=offset; i<offset+(*fp)->getNumberOfParam(); ++i) {
                std::cout << setw(1) << " ";
                std::cout << setw(23) << setprecision(15) << setiosflags(std::ios::right) << this->param[i];
            }
            std::cout << endl;
            std::cout << endl;
            offset += (*fp)->getNumberOfParam();
            ++no;
        }
    } else if (this->funcList.size() >1) {
        for (UInt4 i=0; i<this->funcList.at(0).size(); ++i) {
            std::cout << setw(4*2) << " ";
            std::cout << string("function");
            std::cout << setw(5) << no;
            std::cout << setw(1) << ":";
            for (UInt4 j=0; j<this->funcList.size(); ++j) {
                std::cout << setw(1) << " ";
                std::cout << this->funcList.at(j).at(i)->getName();
                std::cout << "(" <<j <<")";
            }
            std::cout << endl;

            std::cout << setw(4*2) << " ";
            std::cout << setw(9)   << "seq. No.";
            for (UInt4 j=offset; j< offset+this->funcList.at(0).at(i)->getNumberOfParam(); ++j) {
                std::cout << setw(1) << " ";
                std::cout << setw(23) << setiosflags(std::ios::right) << j;
            }
            std::cout << endl;

            std::cout << setw(4*2) << " ";
            std::cout << setw(9)   << "parameter";
            for (UInt4 j=offset; j< offset+this->funcList.at(0).at(i)->getNumberOfParam(); ++j) {
                std::cout << setw(1) << " ";
                std::cout << setw(23) << setprecision(15) << setiosflags(std::ios::right) << this->param[j];
            }
            std::cout << endl;
            std::cout << endl;

            offset += this->funcList.at(0).at(i)->getNumberOfParam();
            ++no;
        }
    } else {
        // never reached
        ;
    }

    /*
    std::cout << setw(4)  << " ";
    std::cout << setw(4)  << " ";
    std::cout << setw(5)  << "No.";
    std::cout << setw(1)  << " ";
    std::cout << setw(23) << "value";
    std::cout << setw(1)  << " ";
    std::cout << setw(8)  << "function";
    std::cout << endl;

    UInt4 ct=0;
    for (std::vector<AdvFuncBase*>::const_iterator fp=this->funcList.begin(); fp != this->funcList.end(); ++fp) {
        for (UInt4 i=0; i<(*fp)->getNumberOfParam(); ++i) {
            std::cout << setw(4)  << " ";
            std::cout << setw(4)  << " ";
            std::cout << setw(5)  << ct;
            std::cout << setw(1)  << " ";
            std::cout << setw(23) << this->param[ct];
            if ( i==0) {
                std::cout << setw(1)  << " ";
                std::cout << (*fp)->getName().c_str();;
            }
            std::cout << endl;
            ++ct;
        }
        std::cout << endl;
    }
    */

    DebugMessage(className, memberName, "exit\n");
}

/**
 *  output the values of options for Levmar to the standard output
 *
 *  \param[in] control control parameters for Levmar
 */
void AdvLevmarArgs::outputOptions(const AdvLevmarControl &control) {
    string memberName=string("outputOptions(Double *)");
    DebugMessage(className, memberName, "enter\n");

    std::cout <<  resetiosflags(std::ios::right);

    std::cout << setw(4) << " ";
    std::cout << setw(4) << " ";
    std::cout << setw(44) << setiosflags(std::ios::left) << "initial value of scaling factor";
    std::cout << " : ";
    std::cout << this->opts[0];
    std::cout << endl;

    std::cout << endl;

    std::cout << setw(4) << " ";
    std::cout << setw(4) << " ";
    std::cout << setw(44) << setiosflags(std::ios::left) << "inf. norm of gradient (Jacobian)";
    std::cout << " : ";
    std::cout << this->opts[1];
    std::cout << endl;

    std::cout << setw(4) << " ";
    std::cout << setw(4) << " ";
    std::cout << setw(44) << setiosflags(std::ios::left) << "L2   norm of difference of fittingParameters";
    std::cout << " : ";
    std::cout << this->opts[2];
    std::cout << endl;

    std::cout << setw(4) << " ";
    std::cout << setw(4) << " ";
    std::cout << setw(44) << setiosflags(std::ios::left) << "L2   norm of residual error";
    std::cout << " : ";
    std::cout << this->opts[3];
    std::cout << endl;

    if (control.useNumericalDiff) {
        std::cout << setw(4) << " ";
        std::cout << setw(4) << " ";
        std::cout << setw(44) << setiosflags(std::ios::left) << "delta for numerical differentiation";
        std::cout << " : ";
        std::cout << this->opts[3];
        std::cout << endl;
    }

    std::cout << endl;

    DebugMessage(className, memberName, "exit\n");
}


void AdvLevmarArgs::outputAdditionalData() {
    string memberName=string("outputAdditionalData()");
    DebugMessage(className, memberName, "enter\n");
    
    std::cout <<  resetiosflags(std::ios::right);
    std::cout <<  resetiosflags(std::ios::left);
    std::cout <<  resetiosflags(std::ios::boolalpha);

    this->additionalData->output(8);
    /*
    std::cout << setw(4) << " " << setw(4) << " ";
    std::cout << setw(24) << setiosflags(std::ios::left) << "size of reference data";
    std::cout << " : ";
    std::cout << this->nRef;
    std::cout << endl;;

    std::cout << setw(4) << " " << setw(4) << " ";
    std::cout << setw(24) << setiosflags(std::ios::left) << "range of reference data";
    std::cout << " : [";
    std::cout << setw(13) << setprecision(5) << setiosflags(std::ios::right) << this->additionalData->x->front();
    std::cout << ", ";
    std::cout << setw(13) << setprecision(5) << setiosflags(std::ios::right) << this->additionalData->x->back();
    std::cout << "]";
    std::cout << endl;

    std::cout <<  resetiosflags(std::ios::right);

    std::cout << setw(4) << " " << setw(4) << " ";
    std::cout << setw(24) << setiosflags(std::ios::left) << "use weights";
    std::cout << " : ";
    std::cout << setw(5) << setiosflags(std::ios::boolalpha) << this->additionalData->useWeight;
    std::cout << endl;

    if (this->additionalData->useWeight) {
        std::cout << setw(4)  << " " << setw(4) << " ";
        std::cout << setw(24) << setiosflags(std::ios::left) << "size  of data weights";
        std::cout << " : ";
        std::cout << setw(5)  << this->additionalData->w->size();
        std::cout << endl;
    }
    std::cout << endl;
    */

    std::cout <<  resetiosflags(std::ios::right);
    std::cout <<  resetiosflags(std::ios::left);
    std::cout <<  resetiosflags(std::ios::boolalpha);

    DebugMessage(className, memberName, "exit\n");
}

void AdvLevmarArgs::outputReferenceData() {
    string memberName=string("outputRefereneceData()");
    DebugMessage(className, memberName, "enter\n");

    Int4 indent=8;

    Int4 offset=0;
    for (UInt4 i=0; i<this->funcList.size(); ++i) {
        vector<Double> *x=this->additionalData->funcEvalBaseList->at(i).x;
        vector<Double> *w=this->additionalData->funcEvalBaseList->at(i).w;
        for (UInt4 i=0; i<x->size(); ++i) {
            std::cout << setw(indent) << " ";
            std::cout << setw(5) << i;
            std::cout << setw(1) << " ";
            std::cout << setw(24) << setprecision(15) << setiosflags(std::ios::right) << x->at(i);
            std::cout << setw(1) << " ";
            std::cout << setw(24) << setprecision(15) << setiosflags(std::ios::right) << w->at(i);
            std::cout << setw(1) << " ";
            std::cout << setw(24) << setprecision(15) << setiosflags(std::ios::right) << this->ref[offset+i];
            std::cout << setw(1) << " ";
            std::cout << setw(24) << setprecision(15) << setiosflags(std::ios::right) << this->ref[offset+i]/w->at(i);
            std::cout << endl;
        }
        std::cout << endl;
        offset += x->size();
    }
    std::cout << endl;

    for (Int4 i=0; i<this->nRef; ++i) {
    }

    DebugMessage(className, memberName, "exit\n");
}
