1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2025-06-17 14:57:05 +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

123
lib/Core/Eigen.hpp Normal file
View File

@ -0,0 +1,123 @@
/*
* Eigen.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/>.
*/
// Eigen inclusion
#define EIGEN_DONT_PARALLELIZE
#define EIGEN_MATRIXBASE_PLUGIN <LatAnalyze/Core/EigenPlugin.hpp>
#include <LatAnalyze/Eigen/Dense>
// copy/assignement from Eigen expression
#define EIGEN_EXPR_CTOR(ctorName, Class, Base, ExprType) \
template <typename Derived>\
ctorName(const ExprType<Derived> &m): Base(m) {}\
template<typename Derived>\
Class & operator=(const ExprType<Derived> &m)\
{\
this->Base::operator=(m);\
return *this;\
}
#define FOR_MAT(mat, i, j) \
for (Latan::Index j = 0; j < mat.cols(); ++j)\
for (Latan::Index i = 0; i < mat.rows(); ++i)
BEGIN_LATAN_NAMESPACE
const int dynamic = Eigen::Dynamic;
// array types
template <typename Derived>
using ArrayExpr = Eigen::ArrayBase<Derived>;
template <typename T, int nRow = dynamic, int nCol = dynamic>
using Array = Eigen::Array<T, nRow, nCol>;
// matrix types
template <typename Derived>
using MatExpr = Eigen::MatrixBase<Derived>;
template <typename T, int nRow = dynamic, int nCol = dynamic>
using MatBase = Eigen::Matrix<T, nRow, nCol>;
template <int nRow, int nCol>
using SFMat = Eigen::Matrix<float, nRow, nCol>;
template <int nRow, int nCol>
using SDMat = Eigen::Matrix<double, nRow, nCol>;
template <int nRow, int nCol>
using SCMat = Eigen::Matrix<std::complex<double>, nRow, nCol>;
// vector types
template <typename T, int size = dynamic>
using Vec = MatBase<T, size, 1>;
template <int size>
using SIVec = Vec<int, size>;
template <int size>
using SUVec = Vec<unsigned int, size>;
template <int size>
using SFVec = Vec<float, size>;
template <int size>
using SDVec = Vec<double, size>;
template <int size>
using SCVec = Vec<std::complex<double>, size>;
typedef SIVec<dynamic> IVec;
typedef SUVec<dynamic> UVec;
typedef SDVec<dynamic> DVec;
typedef SCVec<dynamic> CVec;
// block types
template <typename Derived>
using Block = Eigen::Block<Derived>;
template <typename Derived>
using ConstBlock = const Eigen::Block<const Derived>;
template <typename Derived>
using Row = typename Derived::RowXpr;
template <typename Derived>
using ConstRow = typename Derived::ConstRowXpr;
template <typename Derived>
using Col = typename Derived::ColXpr;
template <typename Derived>
using ConstCol = typename Derived::ConstColXpr;
// map type
template <int stride>
using InnerStride = Eigen::InnerStride<stride>;
template <int rowStride, int colStride>
using Stride = Eigen::Stride<rowStride, colStride>;
template <typename Derived, typename StrideType = Stride<0, 0>>
using Map = Eigen::Map<Derived, Eigen::Unaligned, StrideType>;
template <typename Derived, typename StrideType = Stride<0, 0>>
using ConstMap = Eigen::Map<const Derived, Eigen::Unaligned, StrideType>;
// Index type //////////////////////////////////////////////////////////////////
typedef MatBase<int>::Index Index;
#define FOR_VEC(vec, i) for (Latan::Index i = 0; i < (vec).size(); ++i)
#define FOR_ARRAY(ar, i) FOR_VEC(ar, i)
END_LATAN_NAMESPACE

60
lib/Core/EigenPlugin.hpp Normal file
View File

@ -0,0 +1,60 @@
/*
* EigenPlugin.hpp, part of LatAnalyze
*
* Copyright (C) 2015 Antonin Portelli
*
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
*/
Derived pInverse(const double tolerance = 1.0e-10)
{
auto svd = jacobiSvd(Eigen::ComputeThinU|Eigen::ComputeThinV);
const auto u = svd.matrixU();
const auto v = svd.matrixV();
auto s = svd.singularValues();
double maxsv = 0.;
unsigned int elim = 0;
for (Index i = 0; i < s.rows(); ++i)
{
if (fabs(s(i)) > maxsv) maxsv = fabs(s(i));
}
for (Index i = 0; i < s.rows(); ++i)
{
if (fabs(s(i)) > maxsv*tolerance)
{
s(i) = 1./s(i);
}
else
{
elim++;
s(i) = 0.;
}
}
if (elim)
{
std::cerr << "warning: pseudoinverse: " << elim << "/";
std::cerr << s.rows() << " singular value(s) eliminated (tolerance= ";
std::cerr << tolerance << ")" << std::endl;
}
return v*s.asDiagonal()*u.transpose();
}
Derived singularValues(void)
{
auto svd = jacobiSvd();
return svd.singularValues();
}

51
lib/Core/Exceptions.cpp Normal file
View File

@ -0,0 +1,51 @@
/*
* Exceptions.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/Core/Exceptions.hpp>
#include <LatAnalyze/includes.hpp>
#ifndef ERR_SUFF
#define ERR_SUFF " (" + loc + ")"
#endif
#define CONST_EXC(name, init) \
name::name(string msg, string loc)\
:init\
{}
using namespace std;
using namespace Latan;
using namespace Exceptions;
// logic errors
CONST_EXC(Logic, logic_error(Env::msgPrefix + msg + ERR_SUFF))
CONST_EXC(Definition, Logic("definition error: " + msg, loc))
CONST_EXC(Implementation, Logic("implementation error: " + msg, loc))
CONST_EXC(Range, Logic("range error: " + msg, loc))
CONST_EXC(Size, Logic("size error: " + msg, loc))
// runtime errors
CONST_EXC(Runtime, runtime_error(Env::msgPrefix + msg + ERR_SUFF))
CONST_EXC(Argument, Runtime("argument error: " + msg, loc))
CONST_EXC(Compilation, Runtime("compilation error: " + msg, loc))
CONST_EXC(Io, Runtime("IO error: " + msg, loc))
CONST_EXC(Memory, Runtime("memory error: " + msg, loc))
CONST_EXC(Parsing, Runtime(msg, loc))
CONST_EXC(Program, Runtime(msg, loc))
CONST_EXC(Syntax, Runtime("syntax error: " + msg, loc))
CONST_EXC(System, Runtime("system error: " + msg, loc))

66
lib/Core/Exceptions.hpp Normal file
View File

@ -0,0 +1,66 @@
/*
* Exceptions.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_Exceptions_hpp_
#define Latan_Exceptions_hpp_
#include <stdexcept>
#ifndef LATAN_GLOBAL_HPP_
#include <LatAnalyze/Global.hpp>
#endif
#define SRC_LOC strFrom(__FUNCTION__) + " at " + strFrom(__FILE__) + ":"\
+ strFrom(__LINE__)
#define LATAN_ERROR(exc,msg) throw(Exceptions::exc(msg, SRC_LOC))
#define LATAN_WARNING(msg) \
std::cerr << Env::msgPrefix << "warning: " << msg\
<< " (" << SRC_LOC << ")" << std::endl
#define DECL_EXC(name, base) \
class name: public base\
{\
public:\
name(std::string msg, std::string loc);\
}
BEGIN_LATAN_NAMESPACE
namespace Exceptions
{
// logic errors
DECL_EXC(Logic, std::logic_error);
DECL_EXC(Definition, Logic);
DECL_EXC(Implementation, Logic);
DECL_EXC(Range, Logic);
DECL_EXC(Size, Logic);
// runtime errors
DECL_EXC(Runtime, std::runtime_error);
DECL_EXC(Argument, Runtime);
DECL_EXC(Compilation, Runtime);
DECL_EXC(Io, Runtime);
DECL_EXC(Memory, Runtime);
DECL_EXC(Parsing, Runtime);
DECL_EXC(Program, Runtime);
DECL_EXC(Syntax, Runtime);
DECL_EXC(System, Runtime);
}
END_LATAN_NAMESPACE
#endif // Latan_Exceptions_hpp_

36
lib/Core/Mat.cpp Normal file
View File

@ -0,0 +1,36 @@
/*
* Mat.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/Core/Mat.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
/******************************************************************************
* DMat implementation *
******************************************************************************/
// IO //////////////////////////////////////////////////////////////////////////
namespace Latan
{
template <>
IoObject::IoType Mat<double>::getType(void) const
{
return IoType::dMat;
}
}

69
lib/Core/Mat.hpp Normal file
View File

@ -0,0 +1,69 @@
/*
* Mat.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_Mat_hpp_
#define Latan_Mat_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Io/IoObject.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* matrix type *
******************************************************************************/
template <typename T>
class Mat: public MatBase<T>, public IoObject
{
public:
// constructors
Mat(void) = default;
Mat(const Index nRow, const Index nCol);
EIGEN_EXPR_CTOR(Mat, Mat<T>, MatBase<T>, MatExpr)
// destructor
virtual ~Mat(void) = default;
// IO
virtual IoType getType(void) const;
};
// type aliases
typedef Mat<int> IMat;
typedef Mat<long int> LMat;
typedef Mat<double> DMat;
typedef Mat<std::complex<double>> CMat;
/******************************************************************************
* Mat template implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
template <typename T>
Mat<T>::Mat(const Index nRow, const Index nCol)
: MatBase<T>(nRow, nCol)
{}
// IO //////////////////////////////////////////////////////////////////////////
template <typename T>
IoObject::IoType Mat<T>::getType(void) const
{
return IoType::noType;
}
END_LATAN_NAMESPACE
#endif // Latan_Mat_hpp_

114
lib/Core/Math.cpp Normal file
View File

@ -0,0 +1,114 @@
/*
* Math.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/Core/Math.hpp>
#include <LatAnalyze/includes.hpp>
#include <gsl/gsl_cdf.h>
using namespace std;
using namespace Latan;
/******************************************************************************
* Custom math functions *
******************************************************************************/
DMat MATH_NAMESPACE::varToCorr(const DMat &var)
{
DMat res = var, invDiag = res.diagonal();
invDiag = invDiag.cwiseInverse().cwiseSqrt();
res = (invDiag*invDiag.transpose()).cwiseProduct(res);
return res;
}
/******************************************************************************
* Standard C functions *
******************************************************************************/
#define DEF_STD_FUNC_1ARG(name) \
auto name##VecFunc = [](const double arg[1]){return (name)(arg[0]);};\
DoubleFunction STDMATH_NAMESPACE::name(name##VecFunc, 1);
#define DEF_STD_FUNC_2ARG(name) \
auto name##VecFunc = [](const double arg[2]){return (name)(arg[0], arg[1]);};\
DoubleFunction STDMATH_NAMESPACE::name(name##VecFunc, 2);
// Trigonometric functions
DEF_STD_FUNC_1ARG(cos)
DEF_STD_FUNC_1ARG(sin)
DEF_STD_FUNC_1ARG(tan)
DEF_STD_FUNC_1ARG(acos)
DEF_STD_FUNC_1ARG(asin)
DEF_STD_FUNC_1ARG(atan)
DEF_STD_FUNC_2ARG(atan2)
// Hyperbolic functions
DEF_STD_FUNC_1ARG(cosh)
DEF_STD_FUNC_1ARG(sinh)
DEF_STD_FUNC_1ARG(tanh)
DEF_STD_FUNC_1ARG(acosh)
DEF_STD_FUNC_1ARG(asinh)
DEF_STD_FUNC_1ARG(atanh)
// Exponential and logarithmic functions
DEF_STD_FUNC_1ARG(exp)
DEF_STD_FUNC_1ARG(log)
DEF_STD_FUNC_1ARG(log10)
DEF_STD_FUNC_1ARG(exp2)
DEF_STD_FUNC_1ARG(expm1)
DEF_STD_FUNC_1ARG(log1p)
DEF_STD_FUNC_1ARG(log2)
// Power functions
DEF_STD_FUNC_2ARG(pow)
DEF_STD_FUNC_1ARG(sqrt)
DEF_STD_FUNC_1ARG(cbrt)
DEF_STD_FUNC_2ARG(hypot)
// Error and gamma functions
DEF_STD_FUNC_1ARG(erf)
DEF_STD_FUNC_1ARG(erfc)
DEF_STD_FUNC_1ARG(tgamma)
DEF_STD_FUNC_1ARG(lgamma)
// Rounding and remainder functions
DEF_STD_FUNC_1ARG(ceil)
DEF_STD_FUNC_1ARG(floor)
DEF_STD_FUNC_2ARG(fmod)
DEF_STD_FUNC_1ARG(trunc)
DEF_STD_FUNC_1ARG(round)
DEF_STD_FUNC_1ARG(rint)
DEF_STD_FUNC_1ARG(nearbyint)
DEF_STD_FUNC_2ARG(remainder)
// Minimum, maximum, difference functions
DEF_STD_FUNC_2ARG(fdim)
DEF_STD_FUNC_2ARG(fmax)
DEF_STD_FUNC_2ARG(fmin)
// Absolute value
DEF_STD_FUNC_1ARG(fabs)
// p-value
auto chi2PValueVecFunc = [](const double arg[2])
{
return gsl_cdf_chisq_Q(arg[0], arg[1]);
};
DoubleFunction MATH_NAMESPACE::chi2PValue(chi2PValueVecFunc, 2);

159
lib/Core/Math.hpp Normal file
View File

@ -0,0 +1,159 @@
/*
* Math.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_Math_hpp_
#define Latan_Math_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Core/MathInterpreter.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Custom math functions *
******************************************************************************/
#define MATH_NAMESPACE Math
namespace MATH_NAMESPACE
{
// integer power function
template <unsigned int n, typename T>
typename std::enable_if<(n == 0), T>::type pow(const T x __dumb)
{
return 1;
}
template <unsigned int n, typename T>
typename std::enable_if<(n == 1), T>::type pow(const T x)
{
return x;
}
template <unsigned int n, typename T>
typename std::enable_if<(n > 1), T>::type pow(const T x)
{
return x*pow<n-1>(x);
}
// integral factorial function
template <typename T>
T factorial(const T n)
{
static_assert(std::is_integral<T>::value,
"factorial must me used with an integral argument");
T res = n;
for (T i = n - 1; i != 0; --i)
{
res *= i;
}
return res;
}
// convert variance matrix to correlation matrix
DMat varToCorr(const DMat &var);
// Constants
constexpr double pi = 3.1415926535897932384626433832795028841970;
constexpr double e = 2.7182818284590452353602874713526624977572;
constexpr double inf = std::numeric_limits<double>::infinity();
}
/******************************************************************************
* Standard C functions *
******************************************************************************/
#define STDMATH_NAMESPACE StdMath
#define DECL_STD_FUNC(name) \
namespace STDMATH_NAMESPACE\
{\
extern DoubleFunction name;\
}
// Trigonometric functions
DECL_STD_FUNC(cos)
DECL_STD_FUNC(sin)
DECL_STD_FUNC(tan)
DECL_STD_FUNC(acos)
DECL_STD_FUNC(asin)
DECL_STD_FUNC(atan)
DECL_STD_FUNC(atan2)
// Hyperbolic functions
DECL_STD_FUNC(cosh)
DECL_STD_FUNC(sinh)
DECL_STD_FUNC(tanh)
DECL_STD_FUNC(acosh)
DECL_STD_FUNC(asinh)
DECL_STD_FUNC(atanh)
// Exponential and logarithmic functions
DECL_STD_FUNC(exp)
DECL_STD_FUNC(log)
DECL_STD_FUNC(log10)
DECL_STD_FUNC(exp2)
DECL_STD_FUNC(expm1)
DECL_STD_FUNC(log1p)
DECL_STD_FUNC(log2)
// Power functions
DECL_STD_FUNC(pow)
DECL_STD_FUNC(sqrt)
DECL_STD_FUNC(cbrt)
DECL_STD_FUNC(hypot)
// Error and gamma functions
DECL_STD_FUNC(erf)
DECL_STD_FUNC(erfc)
DECL_STD_FUNC(tgamma)
DECL_STD_FUNC(lgamma)
// Rounding and remainder functions
DECL_STD_FUNC(ceil)
DECL_STD_FUNC(floor)
DECL_STD_FUNC(fmod)
DECL_STD_FUNC(trunc)
DECL_STD_FUNC(round)
DECL_STD_FUNC(rint)
DECL_STD_FUNC(nearbyint)
DECL_STD_FUNC(remainder)
// Minimum, maximum, difference functions
DECL_STD_FUNC(fdim)
DECL_STD_FUNC(fmax)
DECL_STD_FUNC(fmin)
// Absolute value
DECL_STD_FUNC(fabs)
/******************************************************************************
* Other functions *
******************************************************************************/
// p-value
namespace MATH_NAMESPACE
{
extern DoubleFunction chi2PValue;
}
END_LATAN_NAMESPACE
#endif // Latan_Math_hpp_

View File

@ -0,0 +1,745 @@
/*
* MathInterpreter.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/Core/MathInterpreter.hpp>
#include <LatAnalyze/includes.hpp>
#include <LatAnalyze/Core/Math.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* RunContext implementation *
******************************************************************************/
// access //////////////////////////////////////////////////////////////////////
unsigned int RunContext::addFunction(const string &name, DoubleFunction *init)
{
try
{
setFunction(name, init);
return getFunctionAddress(name);
}
catch (Exceptions::Definition)
{
unsigned int address = fTable_.size();
fMem_.push_back(init);
fTable_[name] = address;
return address;
}
}
unsigned int RunContext::addVariable(const string &name, double init)
{
try
{
setVariable(name, init);
return getVariableAddress(name);
}
catch (Exceptions::Definition)
{
unsigned int address = vTable_.size();
vMem_.push_back(init);
vTable_[name] = address;
return address;
}
}
DoubleFunction * RunContext::getFunction(const string &name) const
{
return getFunction(getFunctionAddress(name));
}
DoubleFunction * RunContext::getFunction(const unsigned int address) const
{
if (address >= fTable_.size())
{
LATAN_ERROR(Range, "function address " + strFrom(address)
+ " out of range");
return nullptr;
}
else
{
return fMem_[address];
}
}
unsigned int RunContext::getFunctionAddress(const string &name) const
{
try
{
return fTable_.at(name);
}
catch (out_of_range)
{
LATAN_ERROR(Definition, "undefined function '" + name + "'");
}
}
const RunContext::AddressTable & RunContext::getFunctionTable(void) const
{
return fTable_;
}
unsigned int RunContext::getInsIndex(void) const
{
return insIndex_;
}
double RunContext::getVariable(const string &name) const
{
return getVariable(getVariableAddress(name));
}
double RunContext::getVariable(const unsigned int address) const
{
if (address >= vTable_.size())
{
LATAN_ERROR(Range, "variable address " + strFrom(address)
+ " out of range");
return 0.;
}
else
{
return vMem_[address];
}
}
const RunContext::AddressTable & RunContext::getVariableTable(void) const
{
return vTable_;
}
unsigned int RunContext::getVariableAddress(const string &name) const
{
try
{
return vTable_.at(name);
}
catch (out_of_range)
{
LATAN_ERROR(Definition, "undefined variable '" + name + "'");
}
}
void RunContext::incrementInsIndex(const unsigned int inc)
{
setInsIndex(getInsIndex() + inc);
}
void RunContext::setFunction(const string &name, DoubleFunction *f)
{
setFunction(getFunctionAddress(name), f);
}
void RunContext::setFunction(const unsigned int address, DoubleFunction *f)
{
if (address >= fTable_.size())
{
LATAN_ERROR(Range, "function address " + strFrom(address)
+ " out of range");
}
else
{
fMem_[address] = f;
}
}
void RunContext::setInsIndex(const unsigned index)
{
insIndex_ = index;
}
void RunContext::setVariable(const string &name, const double value)
{
setVariable(getVariableAddress(name), value);
}
void RunContext::setVariable(const unsigned int address, const double value)
{
if (address >= vTable_.size())
{
LATAN_ERROR(Range, "variable address " + strFrom(address)
+ " out of range");
}
else
{
vMem_[address] = value;
}
}
stack<double> & RunContext::stack(void)
{
return dStack_;
}
// reset ///////////////////////////////////////////////////////////////////////
void RunContext::reset(void)
{
insIndex_ = 0;
while (!dStack_.empty())
{
dStack_.pop();
}
vMem_.clear();
fMem_.clear();
vTable_.clear();
fTable_.clear();
}
/******************************************************************************
* Instruction set *
******************************************************************************/
#define CODE_WIDTH 6
#define CODE_MOD setw(CODE_WIDTH) << left
// Instruction operator ////////////////////////////////////////////////////////
ostream &Latan::operator<<(ostream& out, const Instruction& ins)
{
ins.print(out);
return out;
}
// Push constructors ///////////////////////////////////////////////////////////
Push::Push(const double val)
: type_(ArgType::Constant)
, val_(val)
, address_(0)
, name_("")
{}
Push::Push(const unsigned int address, const string &name)
: type_(ArgType::Variable)
, val_(0.0)
, address_(address)
, name_(name)
{}
// Push execution //////////////////////////////////////////////////////////////
void Push::operator()(RunContext &context) const
{
if (type_ == ArgType::Constant)
{
context.stack().push(val_);
}
else
{
context.stack().push(context.getVariable(address_));
}
context.incrementInsIndex();
}
// Push print //////////////////////////////////////////////////////////////////
void Push::print(ostream &out) const
{
out << CODE_MOD << "push";
if (type_ == ArgType::Constant)
{
out << CODE_MOD << val_;
}
else
{
out << CODE_MOD << name_ << " @v" << address_;
}
}
// Pop constructor /////////////////////////////////////////////////////////////
Pop::Pop(const unsigned int address, const string &name)
: address_(address)
, name_(name)
{}
// Pop execution ///////////////////////////////////////////////////////////////
void Pop::operator()(RunContext &context) const
{
if (!name_.empty())
{
context.setVariable(address_, context.stack().top());
}
context.stack().pop();
context.incrementInsIndex();
}
// Pop print ///////////////////////////////////////////////////////////////////
void Pop::print(ostream &out) const
{
out << CODE_MOD << "pop" << CODE_MOD << name_ << " @v" << address_;
}
// Store constructor ///////////////////////////////////////////////////////////
Store::Store(const unsigned int address, const string &name)
: address_(address)
, name_(name)
{}
// Store execution /////////////////////////////////////////////////////////////
void Store::operator()(RunContext &context) const
{
if (!name_.empty())
{
context.setVariable(address_, context.stack().top());
}
context.incrementInsIndex();
}
// Store print /////////////////////////////////////////////////////////////////
void Store::print(ostream &out) const
{
out << CODE_MOD << "store" << CODE_MOD << name_ << " @v" << address_;
}
// Call constructor ////////////////////////////////////////////////////////////
Call::Call(const unsigned int address, const string &name)
: address_(address)
, name_(name)
{}
// Call execution //////////////////////////////////////////////////////////////
void Call::operator()(RunContext &context) const
{
context.stack().push((*context.getFunction(address_))(context.stack()));
context.incrementInsIndex();
}
// Call print //////////////////////////////////////////////////////////////////
void Call::print(ostream &out) const
{
out << CODE_MOD << "call" << CODE_MOD << name_ << " @f" << address_;
}
// Math operations /////////////////////////////////////////////////////////////
#define DEF_OP(name, nArg, exp, insName)\
void name::operator()(RunContext &context) const\
{\
double x[nArg];\
for (int i = 0; i < nArg; ++i)\
{\
x[nArg-1-i] = context.stack().top();\
context.stack().pop();\
}\
context.stack().push(exp);\
context.incrementInsIndex();\
}\
void name::print(ostream &out) const\
{\
out << CODE_MOD << insName;\
}
DEF_OP(Neg, 1, -x[0], "neg")
DEF_OP(Add, 2, x[0] + x[1], "add")
DEF_OP(Sub, 2, x[0] - x[1], "sub")
DEF_OP(Mul, 2, x[0]*x[1], "mul")
DEF_OP(Div, 2, x[0]/x[1], "div")
DEF_OP(Pow, 2, pow(x[0],x[1]), "pow")
/******************************************************************************
* ExprNode implementation *
******************************************************************************/
// ExprNode constructors ///////////////////////////////////////////////////////
ExprNode::ExprNode(const string &name)
: name_(name)
, parent_(nullptr)
{}
// ExprNode access /////////////////////////////////////////////////////////////
const string &ExprNode::getName(void) const
{
return name_;
}
Index ExprNode::getNArg(void) const
{
return static_cast<Index>(arg_.size());
}
const ExprNode * ExprNode::getParent(void) const
{
return parent_;
}
Index ExprNode::getLevel(void) const
{
if (getParent())
{
return getParent()->getLevel() + 1;
}
else
{
return 0;
}
}
void ExprNode::setName(const std::string &name)
{
name_ = name;
}
void ExprNode::pushArg(ExprNode *node)
{
if (node)
{
node->parent_ = this;
arg_.push_back(unique_ptr<ExprNode>(node));
}
}
// ExprNode operators //////////////////////////////////////////////////////////
const ExprNode &ExprNode::operator[](const Index i) const
{
return *arg_[i];
}
ostream &Latan::operator<<(ostream &out, const ExprNode &n)
{
Index level = n.getLevel();
for (Index i = 0; i <= level; ++i)
{
if (i == level)
{
out << "_";
}
else if (i == level - 1)
{
out << "|";
}
else
{
out << " ";
}
}
out << " " << n.getName() << endl;
for (Index i = 0; i < n.getNArg(); ++i)
{
out << n[i];
}
return out;
}
#define PUSH_INS(program, type, ...)\
program.push_back(unique_ptr<type>(new type(__VA_ARGS__)))
#define GET_ADDRESS(address, table, name)\
try\
{\
address = (table).at(name);\
}\
catch (out_of_range)\
{\
address = (table).size();\
(table)[(name)] = address;\
}\
// VarNode compile /////////////////////////////////////////////////////////////
void VarNode::compile(Program &program, RunContext &context) const
{
PUSH_INS(program, Push, context.getVariableAddress(getName()), getName());
}
// CstNode compile /////////////////////////////////////////////////////////////
void CstNode::compile(Program &program, RunContext &context __dumb) const
{
PUSH_INS(program, Push, strTo<double>(getName()));
}
// SemicolonNode compile ///////////////////////////////////////////////////////
void SemicolonNode::compile(Program &program, RunContext &context) const
{
auto &n = *this;
for (Index i = 0; i < getNArg(); ++i)
{
bool isAssign = isDerivedFrom<AssignNode>(&n[i]);
bool isSemiColumn = isDerivedFrom<SemicolonNode>(&n[i]);
bool isKeyword = isDerivedFrom<KeywordNode>(&n[i]);
if (isAssign or isSemiColumn or isKeyword)
{
n[i].compile(program, context);
}
}
}
// AssignNode compile //////////////////////////////////////////////////////////
void AssignNode::compile(Program &program, RunContext &context) const
{
auto &n = *this;
if (isDerivedFrom<VarNode>(&n[0]))
{
bool hasSemicolonParent = isDerivedFrom<SemicolonNode>(getParent());
unsigned int address;
n[1].compile(program, context);
address = context.addVariable(n[0].getName());
if (hasSemicolonParent)
{
PUSH_INS(program, Pop, address, n[0].getName());
}
else
{
PUSH_INS(program, Store, address, n[0].getName());
}
}
else
{
LATAN_ERROR(Compilation, "invalid LHS for '='");
}
}
// MathOpNode compile //////////////////////////////////////////////////////////
#define IFNODE(name, nArg) if ((n.getName() == (name)) and (n.getNArg() == nArg))
#define ELIFNODE(name, nArg) else IFNODE(name, nArg)
#define ELSE else
void MathOpNode::compile(Program &program, RunContext &context) const
{
auto &n = *this;
for (Index i = 0; i < n.getNArg(); ++i)
{
n[i].compile(program, context);
}
IFNODE("-", 1) PUSH_INS(program, Neg,);
ELIFNODE("+", 2) PUSH_INS(program, Add,);
ELIFNODE("-", 2) PUSH_INS(program, Sub,);
ELIFNODE("*", 2) PUSH_INS(program, Mul,);
ELIFNODE("/", 2) PUSH_INS(program, Div,);
ELIFNODE("^", 2) PUSH_INS(program, Pow,);
ELSE LATAN_ERROR(Compilation, "unknown operator '" + getName() + "'");
}
// FuncNode compile ////////////////////////////////////////////////////////////
void FuncNode::compile(Program &program, RunContext &context) const
{
auto &n = *this;
for (Index i = 0; i < n.getNArg(); ++i)
{
n[i].compile(program, context);
}
PUSH_INS(program, Call, context.getFunctionAddress(getName()), getName());
}
// ReturnNode compile ////////////////////////////////////////////////////////////
void ReturnNode::compile(Program &program, RunContext &context) const
{
auto &n = *this;
n[0].compile(program, context);
program.push_back(nullptr);
}
/******************************************************************************
* MathInterpreter implementation *
******************************************************************************/
// MathParserState constructor /////////////////////////////////////////////////
MathInterpreter::MathParserState::MathParserState
(istream *stream, string *name, std::unique_ptr<ExprNode> *data)
: ParserState<std::unique_ptr<ExprNode>>(stream, name, data)
{
initScanner();
}
// MathParserState destructor //////////////////////////////////////////////////
MathInterpreter::MathParserState::~MathParserState(void)
{
destroyScanner();
}
// constructors ////////////////////////////////////////////////////////////////
MathInterpreter::MathInterpreter(const std::string &code)
: codeName_("<string>")
{
setCode(code);
}
// access //////////////////////////////////////////////////////////////////////
const Instruction * MathInterpreter::operator[](const Index i) const
{
return program_[i].get();
}
const ExprNode * MathInterpreter::getAST(void) const
{
return root_.get();
}
void MathInterpreter::push(const Instruction *i)
{
program_.push_back(unique_ptr<const Instruction>(i));
}
// initialization //////////////////////////////////////////////////////////////
void MathInterpreter::setCode(const std::string &code)
{
if (status_)
{
reset();
}
code_.reset(new stringstream(code));
codeName_ = "<string>";
state_.reset(new MathParserState(code_.get(), &codeName_, &root_));
program_.clear();
status_ = Status::initialised;
}
void MathInterpreter::reset(void)
{
code_.reset();
codeName_ = "<no_code>";
state_.reset();
root_.reset();
program_.clear();
status_ = 0;
}
// parser //////////////////////////////////////////////////////////////////////
// Bison/Flex parser declaration
int _math_parse(MathInterpreter::MathParserState *state);
void MathInterpreter::parse(void)
{
_math_parse(state_.get());
}
// interpreter /////////////////////////////////////////////////////////////////
#define ADD_FUNC(context, func)\
(context).addFunction(#func, &STDMATH_NAMESPACE::func);\
#define ADD_STDMATH_FUNCS(context)\
ADD_FUNC(context, cos);\
ADD_FUNC(context, sin);\
ADD_FUNC(context, tan);\
ADD_FUNC(context, acos);\
ADD_FUNC(context, asin);\
ADD_FUNC(context, atan);\
ADD_FUNC(context, atan2);\
ADD_FUNC(context, cosh);\
ADD_FUNC(context, sinh);\
ADD_FUNC(context, tanh);\
ADD_FUNC(context, acosh);\
ADD_FUNC(context, asinh);\
ADD_FUNC(context, atanh);\
ADD_FUNC(context, exp);\
ADD_FUNC(context, log);\
ADD_FUNC(context, log10);\
ADD_FUNC(context, exp2);\
ADD_FUNC(context, expm1);\
ADD_FUNC(context, log1p);\
ADD_FUNC(context, log2);\
ADD_FUNC(context, pow);\
ADD_FUNC(context, sqrt);\
ADD_FUNC(context, cbrt);\
ADD_FUNC(context, hypot);\
ADD_FUNC(context, erf);\
ADD_FUNC(context, erfc);\
ADD_FUNC(context, tgamma);\
ADD_FUNC(context, lgamma);\
ADD_FUNC(context, ceil);\
ADD_FUNC(context, floor);\
ADD_FUNC(context, fmod);\
ADD_FUNC(context, trunc);\
ADD_FUNC(context, round);\
ADD_FUNC(context, rint);\
ADD_FUNC(context, nearbyint);\
ADD_FUNC(context, remainder);\
ADD_FUNC(context, fdim);\
ADD_FUNC(context, fmax);\
ADD_FUNC(context, fmin);\
ADD_FUNC(context, fabs);
void MathInterpreter::compile(RunContext &context)
{
bool gotReturn = false;
if (!(status_ & Status::parsed))
{
parse();
status_ |= Status::parsed;
status_ -= status_ & Status::compiled;
}
if (!(status_ & Status::compiled))
{
if (root_)
{
context.addVariable("pi", Math::pi);
context.addVariable("inf", Math::inf);
ADD_STDMATH_FUNCS(context);
root_->compile(program_, context);
for (unsigned int i = 0; i < program_.size(); ++i)
{
if (!program_[i])
{
gotReturn = true;
program_.resize(i);
program_.shrink_to_fit();
break;
}
}
}
if (!root_ or !gotReturn)
{
LATAN_ERROR(Syntax, "expected 'return' in program '" + codeName_
+ "'");
}
status_ |= Status::compiled;
}
}
// execution ///////////////////////////////////////////////////////////////////
void MathInterpreter::operator()(RunContext &context)
{
if (!(status_ & Status::compiled))
{
compile(context);
}
execute(context);
}
void MathInterpreter::execute(RunContext &context) const
{
context.setInsIndex(0);
while (context.getInsIndex() != program_.size())
{
(*(program_[context.getInsIndex()]))(context);
}
}
// IO //////////////////////////////////////////////////////////////////////////
ostream &Latan::operator<<(ostream &out, const MathInterpreter &program)
{
for (unsigned int i = 0; i < program.program_.size(); ++i)
{
out << *(program.program_[i]) << endl;
}
return out;
}

View File

@ -0,0 +1,313 @@
/*
* MathInterpreter.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_MathInterpreter_hpp_
#define Latan_MathInterpreter_hpp_
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Core/ParserState.hpp>
#define MAXIDLENGTH 256
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Class for runtime context *
******************************************************************************/
class RunContext
{
public:
typedef std::map<std::string, unsigned int> AddressTable;
public:
// constructor
RunContext(void) = default;
// destructor
~RunContext(void) = default;
// access
unsigned int addFunction(const std::string &name,
DoubleFunction *init = nullptr);
unsigned int addVariable(const std::string &name,
const double init = 0.);
DoubleFunction * getFunction(const std::string &name) const;
DoubleFunction * getFunction(const unsigned int address) const;
unsigned int getFunctionAddress(const std::string &name) const;
const AddressTable & getFunctionTable(void) const;
unsigned int getInsIndex(void) const;
double getVariable(const std::string &name) const;
double getVariable(const unsigned int address) const;
unsigned int getVariableAddress(const std::string &name) const;
const AddressTable & getVariableTable(void) const;
void incrementInsIndex(const unsigned int inc = 1);
void setFunction(const std::string &name,
DoubleFunction *f);
void setFunction(const unsigned int address,
DoubleFunction *f);
void setInsIndex(const unsigned index);
void setVariable(const std::string &name,
const double value);
void setVariable(const unsigned int address,
const double value);
std::stack<double> & stack(void);
// reset
void reset(void);
private:
unsigned int insIndex_;
std::stack<double> dStack_;
std::vector<double> vMem_;
std::vector<DoubleFunction *> fMem_;
AddressTable vTable_, fTable_;
};
/******************************************************************************
* Instruction classes *
******************************************************************************/
// Abstract base
class Instruction
{
public:
// destructor
virtual ~Instruction(void) = default;
// instruction execution
virtual void operator()(RunContext &context) const = 0;
friend std::ostream & operator<<(std::ostream &out, const Instruction &ins);
private:
virtual void print(std::ostream &out) const = 0;
};
std::ostream & operator<<(std::ostream &out, const Instruction &ins);
// Instruction container
typedef std::vector<std::unique_ptr<const Instruction>> Program;
// Push
class Push: public Instruction
{
private:
enum class ArgType
{
Constant = 0,
Variable = 1
};
public:
//constructors
explicit Push(const double val);
explicit Push(const unsigned int address, const std::string &name);
// instruction execution
virtual void operator()(RunContext &context) const;
private:
virtual void print(std::ostream& out) const;
private:
ArgType type_;
double val_;
unsigned int address_;
std::string name_;
};
// Pop
class Pop: public Instruction
{
public:
//constructor
explicit Pop(const unsigned int address, const std::string &name);
// instruction execution
virtual void operator()(RunContext &context) const;
private:
virtual void print(std::ostream& out) const;
private:
unsigned int address_;
std::string name_;
};
// Store
class Store: public Instruction
{
public:
//constructor
explicit Store(const unsigned int address, const std::string &name);
// instruction execution
virtual void operator()(RunContext &context) const;
private:
virtual void print(std::ostream& out) const;
private:
unsigned int address_;
std::string name_;
};
// Call function
class Call: public Instruction
{
public:
//constructor
explicit Call(const unsigned int address, const std::string &name);
// instruction execution
virtual void operator()(RunContext &context) const;
private:
virtual void print(std::ostream& out) const;
private:
unsigned int address_;
std::string name_;
};
// Floating point operations
#define DECL_OP(name)\
class name: public Instruction\
{\
public:\
virtual void operator()(RunContext &context) const;\
private:\
virtual void print(std::ostream &out) const;\
}
DECL_OP(Neg);
DECL_OP(Add);
DECL_OP(Sub);
DECL_OP(Mul);
DECL_OP(Div);
DECL_OP(Pow);
/******************************************************************************
* Expression node classes *
******************************************************************************/
class ExprNode
{
public:
// constructors
explicit ExprNode(const std::string &name);
// destructor
virtual ~ExprNode() = default;
// access
const std::string& getName(void) const;
Index getNArg(void) const;
const ExprNode * getParent(void) const;
Index getLevel(void) const;
void setName(const std::string &name);
void pushArg(ExprNode *node);
// operator
const ExprNode &operator[](const Index i) const;
// compile
virtual void compile(Program &program, RunContext &context) const = 0;
private:
std::string name_;
std::vector<std::unique_ptr<ExprNode>> arg_;
const ExprNode * parent_;
};
std::ostream &operator<<(std::ostream &out, const ExprNode &n);
#define DECL_NODE(base, name) \
class name: public base\
{\
public:\
using base::base;\
virtual void compile(Program &program, RunContext &context) const;\
}
DECL_NODE(ExprNode, VarNode);
DECL_NODE(ExprNode, CstNode);
DECL_NODE(ExprNode, SemicolonNode);
DECL_NODE(ExprNode, AssignNode);
DECL_NODE(ExprNode, MathOpNode);
DECL_NODE(ExprNode, FuncNode);
class KeywordNode: public ExprNode
{
public:
using ExprNode::ExprNode;
virtual void compile(Program &program, RunContext &context) const = 0;
};
DECL_NODE(KeywordNode, ReturnNode);
/******************************************************************************
* Interpreter class *
******************************************************************************/
class MathInterpreter
{
public:
// parser state
class MathParserState: public ParserState<std::unique_ptr<ExprNode>>
{
public:
// constructor
explicit MathParserState(std::istream *stream, std::string *name,
std::unique_ptr<ExprNode> *data);
// destructor
virtual ~MathParserState(void);
private:
// allocation/deallocation functions defined in MathLexer.lpp
virtual void initScanner(void);
virtual void destroyScanner(void);
};
private:
// status flags
class Status
{
public:
enum
{
none = 0,
initialised = 1 << 0,
parsed = 1 << 1,
compiled = 1 << 2
};
};
public:
// constructors
MathInterpreter(void) = default;
MathInterpreter(const std::string &code);
// destructor
~MathInterpreter(void) = default;
// access
const Instruction * operator[](const Index i) const;
const ExprNode * getAST(void) const;
// initialization
void setCode(const std::string &code);
// interpreter
void compile(RunContext &context);
// execution
void operator()(RunContext &context);
// IO
friend std::ostream & operator<<(std::ostream &out,
const MathInterpreter &program);
private:
// initialization
void reset(void);
// access
void push(const Instruction *i);
// parser
void parse(void);
// interpreter
void compileNode(const ExprNode &node);
// execution
void execute(RunContext &context) const;
private:
std::unique_ptr<std::istream> code_{nullptr};
std::string codeName_{"<no_code>"};
std::unique_ptr<MathParserState> state_{nullptr};
std::unique_ptr<ExprNode> root_{nullptr};
Program program_;
unsigned int status_{Status::none};
};
std::ostream & operator<<(std::ostream &out, const MathInterpreter &program);
END_LATAN_NAMESPACE
#endif // Latan_MathInterpreter_hpp_

89
lib/Core/MathLexer.lpp Normal file
View File

@ -0,0 +1,89 @@
/*
* MathLexer.lpp, 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/>.
*/
%option reentrant
%option prefix="_math_"
%option bison-bridge
%option bison-locations
%option noyywrap
%option yylineno
%{
#include <LatAnalyze/Core/MathInterpreter.hpp>
#include "MathParser.hpp"
using namespace std;
using namespace Latan;
#define YY_EXTRA_TYPE MathInterpreter::MathParserState *
#define YY_USER_ACTION \
yylloc->first_line = yylloc->last_line = yylineno;\
yylloc->first_column = yylloc->last_column + 1;\
yylloc->last_column = yylloc->first_column + yyleng - 1;
#define YY_INPUT(buf, result, max_size) \
{ \
(*yyextra->stream).read(buf, max_size);\
result = (*yyextra->stream).gcount();\
}
#define YY_DEBUG 0
#if (YY_DEBUG == 1)
#define RET(var) cout << (var) << "(" << yytext << ")" << endl; return (var)
#define RETTOK(tok) cout << #tok << "(" << yytext << ")" << endl; return tok
#else
#define RET(var) return (var)
#define RETTOK(tok) return tok
#endif
%}
DIGIT [0-9]
ALPHA [a-zA-Z_]
FLOAT (({DIGIT}+(\.{DIGIT}*)?)|({DIGIT}*\.{DIGIT}+))([eE][+-]?{DIGIT}+)?
SPECIAL [;,()+\-*/^={}]
BLANK [ \t]
%%
{FLOAT} {
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
RETTOK(FLOAT);
}
{SPECIAL} {RET(*yytext);}
return {RETTOK(RETURN);}
{ALPHA}({ALPHA}|{DIGIT})* {
strncpy(yylval->val_str,yytext,MAXIDLENGTH);
RETTOK(ID);
}
<*>\n {yylloc->last_column = 0;}
<*>{BLANK}
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
%%
void MathInterpreter::MathParserState::initScanner()
{
yylex_init(&scanner);
yyset_extra(this, scanner);
}
void MathInterpreter::MathParserState::destroyScanner()
{
yylex_destroy(scanner);
}

142
lib/Core/MathParser.ypp Normal file
View File

@ -0,0 +1,142 @@
/*
* MathParser.ypp, 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/Global.hpp>
#include <LatAnalyze/Core/MathInterpreter.hpp>
using namespace std;
using namespace Latan;
%}
%pure-parser
%name-prefix "_math_"
%locations
%defines
%error-verbose
%parse-param { Latan::MathInterpreter::MathParserState *state }
%initial-action {yylloc.last_column = 0;}
%lex-param { void* scanner }
%union
{
double val_double;
char val_char;
char val_str[MAXIDLENGTH];
Latan::ExprNode *val_node;
}
%token <val_char> ERR
%token <val_str> FLOAT
%token <val_str> ID
%token RETURN
%left '='
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%left '^'
%type <val_node> stmt stmt_list expr func_args
%{
int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
void _math_error(YYLTYPE *locp, MathInterpreter::MathParserState *state,
const char *err)
{
stringstream buf;
buf << *(state->streamName) << ":" << locp->first_line << ":"\
<< locp->first_column << ": " << err;
LATAN_ERROR(Parsing, buf.str());
}
void _math_warning(YYLTYPE *locp, MathInterpreter::MathParserState *state,
const char *err)
{
stringstream buf;
buf << *(state->streamName) << ":" << locp->first_line << ":"\
<< locp->first_column << ": " << err;
LATAN_WARNING(buf.str());
}
#define scanner state->scanner
%}
%%
program:
/* empty string */
| stmt_list {(*(state->data)).reset($1);}
;
stmt:
';'
{$$ = new SemicolonNode(";");}
| expr ';'
{$$ = nullptr; _math_warning(&yylloc, state, "useless statement removed");}
| ID '=' expr ';'
{$$ = new AssignNode("="); $$->pushArg(new VarNode($1)); $$->pushArg($3);}
| RETURN expr ';'
{$$ = new ReturnNode("return"); $$->pushArg($2);}
| '{' stmt_list '}'
{$$ = $2;}
;
stmt_list:
stmt
{$$ = $1;}
| stmt_list stmt
{$$ = new SemicolonNode(";"); $$->pushArg($1); $$->pushArg($2);}
;
expr:
FLOAT
{$$ = new CstNode($1);}
| ID
{$$ = new VarNode($1);}
| '-' expr %prec UMINUS
{$$ = new MathOpNode("-"); $$->pushArg($2);}
| expr '+' expr
{$$ = new MathOpNode("+"); $$->pushArg($1); $$->pushArg($3);}
| expr '-' expr
{$$ = new MathOpNode("-"); $$->pushArg($1); $$->pushArg($3);}
| expr '*' expr
{$$ = new MathOpNode("*"); $$->pushArg($1); $$->pushArg($3);}
| expr '/' expr
{$$ = new MathOpNode("/"); $$->pushArg($1); $$->pushArg($3);}
| expr '^' expr
{$$ = new MathOpNode("^"); $$->pushArg($1); $$->pushArg($3);}
| '(' expr ')'
{$$ = $2;}
| ID '(' func_args ')'
{$$ = $3; $$->setName($1);}
;
func_args:
/* empty string */
{$$ = new FuncNode("");}
| expr
{$$ = new FuncNode(""); $$->pushArg($1);}
| func_args ',' expr
{$$ = $1; $$->pushArg($3);}
;

272
lib/Core/OptParser.cpp Normal file
View File

@ -0,0 +1,272 @@
/*
* OptParser.cpp, part of LatAnalyze
*
* Copyright (C) 2016 Antonin Portelli
*
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Core/OptParser.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
static char optRegex[] = "(-([a-zA-Z])(.+)?)|(--([a-zA-Z_-]+)=?(.+)?)";
/******************************************************************************
* OptParser implementation *
******************************************************************************/
// regular expressions /////////////////////////////////////////////////////////
const regex OptParser::optRegex_(optRegex);
// access //////////////////////////////////////////////////////////////////////
void OptParser::addOption(const std::string shortName,
const std::string longName,
const OptType type, const bool optional,
const std::string helpMessage,
const std::string defaultVal)
{
OptPar par;
par.shortName = shortName;
par.longName = longName;
par.defaultVal = defaultVal;
par.helpMessage = helpMessage;
par.type = type;
par.optional = optional;
opt_.push_back(par);
}
bool OptParser::gotOption(const std::string name) const
{
int i = optIndex(name);
if (result_.size() != opt_.size())
{
throw(runtime_error("options not parsed"));
}
if (i >= 0)
{
return result_[i].present;
}
else
{
throw(out_of_range("no option with name '" + name + "'"));
}
}
const vector<string> & OptParser::getArgs(void) const
{
return arg_;
}
// parse ///////////////////////////////////////////////////////////////////////
bool OptParser::parse(int argc, char *argv[])
{
smatch sm;
queue<string> arg;
int expectVal = -1;
bool isCorrect = true;
for (int i = 1; i < argc; ++i)
{
arg.push(argv[i]);
}
result_.clear();
result_.resize(opt_.size());
arg_.clear();
for (unsigned int i = 0; i < opt_.size(); ++i)
{
result_[i].value = opt_[i].defaultVal;
}
while (!arg.empty())
{
// option
if (regex_match(arg.front(), sm, optRegex_))
{
// should it be a value?
if (expectVal >= 0)
{
cerr << "warning: expected value for option ";
cerr << optName(opt_[expectVal]);
cerr << ", got option '" << arg.front() << "' instead" << endl;
expectVal = -1;
isCorrect = false;
}
// short option
if (sm[1].matched)
{
string optName = sm[2].str();
// find option
auto it = find_if(opt_.begin(), opt_.end(),
[&optName](const OptPar &p)
{
return (p.shortName == optName);
});
// parse if found
if (it != opt_.end())
{
unsigned int i = it - opt_.begin();
result_[i].present = true;
if (opt_[i].type == OptType::value)
{
if (sm[3].matched)
{
result_[i].value = sm[3].str();
}
else
{
expectVal = i;
}
}
}
// warning if not found
else
{
cerr << "warning: unknown option '" << arg.front() << "'";
cerr << endl;
}
}
// long option
else if (sm[4].matched)
{
string optName = sm[5].str();
// find option
auto it = find_if(opt_.begin(), opt_.end(),
[&optName](const OptPar &p)
{
return (p.longName == optName);
});
// parse if found
if (it != opt_.end())
{
unsigned int i = it - opt_.begin();
result_[i].present = true;
if (opt_[i].type == OptType::value)
{
if (sm[6].matched)
{
result_[i].value = sm[6].str();
}
else
{
expectVal = i;
}
}
}
// warning if not found
else
{
cerr << "warning: unknown option '" << arg.front() << "'";
cerr << endl;
}
}
}
else if (expectVal >= 0)
{
result_[expectVal].value = arg.front();
expectVal = -1;
}
else
{
arg_.push_back(arg.front());
}
arg.pop();
}
if (expectVal >= 0)
{
cerr << "warning: expected value for option ";
cerr << optName(opt_[expectVal]) << endl;
expectVal = -1;
isCorrect = false;
}
for (unsigned int i = 0; i < opt_.size(); ++i)
{
if (!opt_[i].optional and !result_[i].present)
{
cerr << "warning: mandatory option " << optName(opt_[i]);
cerr << " is missing" << endl;
isCorrect = false;
}
}
return isCorrect;
}
// find option index ///////////////////////////////////////////////////////////
int OptParser::optIndex(const string name) const
{
auto it = find_if(opt_.begin(), opt_.end(), [&name](const OptPar &p)
{
return (p.shortName == name) or (p.longName == name);
});
if (it != opt_.end())
{
return static_cast<int>(it - opt_.begin());
}
else
{
return -1;
}
}
// option name for messages ////////////////////////////////////////////////////
std::string OptParser::optName(const OptPar &opt)
{
std::string res = "";
if (!opt.shortName.empty())
{
res += "-" + opt.shortName;
if (!opt.longName.empty())
{
res += "/";
}
}
if (!opt.longName.empty())
{
res += "--" + opt.longName;
if (opt.type == OptParser::OptType::value)
{
res += "=";
}
}
return res;
}
// print option list ///////////////////////////////////////////////////////////
std::ostream & Latan::operator<<(std::ostream &out, const OptParser &parser)
{
for (auto &o: parser.opt_)
{
out << setw(20) << OptParser::optName(o);
out << ": " << o.helpMessage;
if (!o.defaultVal.empty())
{
out << " (default: " << o.defaultVal << ")";
}
out << endl;
}
return out;
}

103
lib/Core/OptParser.hpp Normal file
View File

@ -0,0 +1,103 @@
/*
* OptParser.hpp, part of LatAnalyze
*
* Copyright (C) 2016 Antonin Portelli
*
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LatAnalyze_OptParser_hpp_
#define LatAnalyze_OptParser_hpp_
#include <LatAnalyze/Global.hpp>
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* command-line option parser *
******************************************************************************/
class OptParser
{
public:
enum class OptType {value, trigger};
private:
struct OptPar
{
std::string shortName, longName, defaultVal, helpMessage;
OptType type;
bool optional;
};
struct OptRes
{
std::string value;
bool present;
};
public:
// constructor
OptParser(void) = default;
// destructor
virtual ~OptParser(void) = default;
// access
void addOption(const std::string shortName, const std::string longName,
const OptType type, const bool optional = false,
const std::string helpMessage = "",
const std::string defaultVal = "");
bool gotOption(const std::string name) const;
template <typename T = std::string>
T optionValue(const std::string name) const;
const std::vector<std::string> & getArgs(void) const;
// parse
bool parse(int argc, char *argv[]);
// print option list
friend std::ostream & operator<<(std::ostream &out,
const OptParser &parser);
private:
// find option index
int optIndex(const std::string name) const;
// option name for messages
static std::string optName(const OptPar &opt);
private:
std::vector<OptPar> opt_;
std::vector<OptRes> result_;
std::vector<std::string> arg_;
static const std::regex optRegex_;
};
std::ostream & operator<<(std::ostream &out, const OptParser &parser);
/******************************************************************************
* OptParser template implementation *
******************************************************************************/
template <typename T>
T OptParser::optionValue(const std::string name) const
{
int i = optIndex(name);
if (result_.size() != opt_.size())
{
throw(std::runtime_error("options not parsed"));
}
if (i >= 0)
{
return strTo<T>(result_[i].value);
}
else
{
throw(std::out_of_range("no option with name '" + name + "'"));
}
}
END_LATAN_NAMESPACE
#endif // LatAnalyze_OptParser_hpp_

58
lib/Core/ParserState.hpp Normal file
View File

@ -0,0 +1,58 @@
/*
* ParserState.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_ParserState_hpp_
#define Latan_ParserState_hpp_
#include <LatAnalyze/Global.hpp>
BEGIN_LATAN_NAMESPACE
template <typename DataObj>
class ParserState
{
public:
// constructor
ParserState(std::istream *streamPt, std::string *namePt, DataObj *dataPt);
// destructor
virtual ~ParserState(void) = default;
private:
// scanner allocation/deallocation
virtual void initScanner(void) = 0;
virtual void destroyScanner(void) = 0;
public:
DataObj *data;
void *scanner;
std::istream *stream;
std::string *streamName;
};
template <typename DataObj>
ParserState<DataObj>::ParserState(std::istream *streamPt, std::string *namePt,
DataObj *dataPt)
: data(dataPt)
, scanner(nullptr)
, stream(streamPt)
, streamName(namePt)
{}
END_LATAN_NAMESPACE
#endif // Latan_ParserState_hpp_

689
lib/Core/Plot.cpp Normal file
View File

@ -0,0 +1,689 @@
/*
* Plot.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/Core/Plot.hpp>
#include <LatAnalyze/includes.hpp>
#include <LatAnalyze/Core/Mat.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* Plot objects *
******************************************************************************/
// PlotObject access ///////////////////////////////////////////////////////////
const string & PlotObject::getCommand(void) const
{
return command_;
}
const string & PlotObject::getHeadCommand(void) const
{
return headCommand_;
}
void PlotObject::setCommand(const string &command)
{
command_ = command;
}
void PlotObject::setHeadCommand(const string &command)
{
headCommand_ = command;
}
string PlotObject::popTmpFile(void)
{
string res = tmpFileName_.top();
tmpFileName_.pop();
return res;
}
void PlotObject::pushTmpFile(const std::string &fileName)
{
tmpFileName_.push(fileName);
}
// PlotObject dump a matrix to a temporary file ////////////////////////////////
string PlotObject::dumpToTmpFile(const DMat &m)
{
char tmpFileName[MAX_PATH_LENGTH];
int fd;
FILE *tmpFile;
for (Index j = 0; j < m.cols(); ++j)
{
}
sprintf(tmpFileName, "%s/latan_plot_tmp.XXXXXX.dat", P_tmpdir);
fd = mkstemps(tmpFileName, 4);
if (fd == -1)
{
LATAN_ERROR(System, "impossible to create a temporary file from template "
+ strFrom(tmpFileName));
}
tmpFile = fdopen(fd, "w");
for (Index i = 0; i < m.rows(); ++i)
{
for (Index j = 0; j < m.cols(); ++j)
{
fprintf(tmpFile, "%e ", m(i, j));
}
fprintf(tmpFile, "\n");
}
fclose(tmpFile);
return string(tmpFileName);
}
// PlotObject test /////////////////////////////////////////////////////////////
bool PlotObject::gotTmpFile(void) const
{
return !tmpFileName_.empty();
}
// PlotCommand constructor /////////////////////////////////////////////////////
PlotCommand::PlotCommand(const string &command)
{
setCommand(command);
}
// PlotHeadCommand constructor /////////////////////////////////////////////////
PlotHeadCommand::PlotHeadCommand(const string &command)
{
setHeadCommand(command);
}
// PlotData constructor ////////////////////////////////////////////////////////
PlotData::PlotData(const DMatSample &x, const DMatSample &y)
{
if (x[central].rows() != y[central].rows())
{
LATAN_ERROR(Size, "x and y vector does not have the same size");
}
DMat d(x[central].rows(), 4);
string usingCmd, tmpFileName;
d.col(0) = x[central];
d.col(2) = y[central];
d.col(1) = x.variance().cwiseSqrt();
d.col(3) = y.variance().cwiseSqrt();
tmpFileName = dumpToTmpFile(d);
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' u 1:3:2:4 w xyerr");
}
PlotData::PlotData(const DVec &x, const DMatSample &y)
{
if (x.rows() != y[central].rows())
{
LATAN_ERROR(Size, "x and y vector does not have the same size");
}
DMat d(x.rows(), 3);
string usingCmd, tmpFileName;
d.col(0) = x;
d.col(1) = y[central];
d.col(2) = y.variance().cwiseSqrt();
tmpFileName = dumpToTmpFile(d);
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' u 1:2:3 w yerr");
}
PlotData::PlotData(const DMatSample &x, const DVec &y)
{
if (x[central].rows() != y.rows())
{
LATAN_ERROR(Size, "x and y vector does not have the same size");
}
DMat d(x[central].rows(), 3), xerr, yerr;
string usingCmd, tmpFileName;
d.col(0) = x[central];
d.col(2) = y;
d.col(1) = x.variance().cwiseSqrt();
tmpFileName = dumpToTmpFile(d);
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' u 1:3:2 w xerr");
}
PlotData::PlotData(const XYStatData &data, const Index i, const Index j)
{
string usingCmd, tmpFileName;
usingCmd = (data.isXExact(i)) ? "u 1:3:4 w yerr" : "u 1:3:2:4 w xyerr";
tmpFileName = dumpToTmpFile(data.getTable(i, j));
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' " + usingCmd);
}
// PlotHLine constructor ///////////////////////////////////////////////////////
PlotHLine::PlotHLine(const double y)
{
setCommand(strFrom(y));
}
// PlotHBand constructor ///////////////////////////////////////////////////////
PlotBand::PlotBand(const double xMin, const double xMax, const double yMin,
const double yMax, const double opacity)
{
setCommand("'< printf \"%e %e\\n%e %e\\n%e %e\\n%e %e\\n%e %e\\n\" "
+ strFrom(xMin) + " " + strFrom(yMin) + " "
+ strFrom(xMax) + " " + strFrom(yMin) + " "
+ strFrom(xMax) + " " + strFrom(yMax) + " "
+ strFrom(xMin) + " " + strFrom(yMax) + " "
+ strFrom(xMin) + " " + strFrom(yMin)
+ "' u 1:2 w filledcurves closed fs solid " + strFrom(opacity)
+ " noborder");
}
// PlotFunction constructor ////////////////////////////////////////////////////
PlotFunction::PlotFunction(const DoubleFunction &function, const double xMin,
const double xMax, const unsigned int nPoint)
{
DMat d(nPoint, 2);
string tmpFileName;
double dx = (xMax - xMin)/static_cast<double>(nPoint - 1);
for (Index i = 0; i < nPoint; ++i)
{
d(i, 0) = xMin + i*dx;
d(i, 1) = function(d(i, 0));
}
tmpFileName = dumpToTmpFile(d);
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' u 1:2 w lines");
}
// PlotPredBand constructor ////////////////////////////////////////////////////
PlotPredBand::PlotPredBand(const DoubleFunctionSample &function,
const double xMin, const double xMax,
const unsigned int nPoint, const double opacity)
{
DMat dLow(nPoint, 2), dHigh(nPoint, 2);
DSample pred(function.size());
double dx = (xMax - xMin)/static_cast<double>(nPoint - 1);
string lowFileName, highFileName;
for (Index i = 0; i < nPoint; ++i)
{
double x = xMin + i*dx, err;
pred = function(x);
err = sqrt(pred.variance());
dLow(i, 0) = x;
dLow(i, 1) = pred[central] - err;
dHigh(i, 0) = x;
dHigh(i, 1) = pred[central] + err;
}
lowFileName = dumpToTmpFile(dLow);
highFileName = dumpToTmpFile(dHigh);
pushTmpFile(lowFileName);
pushTmpFile(highFileName);
setCommand("'< (cat " + lowFileName + "; tac " + highFileName +
"; head -n1 " + lowFileName + ")' u 1:2 w filledcurves closed" +
" fs solid " + strFrom(opacity) + " noborder");
}
// PlotHistogram constructor ///////////////////////////////////////////////////
PlotHistogram::PlotHistogram(const Histogram &h)
{
DMat d(h.size(), 2);
string tmpFileName;
for (Index i = 0; i < h.size(); ++i)
{
d(i, 0) = h.getX(i);
d(i, 1) = h[i];
}
tmpFileName = dumpToTmpFile(d);
pushTmpFile(tmpFileName);
setCommand("'" + tmpFileName + "' u 1:2 w steps");
}
// PlotMatrixNoRange constructor ///////////////////////////////////////////////
PlotMatrixNoRange::PlotMatrixNoRange(const DMat &m)
{
string tmpFileName = dumpToTmpFile(m);
setCommand("'" + tmpFileName + "' matrix w image");
}
/******************************************************************************
* Plot modifiers *
******************************************************************************/
// Caption constructor /////////////////////////////////////////////////////////
Caption::Caption(const string &caption)
: caption_(caption)
{}
// Caption modifier ////////////////////////////////////////////////////////////
void Caption::operator()(PlotOptions &option) const
{
option.caption = caption_;
}
// Label constructor ///////////////////////////////////////////////////////////
Label::Label(const string &label, const Axis axis)
: label_(label)
, axis_(axis)
{}
// Label modifier //////////////////////////////////////////////////////////////
void Label::operator()(PlotOptions &option) const
{
option.label[static_cast<int>(axis_)] = label_;
}
// Color constructor ///////////////////////////////////////////////////////////
Color::Color(const string &color)
: color_(color)
{}
// Color modifier //////////////////////////////////////////////////////////////
void Color::operator()(PlotOptions &option) const
{
option.lineColor = color_;
}
// LogScale constructor ////////////////////////////////////////////////////////
LogScale::LogScale(const Axis axis)
: axis_(axis)
{}
// Logscale modifier ///////////////////////////////////////////////////////////
void LogScale::operator()(PlotOptions &option) const
{
option.scaleMode[static_cast<int>(axis_)] |= Plot::Scale::log;
}
// PlotRange constructors //////////////////////////////////////////////////////
PlotRange::PlotRange(const Axis axis)
: axis_(axis)
, reset_(true)
, min_(0.)
, max_(0.)
{}
PlotRange::PlotRange(const Axis axis, const double min, const double max)
: axis_(axis)
, reset_(false)
, min_(min)
, max_(max)
{}
// PlotRange modifier ///////////////////////////////////////////////////////////
void PlotRange::operator()(PlotOptions &option) const
{
int a = static_cast<int>(axis_);
if (!reset_)
{
option.scaleMode[a] |= Plot::Scale::manual;
option.scale[a].min = min_;
option.scale[a].max = max_;
}
else
{
option.scaleMode[a] = Plot::Scale::reset;
}
}
// Terminal constructor ////////////////////////////////////////////////////////
Terminal::Terminal(const string &terminal, const std::string &options)
: terminalCmd_(terminal + " " + options)
{}
// Terminal modifier ///////////////////////////////////////////////////////////
void Terminal::operator()(PlotOptions &option) const
{
option.terminal = terminalCmd_;
}
// Title constructor ///////////////////////////////////////////////////////////
Title::Title(const string &title)
: title_(title)
{}
// Title modifier //////////////////////////////////////////////////////////////
void Title::operator()(PlotOptions &option) const
{
option.title = title_;
}
/******************************************************************************
* Plot implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
Plot::Plot(void)
{
initOptions();
}
// default options /////////////////////////////////////////////////////////////
void Plot::initOptions(void)
{
options_.terminal = "qt";
options_.output = "";
options_.caption = "";
options_.title = "";
options_.scaleMode[0] = Plot::Scale::reset;
options_.scaleMode[1] = Plot::Scale::reset;
options_.scale[0] = {0.0, 0.0};
options_.scale[1] = {0.0, 0.0};
options_.label[0] = "";
options_.label[1] = "";
options_.lineColor = "";
}
// plot reset //////////////////////////////////////////////////////////////////
void Plot::reset(void)
{
headCommand_.clear();
plotCommand_.clear();
tmpFileName_.clear();
initOptions();
}
// plot objects ////////////////////////////////////////////////////////////////
Plot & Plot::operator<<(PlotObject &&command)
{
string commandStr;
while (command.gotTmpFile())
{
tmpFileName_.push_back(command.popTmpFile());
commandStr += "'" + tmpFileName_.back() + "' ";
}
commandStr = command.getCommand();
if (!commandStr.empty())
{
if (!options_.lineColor.empty())
{
commandStr += " lc " + options_.lineColor;
options_.lineColor = "";
}
if (options_.title.empty())
{
commandStr += " notitle";
}
else
{
commandStr += " t '" + options_.title + "'";
options_.title = "";
}
plotCommand_.push_back(commandStr);
}
if (!command.getHeadCommand().empty())
{
headCommand_.push_back(command.getHeadCommand());
}
return *this;
}
Plot & Plot::operator<<(PlotModifier &&modifier)
{
modifier(options_);
return *this;
}
// find gnuplot ////////////////////////////////////////////////////////////////
void Plot::getProgramPath(void)
{
int i, j, lg;
char *path;
static char buf[MAX_PATH_LENGTH];
// trivial case: try in CWD
sprintf(buf,"./%s", gnuplotBin_.c_str()) ;
if (access(buf, X_OK) == 0)
{
sprintf(buf,".");
gnuplotPath_ = buf;
}
// try out in all paths given in the PATH variable
else
{
buf[0] = 0;
path = getenv("PATH") ;
if (path)
{
for (i=0;path[i];)
{
for (j=i;(path[j]) and (path[j]!=':');j++);
lg = j - i;
strncpy(buf,path + i,(size_t)(lg));
if (lg == 0)
{
buf[lg++] = '.';
}
buf[lg++] = '/';
strcpy(buf + lg, gnuplotBin_.c_str());
if (access(buf, X_OK) == 0)
{
// found it!
break ;
}
buf[0] = 0;
i = j;
if (path[i] == ':') i++ ;
}
}
else
{
LATAN_ERROR(System, "PATH variable not set");
}
// if the buffer is still empty, the command was not found
if (buf[0] == 0)
{
LATAN_ERROR(System, "cannot find gnuplot in $PATH");
}
// otherwise truncate the command name to yield path only
lg = (int)(strlen(buf) - 1);
while (buf[lg]!='/')
{
buf[lg] = 0;
lg--;
}
buf[lg] = 0;
gnuplotPath_ = buf;
}
}
// plot parsing and output /////////////////////////////////////////////////////
void Plot::display(void)
{
int pid = fork();
if (pid == 0)
{
FILE *gnuplotPipe;
string command;
ostringstream scriptBuf;
if (!getenv("DISPLAY"))
{
LATAN_ERROR(System, "cannot find DISPLAY variable: is it set ?");
}
getProgramPath();
command = gnuplotPath_ + "/" + gnuplotBin_;
gnuplotPipe = popen(command.c_str(), "w");
if (!gnuplotPipe)
{
LATAN_ERROR(System, "error starting gnuplot (command was '"
+ command + "')");
}
commandBuffer_.str("");
commandBuffer_ << *this << endl;
commandBuffer_ << "pause mouse close" << endl;
fprintf(gnuplotPipe, "%s", commandBuffer_.str().c_str());
if (pclose(gnuplotPipe) == -1)
{
LATAN_ERROR(System, "problem closing communication to gnuplot");
}
exit(EXIT_SUCCESS);
}
else if (pid == -1)
{
perror("fork error");
LATAN_ERROR(System, "problem forking to the process handling gnuplot");
}
}
void Plot::save(string dirName)
{
vector<string> commandBack;
string path, terminalBack, outputBack, gpCommand, scriptName;
mode_t mode755;
ofstream script;
mode755 = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
// backup I/O parameters
terminalBack = options_.terminal;
outputBack = options_.output;
commandBack = plotCommand_;
// generate directory
if (mkdir(dirName))
{
LATAN_ERROR(Io, "impossible to create directory '" + dirName + "'");
}
// save PDF
options_.terminal = "pdf";
options_.output = dirName + "/plot.pdf";
display();
options_.terminal = terminalBack;
options_.output = outputBack;
// save script and datafiles
for (unsigned int i = 0; i < tmpFileName_.size(); ++i)
{
ofstream dataFile;
ifstream tmpFile;
string dataFileName = "points_" + strFrom(i) + ".dat";
dataFile.open(dirName + "/" + dataFileName);
tmpFile.open(tmpFileName_[i]);
dataFile << tmpFile.rdbuf();
dataFile.close();
tmpFile.close();
for (string &command: plotCommand_)
{
auto pos = command.find(tmpFileName_[i]);
while (pos != string::npos)
{
command.replace(pos, tmpFileName_[i].size(), dataFileName);
pos = command.find(tmpFileName_[i], pos + 1);
}
}
}
scriptName = dirName + "/source.plt";
script.open(scriptName);
getProgramPath();
gpCommand = gnuplotPath_ + "/" + gnuplotBin_ + " " + gnuplotArgs_;
script << "#!/usr/bin/env " << gpCommand << "\n" << endl;
script << "# script generated by " << Env::fullName << "\n" << endl;
script << *this;
script.close();
if (chmod(scriptName.c_str(), mode755))
{
LATAN_ERROR(Io, "impossible to set file '" + scriptName +
"' in mode 755");
}
plotCommand_ = commandBack;
}
ostream & Latan::operator<<(ostream &out, const Plot &plot)
{
std::string begin, end;
int x = static_cast<int>(Axis::x), y = static_cast<int>(Axis::y);
if (!plot.options_.terminal.empty())
{
out << "set term " << plot.options_.terminal << endl;
}
if (!plot.options_.output.empty())
{
out << "set output '" << plot.options_.output << "'" << endl;
}
if (!plot.options_.caption.empty())
{
out << "set title '" << plot.options_.caption << "'" << endl;
}
if (plot.options_.scaleMode[x] & Plot::Scale::manual)
{
out << "xMin = " << plot.options_.scale[x].min << endl;
out << "xMax = " << plot.options_.scale[x].max << endl;
}
if (plot.options_.scaleMode[y] & Plot::Scale::manual)
{
out << "yMin = " << plot.options_.scale[y].min << endl;
out << "yMax = " << plot.options_.scale[y].max << endl;
}
if (!plot.options_.title.empty())
{
out << "set title '" << plot.options_.title << "'" << endl;
}
if (plot.options_.scaleMode[x] & Plot::Scale::manual)
{
out << "set xrange [xMin:xMax]" << endl;
}
if (plot.options_.scaleMode[y] & Plot::Scale::manual)
{
out << "set yrange [yMin:yMax]" << endl;
}
if (plot.options_.scaleMode[x] & Plot::Scale::log)
{
out << "set log x" << endl;
}
if (plot.options_.scaleMode[y] & Plot::Scale::log)
{
out << "set log y" << endl;
}
if (!plot.options_.label[x].empty())
{
out << "set xlabel '" << plot.options_.label[x] << "'" << endl;
}
if (!plot.options_.label[y].empty())
{
out << "set ylabel '" << plot.options_.label[y] << "'" << endl;
}
for (unsigned int i = 0; i < plot.headCommand_.size(); ++i)
{
out << plot.headCommand_[i] << endl;
}
for (unsigned int i = 0; i < plot.plotCommand_.size(); ++i)
{
begin = (i == 0) ? "plot " : " ";
end = (i == plot.plotCommand_.size() - 1) ? "" : ",\\";
out << begin << plot.plotCommand_[i] << end << endl;
}
return out;
}

342
lib/Core/Plot.hpp Normal file
View File

@ -0,0 +1,342 @@
/*
* Plot.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_Plot_hpp_
#define Latan_Plot_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Functional/Function.hpp>
#include <LatAnalyze/Core/Mat.hpp>
#include <LatAnalyze/Statistics/MatSample.hpp>
#include <LatAnalyze/Statistics/Histogram.hpp>
#include <LatAnalyze/Statistics/XYStatData.hpp>
// gnuplot default parameters
#ifndef GNUPLOT_BIN
#define GNUPLOT_BIN "gnuplot"
#endif
#ifndef GNUPLOT_ARGS
#define GNUPLOT_ARGS "-p"
#endif
BEGIN_LATAN_NAMESPACE
/******************************************************************************
* Plot objects *
******************************************************************************/
class PlotObject
{
public:
// destructor
virtual ~PlotObject(void) = default;
// access
std::string popTmpFile(void);
const std::string & getCommand(void) const;
const std::string & getHeadCommand(void) const;
// test
bool gotTmpFile(void) const;
protected:
// access
void pushTmpFile(const std::string &fileName);
void setCommand(const std::string &command);
void setHeadCommand(const std::string &command);
// dump a matrix to a temporary file
std::string dumpToTmpFile(const DMat &m);
private:
// plot command
std::string command_;
std::string headCommand_;
// stack of created temporary files
std::stack<std::string> tmpFileName_;
};
class PlotCommand: public PlotObject
{
public:
// constructor
explicit PlotCommand(const std::string &command);
// destructor
virtual ~PlotCommand(void) = default;
};
class PlotHeadCommand: public PlotObject
{
public:
// constructor
explicit PlotHeadCommand(const std::string &command);
// destructor
virtual ~PlotHeadCommand(void) = default;
};
class PlotData: public PlotObject
{
public:
// constructor
PlotData(const DMatSample &x, const DMatSample &y);
PlotData(const DVec &x, const DMatSample &y);
PlotData(const DMatSample &x, const DVec &y);
PlotData(const XYStatData &data, const Index i = 0, const Index j = 0);
// destructor
virtual ~PlotData(void) = default;
};
class PlotHLine: public PlotObject
{
public:
// constructor
PlotHLine(const double y);
// destructor
virtual ~PlotHLine(void) = default;
};
class PlotBand: public PlotObject
{
public:
// constructor
PlotBand(const double xMin, const double xMax, const double yMin,
const double yMax, const double opacity = 0.15);
// destructor
virtual ~PlotBand(void) = default;
};
class PlotFunction: public PlotObject
{
public:
// constructor
PlotFunction(const DoubleFunction &function, const double xMin,
const double xMax, const unsigned int nPoint = 1000);
// destructor
virtual ~PlotFunction(void) = default;
};
class PlotPredBand: public PlotObject
{
public:
// constructor
PlotPredBand(const DoubleFunctionSample &function, const double xMin,
const double xMax, const unsigned int nPoint = 1000,
const double opacity = 0.15);
// destructor
virtual ~PlotPredBand(void) = default;
};
class PlotHistogram: public PlotObject
{
public:
// constructor
PlotHistogram(const Histogram &h);
// destructor
virtual ~PlotHistogram(void) = default;
};
class PlotMatrixNoRange: public PlotObject
{
public:
// constructor
PlotMatrixNoRange(const DMat &m);
// destructor
virtual ~PlotMatrixNoRange(void) = default;
};
#define PlotMatrix(m)\
PlotRange(Axis::x, -.5, (m).cols() - .5) <<\
PlotRange(Axis::y, (m).rows() - .5, -.5) <<\
PlotMatrixNoRange(m)
/******************************************************************************
* Plot modifiers *
******************************************************************************/
enum class Axis {x = 0, y = 1};
struct Range
{
double min, max;
};
struct PlotOptions
{
std::string terminal;
std::string output;
std::string caption;
std::string title;
unsigned int scaleMode[2];
Range scale[2];
std::string label[2];
std::string lineColor;
};
class PlotModifier
{
public:
// destructor
virtual ~PlotModifier(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const = 0;
};
class Caption: public PlotModifier
{
public:
// constructor
explicit Caption(const std::string &title);
// destructor
virtual ~Caption(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const std::string caption_;
};
class Label: public PlotModifier
{
public:
// constructor
explicit Label(const std::string &label, const Axis axis);
// destructor
virtual ~Label(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const std::string label_;
const Axis axis_;
};
class Color: public PlotModifier
{
public:
// constructor
explicit Color(const std::string &color);
// destructor
virtual ~Color(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const std::string color_;
};
class LogScale: public PlotModifier
{
public:
// constructor
explicit LogScale(const Axis axis);
// destructor
virtual ~LogScale(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const Axis axis_;
};
class PlotRange: public PlotModifier
{
public:
// constructors
PlotRange(const Axis axis);
PlotRange(const Axis axis, const double min, const double max);
// destructor
virtual ~PlotRange(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const Axis axis_;
const bool reset_;
const double min_, max_;
};
class Terminal: public PlotModifier
{
public:
// constructor
Terminal(const std::string &terminal, const std::string &options = "");
// destructor
virtual ~Terminal(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const std::string terminalCmd_;
};
class Title: public PlotModifier
{
public:
// constructor
explicit Title(const std::string &title);
// destructor
virtual ~Title(void) = default;
// modifier
virtual void operator()(PlotOptions &option) const;
private:
const std::string title_;
};
/******************************************************************************
* Plot class *
******************************************************************************/
class Plot
{
public:
class Scale
{
public:
enum
{
reset = 0,
manual = 1 << 0,
log = 1 << 1
};
};
public:
// constructor/destructor
Plot(void);
virtual ~Plot(void) = default;
// plot operations
Plot & operator<<(PlotObject &&command);
Plot & operator<<(PlotModifier &&modifier);
// plot parsing and output
void display(void);
void save(std::string dirName);
friend std::ostream & operator<<(std::ostream &out, const Plot &plot);
// plot reset
void reset(void);
private:
// find gnuplot
void getProgramPath(void);
// default options
void initOptions(void);
private:
// gnuplot execution parameters
std::string gnuplotBin_ {GNUPLOT_BIN};
std::string gnuplotArgs_ {GNUPLOT_ARGS};
std::string gnuplotPath_ {""};
// string buffer for commands
std::ostringstream commandBuffer_;
// stack of created temporary files
std::vector<std::string> tmpFileName_;
// plot content
PlotOptions options_;
std::vector<std::string> headCommand_;
std::vector<std::string> plotCommand_;
};
std::ostream & operator<<(std::ostream &out, const Plot &plot);
END_LATAN_NAMESPACE
#endif // Latan_Plot_hpp_

137
lib/Core/Utilities.cpp Normal file
View File

@ -0,0 +1,137 @@
/*
* Utilities.cpp, part of LatAnalyze
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Core/Utilities.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
void Latan::testFunction(void)
{}
ostream & Latan::operator<<(ostream &out, const ProgressBar &&bar)
{
const Index nTick = bar.nCol_*bar.current_/bar.total_;
out << "[";
for (Index i = 0; i < nTick; ++i)
{
out << "=";
}
for (Index i = nTick; i < bar.nCol_; ++i)
{
out << " ";
}
out << "] " << bar.current_ << "/" << bar.total_;
out.flush();
return out;
}
int Latan::mkdir(const std::string dirName)
{
if (access(dirName.c_str(), R_OK|W_OK|X_OK))
{
mode_t mode755;
char tmp[MAX_PATH_LENGTH];
char *p = NULL;
size_t len;
mode755 = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
snprintf(tmp, sizeof(tmp), "%s", dirName.c_str());
len = strlen(tmp);
if(tmp[len - 1] == '/')
{
tmp[len - 1] = 0;
}
for(p = tmp + 1; *p; p++)
{
if(*p == '/')
{
*p = 0;
::mkdir(tmp, mode755);
*p = '/';
}
}
return ::mkdir(tmp, mode755);
}
else
{
return 0;
}
}
string Latan::basename(const string &s)
{
constexpr char sep = '/';
size_t i = s.rfind(sep, s.length());
if (i != string::npos)
{
return s.substr(i+1, s.length() - i);
}
else
{
return s;
}
}
std::string Latan::dirname(const std::string &s)
{
constexpr char sep = '/';
size_t i = s.rfind(sep, s.length());
if (i != std::string::npos)
{
return s.substr(0, i);
}
else
{
return "";
}
}
VarName::VarName(const string defName)
: defName_(defName)
{}
string VarName::getName(const Index i) const
{
if (hasName(i))
{
return name_.at(i);
}
else
{
return defName_ + "_" + strFrom(i);
}
}
void VarName::setName(const Index i, const string name)
{
name_[i] = name;
}
bool VarName::hasName(const Index i) const
{
return (name_.find(i) != name_.end());
}

250
lib/Core/Utilities.hpp Normal file
View File

@ -0,0 +1,250 @@
/*
* Utilities.hpp, part of LatAnalyze
*
* Copyright (C) 2013 - 2015 Antonin Portelli
*
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LatAnalyze_Utilities_hpp_
#define LatAnalyze_Utilities_hpp_
#ifndef LATAN_GLOBAL_HPP_
#include <LatAnalyze/Global.hpp>
#endif
BEGIN_LATAN_NAMESPACE
// Random seed type ////////////////////////////////////////////////////////////
typedef std::random_device::result_type SeedType;
// Type utilities //////////////////////////////////////////////////////////////
// pointer type test
template <typename Derived, typename Base>
inline bool isDerivedFrom(const Base *pt)
{
return (dynamic_cast<const Derived *>(pt) != nullptr);
}
// static logical or
template <bool... b>
struct static_or;
template <bool... tail>
struct static_or<true, tail...> : static_or<tail...> {};
template <bool... tail>
struct static_or<false, tail...> : std::false_type {};
template <>
struct static_or<> : std::true_type {};
// Environment /////////////////////////////////////////////////////////////////
void testFunction(void);
// String utilities ////////////////////////////////////////////////////////////
inline std::string extension(const std::string fileName)
{
return fileName.substr(fileName.find_last_of(".") + 1);
}
template <typename T>
inline T strTo(const std::string &str)
{
T buf;
std::istringstream stream(str);
stream >> buf;
return buf;
}
// optimized specializations
template <>
inline float strTo<float>(const std::string &str)
{
return strtof(str.c_str(), (char **)NULL);
}
template <>
inline double strTo<double>(const std::string &str)
{
return strtod(str.c_str(), (char **)NULL);
}
template <>
inline int strTo<int>(const std::string &str)
{
return (int)(strtol(str.c_str(), (char **)NULL, 10));
}
template <>
inline long strTo<long>(const std::string &str)
{
return strtol(str.c_str(), (char **)NULL, 10);
}
template <>
inline std::string strTo<std::string>(const std::string &str)
{
return str;
}
template <typename T>
inline std::string strFrom(const T x)
{
std::ostringstream stream;
stream << x;
return stream.str();
}
// specialization for vectors
template<>
inline DVec strTo<DVec>(const std::string &str)
{
DVec res;
std::vector<double> vbuf;
double buf;
std::istringstream stream(str);
while (!stream.eof())
{
stream >> buf;
vbuf.push_back(buf);
}
res = Map<DVec>(vbuf.data(), static_cast<Index>(vbuf.size()));
return res;
}
template<>
inline IVec strTo<IVec>(const std::string &str)
{
IVec res;
std::vector<int> vbuf;
int buf;
std::istringstream stream(str);
while (!stream.eof())
{
stream >> buf;
vbuf.push_back(buf);
}
res = Map<IVec>(vbuf.data(), static_cast<Index>(vbuf.size()));
return res;
}
template<>
inline UVec strTo<UVec>(const std::string &str)
{
UVec res;
std::vector<unsigned int> vbuf;
unsigned int buf;
std::istringstream stream(str);
while (!stream.eof())
{
stream >> buf;
vbuf.push_back(buf);
}
res = Map<UVec>(vbuf.data(), static_cast<Index>(vbuf.size()));
return res;
}
template <typename T>
void tokenReplace(std::string &str, const std::string token,
const T &x, const std::string mark = "@")
{
std::string fullToken = mark + token + mark;
auto pos = str.find(fullToken);
if (pos != std::string::npos)
{
str.replace(pos, fullToken.size(), strFrom(x));
}
}
// Manifest file reader ////////////////////////////////////////////////////////
inline std::vector<std::string> readManifest(const std::string manFileName)
{
std::vector<std::string> list;
std::ifstream manFile;
char buf[MAX_PATH_LENGTH];
manFile.open(manFileName);
while (!manFile.eof())
{
manFile.getline(buf, MAX_PATH_LENGTH);
if (!std::string(buf).empty())
{
list.push_back(buf);
}
}
manFile.close();
return list;
}
// Recursive directory creation ////////////////////////////////////////////////
int mkdir(const std::string dirName);
// C++ version of basename/dirname /////////////////////////////////////////////
std::string basename(const std::string& s);
std::string dirname(const std::string& s);
// Progress bar class //////////////////////////////////////////////////////////
class ProgressBar
{
public:
// constructor
template <typename A, typename B>
ProgressBar(const A current, const B total, const Index nCol = 60);
// IO
friend std::ostream & operator<<(std::ostream &out,
const ProgressBar &&bar);
private:
Index current_, total_, nCol_;
};
template <typename A, typename B>
ProgressBar::ProgressBar(const A current, const B total, const Index nCol)
: current_(static_cast<Index>(current))
, total_(static_cast<Index>(total))
, nCol_(nCol)
{}
std::ostream & operator<<(std::ostream &out, const ProgressBar &&bar);
// named variable interface ////////////////////////////////////////////////////
// FIXME: check redundant names and variable number limit
class VarName
{
public:
// constructor
VarName(const std::string defName);
// destructor
virtual ~VarName(void) = default;
// access
std::string getName(const Index i) const;
void setName(const Index i, const std::string name);
// test
bool hasName(const Index i) const;
private:
std::string defName_;
std::unordered_map<Index, std::string> name_;
};
END_LATAN_NAMESPACE
#endif // LatAnalyze_Utilities_hpp_

56
lib/Core/stdincludes.hpp Normal file
View File

@ -0,0 +1,56 @@
/*
* stdincludes.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_stdincludes_hpp_
#define Latan_stdincludes_hpp_
#include <algorithm>
#include <array>
#include <chrono>
#include <complex>
#include <fstream>
#include <functional>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <stack>
#include <string>
#include <sstream>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <unistd.h>
#endif // Latan_stdincludes_hpp_