1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2025-08-01 06:07:06 +01:00

reintegration of LatCore & folder restructuration

This commit is contained in:
2019-02-10 00:23:36 +00:00
parent 6addec5e14
commit 83d5428c3a
111 changed files with 6974 additions and 315 deletions

View File

@@ -0,0 +1,131 @@
/*
* CompiledFunction.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Functional/CompiledFunction.hpp>
#include <LatAnalyze/Core/Math.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* Compiled double function implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
CompiledDoubleFunction::CompiledDoubleFunction(const Index nArg)
: nArg_(nArg)
{}
CompiledDoubleFunction::CompiledDoubleFunction(const string &code,
const Index nArg)
: CompiledDoubleFunction(nArg)
{
setCode(code);
}
// access //////////////////////////////////////////////////////////////////////
string CompiledDoubleFunction::getCode(void)
{
return code_;
}
void CompiledDoubleFunction::setCode(const string &code)
{
code_ = code;
interpreter_.reset(new MathInterpreter(code));
context_.reset(new RunContext);
varAddress_.reset(new std::vector<unsigned int>);
isCompiled_.reset(new bool(false));
}
// compile /////////////////////////////////////////////////////////////////////
void CompiledDoubleFunction::compile(void) const
{
if (!*isCompiled_)
{
varAddress_->clear();
for (Index i = 0; i < nArg_; ++i)
{
varAddress_->push_back(context_->addVariable("x_" + strFrom(i)));
}
interpreter_->compile(*(context_));
*isCompiled_ = true;
}
}
// function call ///////////////////////////////////////////////////////////////
double CompiledDoubleFunction::operator()(const double *arg) const
{
double result;
compile();
for (unsigned int i = 0; i < nArg_; ++i)
{
context_->setVariable((*varAddress_)[i], arg[i]);
}
(*interpreter_)(*context_);
if (!context_->stack().empty())
{
result = context_->stack().top();
context_->stack().pop();
}
else
{
result = 0.0;
LATAN_ERROR(Program, "program execution resulted in an empty stack");
}
return result;
}
// IO //////////////////////////////////////////////////////////////////////////
ostream & Latan::operator<<(ostream &out, CompiledDoubleFunction &f)
{
f.compile();
out << *(f.interpreter_);
return out;
}
// DoubleFunction factory //////////////////////////////////////////////////////
DoubleFunction CompiledDoubleFunction::makeFunction(const bool makeHardCopy)
const
{
DoubleFunction res;
if (makeHardCopy)
{
CompiledDoubleFunction copy(*this);
res.setFunction([copy](const double *p){return copy(p);}, nArg_);
}
else
{
res.setFunction([this](const double *p){return (*this)(p);}, nArg_);
}
return res;
}
DoubleFunction Latan::compile(const string code, const Index nArg)
{
CompiledDoubleFunction compiledFunc(code, nArg);
return compiledFunc.makeFunction();
}

View File

@@ -0,0 +1,70 @@
/*
* CompiledFunction.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_CompiledFunction_hpp_
#define Latan_CompiledFunction_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Core/MathInterpreter.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* compiled double function class *
******************************************************************************/
class CompiledDoubleFunction: public DoubleFunctionFactory
{
public:
// constructors
explicit CompiledDoubleFunction(const Index nArg);
CompiledDoubleFunction(const std::string &code, const Index nArg);
// destructor
virtual ~CompiledDoubleFunction(void) = default;
// access
std::string getCode(void);
void setCode(const std::string &code);
// function call
double operator()(const double *arg) const;
// IO
friend std::ostream & operator<<(std::ostream &out,
CompiledDoubleFunction &f);
// factory
virtual DoubleFunction makeFunction(const bool makeHardCopy = true) const;
private:
// compile
void compile(void) const;
private:
Index nArg_;
std::string code_;
std::shared_ptr<MathInterpreter> interpreter_;
std::shared_ptr<RunContext> context_;
std::shared_ptr<std::vector<unsigned int>> varAddress_;
std::shared_ptr<bool> isCompiled_;
};
std::ostream & operator<<(std::ostream &out, CompiledDoubleFunction &f);
// DoubleFunction factory
DoubleFunction compile(const std::string code, const Index nArg);
END_LATAN_NAMESPACE
#endif // Latan_CompiledFunction_hpp_

View File

@@ -0,0 +1,145 @@
/*
* CompiledModel.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Functional/CompiledModel.hpp>
#include <LatAnalyze/Core/Math.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* CompiledDoubleModel implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
CompiledDoubleModel::CompiledDoubleModel(const Index nArg, const Index nPar)
: nArg_(nArg)
, nPar_(nPar)
{}
CompiledDoubleModel::CompiledDoubleModel(const string &code, const Index nArg,
const Index nPar)
: CompiledDoubleModel(nArg, nPar)
{
setCode(code);
}
// access //////////////////////////////////////////////////////////////////////
string CompiledDoubleModel::getCode(void)
{
return code_;
}
void CompiledDoubleModel::setCode(const std::string &code)
{
code_ = code;
interpreter_.reset(new MathInterpreter(code_));
context_.reset(new RunContext);
varAddress_.reset(new std::vector<unsigned int>);
parAddress_.reset(new std::vector<unsigned int>);
isCompiled_.reset(new bool(false));
}
// compile /////////////////////////////////////////////////////////////////////
void CompiledDoubleModel::compile(void) const
{
if (!*isCompiled_)
{
varAddress_->clear();
parAddress_->clear();
for (Index i = 0; i < nArg_; ++i)
{
varAddress_->push_back(context_->addVariable("x_" + strFrom(i)));
}
for (Index j = 0; j < nPar_; ++j)
{
parAddress_->push_back(context_->addVariable("p_" + strFrom(j)));
}
interpreter_->compile(*(context_));
*isCompiled_ = true;
}
}
// function call ///////////////////////////////////////////////////////////////
double CompiledDoubleModel::operator()(const double *arg,
const double *par) const
{
double result;
compile();
for (unsigned int i = 0; i < nArg_; ++i)
{
context_->setVariable((*varAddress_)[i], arg[i]);
}
for (unsigned int j = 0; j < nPar_; ++j)
{
context_->setVariable((*parAddress_)[j], par[j]);
}
(*interpreter_)(*context_);
if (!context_->stack().empty())
{
result = context_->stack().top();
context_->stack().pop();
}
else
{
result = 0.0;
LATAN_ERROR(Program, "program execution resulted in an empty stack");
}
return result;
}
// IO //////////////////////////////////////////////////////////////////////////
ostream & Latan::operator<<(std::ostream &out, CompiledDoubleModel &m)
{
m.compile();
out << *(m.interpreter_);
return out;
}
// DoubleModel factory /////////////////////////////////////////////////////////
DoubleModel CompiledDoubleModel::makeModel(const bool makeHardCopy) const
{
DoubleModel res;
if (makeHardCopy)
{
CompiledDoubleModel copy(*this);
res.setFunction([copy](const double *x, const double *p)
{return copy(x, p);}, nArg_, nPar_);
}
else
{
res.setFunction([this](const double *x, const double *p)
{return (*this)(x, p);}, nArg_, nPar_);
}
return res;
}
DoubleModel Latan::compile(const std::string &code, const Index nArg,
const Index nPar)
{
CompiledDoubleModel compiledModel(code, nArg, nPar);
return compiledModel.makeModel();
}

View File

@@ -0,0 +1,71 @@
/*
* CompiledModel.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_CompiledModel_hpp_
#define Latan_CompiledModel_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Model.hpp>
#include <LatAnalyze/Core/MathInterpreter.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* compiled double model class *
******************************************************************************/
class CompiledDoubleModel: public DoubleModelFactory
{
public:
// constructor
CompiledDoubleModel(const Index nArg, const Index nPar);
CompiledDoubleModel(const std::string &code, const Index nArg,
const Index nPar);
// destructor
virtual ~CompiledDoubleModel(void) = default;
// access
std::string getCode(void);
void setCode(const std::string &code);
// function call
double operator()(const double *arg, const double *par) const;
// IO
friend std::ostream & operator<<(std::ostream &out,
CompiledDoubleModel &f);
// factory
DoubleModel makeModel(const bool makeHardCopy = true) const;
private:
// compile
void compile(void) const;
private:
Index nArg_, nPar_;
std::string code_;
std::shared_ptr<MathInterpreter> interpreter_;
std::shared_ptr<RunContext> context_;
std::shared_ptr<std::vector<unsigned int>> varAddress_, parAddress_;
std::shared_ptr<bool> isCompiled_;
};
std::ostream & operator<<(std::ostream &out, CompiledDoubleModel &f);
// DoubleModel factory
DoubleModel compile(const std::string &code, const Index nArg,
const Index nPar);
END_LATAN_NAMESPACE
#endif // Latan_CompiledModel_hpp_

282
lib/Functional/Function.cpp Normal file
View File

@@ -0,0 +1,282 @@
/*
* Function.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* DoubleFunction implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
DoubleFunction::DoubleFunction(const vecFunc &f, const Index nArg)
: buffer_(new DVec)
, varName_("x")
{
setFunction(f, nArg);
}
// access //////////////////////////////////////////////////////////////////////
Index DoubleFunction::getNArg(void) const
{
return buffer_->size();
}
void DoubleFunction::setFunction(const vecFunc &f, const Index nArg)
{
buffer_->resize(nArg);
f_ = f;
}
VarName & DoubleFunction::varName(void)
{
return varName_;
}
const VarName & DoubleFunction::varName(void) const
{
return varName_;
}
// error checking //////////////////////////////////////////////////////////////
void DoubleFunction::checkSize(const Index nPar) const
{
if (nPar != getNArg())
{
LATAN_ERROR(Size, "function argument vector has a wrong size (expected "
+ strFrom(getNArg()) + ", got " + strFrom(nPar)
+ ")");
}
}
// function call ///////////////////////////////////////////////////////////////
double DoubleFunction::operator()(const double *arg) const
{
return f_(arg);
}
double DoubleFunction::operator()(const DVec &arg) const
{
checkSize(arg.size());
return (*this)(arg.data());
}
double DoubleFunction::operator()(const std::vector<double> &arg) const
{
checkSize(static_cast<Index>(arg.size()));
return (*this)(arg.data());
}
double DoubleFunction::operator()(std::stack<double> &arg) const
{
for (Index i = 0; i < getNArg(); ++i)
{
if (arg.empty())
{
LATAN_ERROR(Size, "function argument stack is empty (expected "
+ strFrom(getNArg()) + "arguments, got " + strFrom(i)
+ ")");
}
(*buffer_)(getNArg() - i - 1) = arg.top();
arg.pop();
}
return (*this)(*buffer_);
}
double DoubleFunction::operator()(void) const
{
checkSize(0);
return (*this)(nullptr);
}
// bind ////////////////////////////////////////////////////////////////////////
DoubleFunction DoubleFunction::bind(const Index argIndex,
const double val) const
{
Index nArg = getNArg();
shared_ptr<DVec> buf(new DVec(nArg));
DoubleFunction copy(*this), bindFunc;
auto func = [copy, buf, argIndex, val](const double *arg)
{
FOR_VEC(*buf, i)
{
if (i < argIndex)
{
(*buf)(i) = arg[i];
}
else if (i == argIndex)
{
(*buf)(i) = val;
}
else
{
(*buf)(i) = arg[i - 1];
}
}
return copy(*buf);
};
bindFunc.setFunction(func, nArg - 1);
return bindFunc;
}
DoubleFunction DoubleFunction::bind(const Index argIndex,
const DVec &x) const
{
Index nArg = getNArg();
shared_ptr<DVec> buf(new DVec(nArg));
DoubleFunction copy(*this), bindFunc;
auto func = [copy, buf, argIndex, x](const double *arg)
{
*buf = x;
(*buf)(argIndex) = arg[0];
return copy(*buf);
};
bindFunc.setFunction(func, 1);
return bindFunc;
}
// arithmetic operators ////////////////////////////////////////////////////////
DoubleFunction DoubleFunction::operator-(void) const
{
DoubleFunction copy(*this), resFunc;
return DoubleFunction([copy](const double *arg){return -copy(arg);},
getNArg());
}
#define MAKE_SELF_FUNC_OP(op)\
DoubleFunction & DoubleFunction::operator op##=(const DoubleFunction &f)\
{\
DoubleFunction copy(*this);\
checkSize(f.getNArg());\
auto res = [f, copy](const double *arg){return copy(arg) op f(arg);};\
setFunction(res, getNArg());\
return *this;\
}\
DoubleFunction & DoubleFunction::operator op##=(const DoubleFunction and f)\
{\
*this op##= f;\
return *this;\
}
#define MAKE_SELF_SCALAR_OP(op)\
DoubleFunction & DoubleFunction::operator op##=(const double x)\
{\
DoubleFunction copy(*this);\
auto res = [x, copy](const double *arg){return copy(arg) op x;};\
setFunction(res, getNArg());\
return *this;\
}\
MAKE_SELF_FUNC_OP(+)
MAKE_SELF_FUNC_OP(-)
MAKE_SELF_FUNC_OP(*)
MAKE_SELF_FUNC_OP(/)
MAKE_SELF_SCALAR_OP(+)
MAKE_SELF_SCALAR_OP(-)
MAKE_SELF_SCALAR_OP(*)
MAKE_SELF_SCALAR_OP(/)
/******************************************************************************
* DoubleFunctionSample implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
DoubleFunctionSample::DoubleFunctionSample(void)
: Sample<DoubleFunction>()
{}
DoubleFunctionSample::DoubleFunctionSample(const Index nSample)
: Sample<DoubleFunction>(nSample)
{}
// function call ///////////////////////////////////////////////////////////////
DSample DoubleFunctionSample::operator()(const DMatSample &arg) const
{
DSample result(size());
FOR_STAT_ARRAY((*this), s)
{
result[s] = (*this)[s](arg[s]);
}
return result;
}
DSample DoubleFunctionSample::operator()(const double *arg) const
{
DSample result(size());
FOR_STAT_ARRAY((*this), s)
{
result[s] = (*this)[s](arg);
}
return result;
}
DSample DoubleFunctionSample::operator()(const DVec &arg) const
{
return (*this)(arg.data());
}
DSample DoubleFunctionSample::operator()(const vector<double> &arg) const
{
return (*this)(arg.data());
}
// bind ////////////////////////////////////////////////////////////////////////
DoubleFunctionSample DoubleFunctionSample::bind(const Index argIndex,
const double val) const
{
DoubleFunctionSample bindFunc(size());
FOR_STAT_ARRAY(bindFunc, s)
{
bindFunc[s] = (*this)[s].bind(argIndex, val);
}
return bindFunc;
}
DoubleFunctionSample DoubleFunctionSample::bind(const Index argIndex,
const DVec &x) const
{
DoubleFunctionSample bindFunc(size());
FOR_STAT_ARRAY(bindFunc, s)
{
bindFunc[s] = (*this)[s].bind(argIndex, x);
}
return bindFunc;
}

204
lib/Functional/Function.hpp Normal file
View File

@@ -0,0 +1,204 @@
/*
* Function.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Function_hpp_
#define Latan_Function_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Core/Mat.hpp>
#include <LatAnalyze/Statistics/MatSample.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Double function class *
******************************************************************************/
class DoubleFunction
{
private:
// function type
typedef std::function<double(const double *)> vecFunc;
public:
// constructor
explicit DoubleFunction(const vecFunc &f = nullptr, const Index nArg = 0);
// destructor
virtual ~DoubleFunction(void) = default;
// access
virtual Index getNArg(void) const;
void setFunction(const vecFunc &f, const Index nArg);
VarName & varName(void);
const VarName & varName(void) const;
// function call
double operator()(const double *arg) const;
double operator()(const DVec &arg) const;
double operator()(const std::vector<double> &arg) const;
double operator()(std::stack<double> &arg) const;
double operator()(void) const;
template <typename... Ts>
double operator()(const double arg0, const Ts... args) const;
// bind
DoubleFunction bind(const Index argIndex, const double val) const;
DoubleFunction bind(const Index argIndex, const DVec &x) const;
// arithmetic operators
DoubleFunction operator-(void) const;
DoubleFunction & operator+=(const DoubleFunction &f);
DoubleFunction & operator+=(const DoubleFunction &&f);
DoubleFunction & operator-=(const DoubleFunction &f);
DoubleFunction & operator-=(const DoubleFunction &&f);
DoubleFunction & operator*=(const DoubleFunction &f);
DoubleFunction & operator*=(const DoubleFunction &&f);
DoubleFunction & operator/=(const DoubleFunction &f);
DoubleFunction & operator/=(const DoubleFunction &&f);
DoubleFunction & operator+=(const double x);
DoubleFunction & operator-=(const double x);
DoubleFunction & operator*=(const double x);
DoubleFunction & operator/=(const double x);
private:
// error checking
void checkSize(const Index nPar) const;
private:
std::shared_ptr<DVec> buffer_{nullptr};
VarName varName_;
vecFunc f_;
};
/******************************************************************************
* DoubleFunction template implementation *
******************************************************************************/
template <typename... Ts>
double DoubleFunction::operator()(const double arg0, const Ts... args) const
{
static_assert(static_or<std::is_convertible<double, Ts>::value...>::value,
"DoubleFunction arguments are not compatible with double");
const double arg[] = {arg0, static_cast<double>(args)...};
checkSize(sizeof...(args) + 1);
return (*this)(arg);
}
/******************************************************************************
* DoubleFunction inline arithmetic operators *
******************************************************************************/
#define MAKE_INLINE_FUNC_OP(op)\
inline DoubleFunction operator op(DoubleFunction lhs,\
const DoubleFunction &rhs)\
{\
lhs op##= rhs;\
return lhs;\
}\
inline DoubleFunction operator op(DoubleFunction lhs,\
const DoubleFunction &&rhs)\
{\
return lhs op rhs;\
}
#define MAKE_INLINE_RSCALAR_OP(op)\
inline DoubleFunction operator op(DoubleFunction lhs, const double rhs)\
{\
lhs op##= rhs;\
return lhs;\
}\
#define MAKE_INLINE_LSCALAR_OP(op)\
inline DoubleFunction operator op(const double lhs, DoubleFunction rhs)\
{\
rhs op##= lhs;\
return rhs;\
}
MAKE_INLINE_FUNC_OP(+)
MAKE_INLINE_FUNC_OP(-)
MAKE_INLINE_FUNC_OP(*)
MAKE_INLINE_FUNC_OP(/)
MAKE_INLINE_RSCALAR_OP(+)
MAKE_INLINE_RSCALAR_OP(-)
MAKE_INLINE_RSCALAR_OP(*)
MAKE_INLINE_RSCALAR_OP(/)
MAKE_INLINE_LSCALAR_OP(+)
MAKE_INLINE_LSCALAR_OP(*)
// special case for scalar - function
inline DoubleFunction operator-(const double lhs, DoubleFunction rhs)
{
return (-rhs) + lhs;
}
// special case for scalar/function
inline DoubleFunction operator/(const double lhs, DoubleFunction rhs)
{
auto res = [lhs, rhs](const double *arg){return lhs/rhs(arg);};
rhs.setFunction(res, rhs.getNArg());
return rhs;
}
/******************************************************************************
* DoubleFunctionSample class *
******************************************************************************/
class DoubleFunctionSample: public Sample<DoubleFunction>
{
public:
// constructors
DoubleFunctionSample(void);
DoubleFunctionSample(const Index nSample);
EIGEN_EXPR_CTOR(DoubleFunctionSample, DoubleFunctionSample,
Sample<DoubleFunction>, ArrayExpr)
// destructor
virtual ~DoubleFunctionSample(void) = default;
// function call
DSample operator()(const DMatSample &arg) const;
DSample operator()(const double *arg) const;
DSample operator()(const DVec &arg) const;
DSample operator()(const std::vector<double> &arg) const;
template <typename... Ts>
DSample operator()(const double arg0, const Ts... args) const;
// bind
DoubleFunctionSample bind(const Index argIndex, const double val) const;
DoubleFunctionSample bind(const Index argIndex, const DVec &x) const ;
};
template <typename... Ts>
DSample DoubleFunctionSample::operator()(const double arg0,
const Ts... args) const
{
const double arg[] = {arg0, static_cast<double>(args)...};
return (*this)(arg);
}
/******************************************************************************
* DoubleFunctionFactory class *
******************************************************************************/
class DoubleFunctionFactory
{
public:
// constructor
DoubleFunctionFactory(void) = default;
// destructor
virtual ~DoubleFunctionFactory(void) = default;
// factory
virtual DoubleFunction makeFunction(const bool makeHardCopy) const = 0;
};
END_LATAN_NAMESPACE
#endif // Latan_Function_hpp_

150
lib/Functional/Model.cpp Normal file
View File

@@ -0,0 +1,150 @@
/*
* Model.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Functional/Model.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace std::placeholders;
using namespace Latan;
/******************************************************************************
* Model implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
DoubleModel::DoubleModel(const vecFunc &f, const Index nArg, const Index nPar)
: size_(new ModelSize)
, varName_("x")
, parName_("p")
{
setFunction(f, nArg, nPar);
}
// access //////////////////////////////////////////////////////////////////////
Index DoubleModel::getNArg(void) const
{
return size_->nArg;
}
Index DoubleModel::getNPar(void) const
{
return size_->nPar;
}
void DoubleModel::setFunction(const vecFunc &f, const Index nArg,
const Index nPar)
{
size_->nArg = nArg;
size_->nPar = nPar;
f_ = f;
}
VarName & DoubleModel::varName(void)
{
return varName_;
}
const VarName & DoubleModel::varName(void) const
{
return varName_;
}
VarName & DoubleModel::parName(void)
{
return parName_;
}
const VarName & DoubleModel::parName(void) const
{
return parName_;
}
// error checking //////////////////////////////////////////////////////////////
void DoubleModel::checkSize(const Index nArg, const Index nPar) const
{
if (nArg != getNArg())
{
LATAN_ERROR(Size, "model argument vector has a wrong size (expected "
+ strFrom(getNArg()) + ", got " + strFrom(nArg)
+ ")");
}
if (nPar != getNPar())
{
LATAN_ERROR(Size, "model parameter vector has a wrong size (expected "
+ strFrom(getNPar()) + ", got " + strFrom(nPar)
+ ")");
}
}
// function call ///////////////////////////////////////////////////////////////
double DoubleModel::operator()(const DVec &arg, const DVec &par) const
{
checkSize(arg.size(), par.size());
return (*this)(arg.data(), par.data());
}
double DoubleModel::operator()(const vector<double> &arg,
const vector<double> &par) const
{
checkSize(static_cast<Index>(arg.size()), static_cast<Index>(par.size()));
return (*this)(arg.data(), par.data());
}
double DoubleModel::operator()(const double *data, const double *par) const
{
return f_(data, par);
}
// model bind //////////////////////////////////////////////////////////////////
DoubleFunction DoubleModel::fixArg(const DVec &arg) const
{
DoubleModel copy(*this);
auto modelWithVec = [copy](const DVec &x, const double *p)
{
return copy(x.data(), p);
};
auto modelBind = bind(modelWithVec, arg, _1);
return DoubleFunction(modelBind, getNPar());
}
DoubleFunction DoubleModel::fixPar(const DVec &par) const
{
DoubleModel copy(*this);
auto modelWithVec = [copy](const double *x, const DVec &p)
{
return copy(x, p.data());
};
auto modelBind = bind(modelWithVec, _1, par);
return DoubleFunction(modelBind, getNArg());
}
DoubleFunction DoubleModel::toFunction(void) const
{
DoubleModel copy(*this);
auto func = [copy](const double *x){return copy(x, x + copy.getNArg());};
return DoubleFunction(func, getNArg() + getNPar());
}

87
lib/Functional/Model.hpp Normal file
View File

@@ -0,0 +1,87 @@
/*
* Model.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Model_hpp_
#define Latan_Model_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Core/Mat.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Double model class *
******************************************************************************/
class DoubleModel
{
public:
typedef std::function<double(const double *, const double *)> vecFunc;
private:
struct ModelSize{Index nArg, nPar;};
public:
// constructor
DoubleModel(const vecFunc &f = nullptr, const Index nArg = 0,
const Index nPar = 0);
// destructor
virtual ~DoubleModel(void) = default;
// access
virtual Index getNArg(void) const;
virtual Index getNPar(void) const;
void setFunction(const vecFunc &f, const Index nArg,
const Index nPar);
VarName & varName(void);
const VarName & varName(void) const;
VarName & parName(void);
const VarName & parName(void) const;
// function call
double operator()(const DVec &data, const DVec &par) const;
double operator()(const std::vector<double> &data,
const std::vector<double> &par) const;
double operator()(const double *data, const double *par) const;
// bind
DoubleFunction fixArg(const DVec &arg) const;
DoubleFunction fixPar(const DVec &par) const;
DoubleFunction toFunction(void) const;
private:
// error checking
void checkSize(const Index nArg, const Index nPar) const;
private:
std::shared_ptr<ModelSize> size_;
VarName varName_, parName_;
vecFunc f_;
};
/******************************************************************************
* base class for model factories *
******************************************************************************/
class DoubleModelFactory
{
public:
// constructor
DoubleModelFactory(void) = default;
// destructor
virtual ~DoubleModelFactory(void) = default;
// factory
virtual DoubleModel makeModel(const bool makeHardCopy) const = 0;
};
END_LATAN_NAMESPACE
#endif // Latan_Model_hpp_

View File

@@ -0,0 +1,164 @@
/*
* TabFunction.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Functional/TabFunction.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* TabFunction implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
TabFunction::TabFunction(const DVec &x, const DVec &y,
const InterpType interpType)
{
setData(x, y);
setInterpolationType(interpType);
}
// access //////////////////////////////////////////////////////////////////////
void TabFunction::setData(const DVec &x, const DVec &y)
{
if (x.size() != y.size())
{
LATAN_ERROR(Size, "tabulated function x/y data size mismatch");
}
FOR_VEC(x, i)
{
value_[x(i)] = y(i);
}
}
void TabFunction::setInterpolationType(const InterpType interpType)
{
interpType_ = interpType;
}
// function call ///////////////////////////////////////////////////////////////
double TabFunction::operator()(const double *arg) const
{
double result = 0.0, x = arg[0];
if ((x < value_.begin()->first) or (x >= value_.rbegin()->first)) {
LATAN_ERROR(Range, "tabulated function variable out of range "
"(x= " + strFrom(x) + " not in ["
+ strFrom(value_.begin()->first) + ", "
+ strFrom(value_.rbegin()->first) + "])");
}
auto i = value_.equal_range(x);
auto low = (x == i.first->first) ? i.first : prev(i.first);
auto high = i.second;
switch (interpType_) {
case InterpType::LINEAR: {
double x_a, x_b, y_a, y_b;
x_a = low->first;
x_b = high->first;
y_a = low->second;
y_b = high->second;
result = y_a + (x - x_a) * (y_b - y_a) / (x_b - x_a);
break;
}
case InterpType::NEAREST: {
result = nearest(x)->second;
break;
}
case InterpType::QUADRATIC: {
double xs[3], ys[3], ds[3], d01, d02, d12;
auto it = nearest(x);
if (it == value_.begin()) {
it = next(it);
}
else if (it == prev(value_.end())) {
it = prev(it);
}
xs[0] = prev(it)->first;
ys[0] = prev(it)->second;
xs[1] = it->first;
ys[1] = it->second;
xs[2] = next(it)->first;
ys[2] = next(it)->second;
ds[0] = x - xs[0];
ds[1] = x - xs[1];
ds[2] = x - xs[2];
d01 = xs[0] - xs[1];
d02 = xs[0] - xs[2];
d12 = xs[1] - xs[2];
// Lagrange polynomial coefficient computation
result = ds[1]/d01*ds[2]/d02*ys[0]
-ds[0]/d01*ds[2]/d12*ys[1]
+ds[0]/d02*ds[1]/d12*ys[2];
break;
}
default:
int intType = static_cast<int>(interpType_);
LATAN_ERROR(Implementation, "unsupported interpolation type in "
"tabulated function: "
+ strFrom(intType));
}
return result;
}
// DoubleFunction factory //////////////////////////////////////////////////////
DoubleFunction TabFunction::makeFunction(const bool makeHardCopy) const
{
DoubleFunction res;
if (makeHardCopy)
{
TabFunction copy(*this);
res.setFunction([copy](const double *x){return copy(x);}, 1);
}
else
{
res.setFunction([this](const double *x){return (*this)(x);}, 1);
}
return res;
}
DoubleFunction Latan::interpolate(const DVec &x, const DVec &y,
const InterpType interpType)
{
return TabFunction(x, y, interpType).makeFunction();
}
map<double, double>::const_iterator TabFunction::nearest(const double x) const
{
map<double, double>::const_iterator ret;
auto i = value_.equal_range(x);
auto low = (x == i.first->first) ? i.first : prev(i.first);
auto high = i.second;
if (fabs(high->first - x) < fabs(low->first - x)) {
ret = high;
}
else {
ret = low;
}
return ret;
}

View File

@@ -0,0 +1,69 @@
/*
* TabFunction.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2016 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_TabFunction_hpp_
#define Latan_TabFunction_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Core/Math.hpp>
#include <LatAnalyze/Statistics/XYStatData.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* tabulated function: 1D only *
******************************************************************************/
enum class InterpType
{
NEAREST,
LINEAR,
QUADRATIC
};
class TabFunction: public DoubleFunctionFactory
{
public:
// constructors
TabFunction(void) = default;
TabFunction(const DVec &x, const DVec &y,
const InterpType interpType = InterpType::LINEAR);
// destructor
virtual ~TabFunction(void) = default;
// access
void setData(const DVec &x, const DVec &y);
void setInterpolationType(const InterpType interpType);
// function call
double operator()(const double *arg) const;
// factory
virtual DoubleFunction makeFunction(const bool makeHardCopy = true) const;
private:
std::map<double, double>::const_iterator nearest(const double x) const;
std::map<double, double> value_;
InterpType interpType_;
};
DoubleFunction interpolate(const DVec &x, const DVec &y,
const InterpType interpType = InterpType::LINEAR);
END_LATAN_NAMESPACE
#endif // Latan_TabFunction_hpp_