diff --git a/.gitignore b/.gitignore index 65989e1..46899ee 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,14 @@ latan/*Parser.hpp # Eigen headers latan/Eigen/* latan/eigen_files.mk + +# Examples +examples/exCompiledDoubleFunction +examples/exMat +examples/exMathInterpreter +examples/exPlot +examples/exRand +examples/exRand.seed + +# Utils +utils/latan_sample_read diff --git a/Makefile.am b/Makefile.am index 498367c..617ac3c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = latan examples +SUBDIRS = latan utils examples ACLOCAL_AMFLAGS = -I .buildutils/m4 diff --git a/acinclude.m4 b/acinclude.m4 index cf791ad..034ca55 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -91,4 +91,145 @@ done ]) ]) +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# The first argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The second argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline C++11 support is required and that the macro +# should error out if no mode with that support is found. If specified +# 'optional', then configuration proceeds regardless, after defining +# HAVE_CXX11 if and only if a supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014 Alexey Sokolov +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + struct Base { + virtual void f() {} + }; + struct Child : public Base { + virtual void f() override {} + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + auto l = [](){}; +]]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], + [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], + [$2], [optional], [ax_cxx_compile_cxx11_required=false], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + AC_MSG_NOTICE([No compiler with C++11 support was found]) + else + HAVE_CXX11=1 + AC_DEFINE(HAVE_CXX11,1, + [define if the compiler supports basic C++11 syntax]) + fi + + AC_SUBST(HAVE_CXX11) + fi +]) + diff --git a/configure.ac b/configure.ac index 8b5da33..014d4e7 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,7 @@ AC_PREREQ([2.64]) AC_INIT([LatAnalyze],[3.0alpha1],[antonin.portelli@me.com],[latan]) AC_CONFIG_AUX_DIR([.buildutils]) AC_CONFIG_SRCDIR([latan/Global.cpp]) +AC_CONFIG_SRCDIR([utils/sample_read.cpp]) AC_CONFIG_SRCDIR([examples/exMathInterpreter.cpp]) AC_CONFIG_MACRO_DIR([.buildutils/m4]) AM_INIT_AUTOMAKE([-Wall -Werror]) @@ -42,12 +43,12 @@ AC_DEFINE_UNQUOTED([C_COMP_VENDOR],["$ax_cv_c_compiler_vendor"], AM_CONDITIONAL([CC_GNU],[test $ax_cv_c_compiler_vendor = "gnu"]) AM_CONDITIONAL([CC_INTEL],[test $ax_cv_c_compiler_vendor = "intel"]) AC_LANG([C++]) +AX_CXX_COMPILE_STDCXX_11([noext],[mandatory]) AX_COMPILER_VENDOR AC_DEFINE_UNQUOTED([CXX_COMP_VENDOR],["$ax_cv_cxx_compiler_vendor"], [vendor of C++ compiler that will compile the code]) AM_CONDITIONAL([CXX_GNU],[test $ax_cv_cxx_compiler_vendor = "gnu"]) AM_CONDITIONAL([CXX_INTEL],[test $ax_cv_cxx_compiler_vendor = "intel"]) -AC_LANG([C]) AX_GCC_VERSION AC_DEFINE_UNQUOTED([GCC_VERSION],["$GCC_VERSION"], [version of gcc that will compile the code]) @@ -56,9 +57,7 @@ AC_DEFINE_UNQUOTED([GXX_VERSION],["$GXX_VERSION"], [version of g++ that will compile the code]) # Checks for libraries. -AC_LANG([C++]) AC_CHECK_LIB([m],[cos],[],[AC_MSG_ERROR([libm library not found])]) -AC_CHECK_LIB([stdc++],[main],[LIBS="-lstdc++ $LIBS"],[AC_MSG_ERROR([libstdc++ library not found])]) # Checks for header files. AC_HEADER_STDC @@ -67,5 +66,5 @@ AC_SUBST([LIBS]) AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_LDFLAGS]) -AC_CONFIG_FILES([Makefile latan/Makefile examples/Makefile]) +AC_CONFIG_FILES([Makefile latan/Makefile utils/Makefile examples/Makefile]) AC_OUTPUT diff --git a/examples/exMat.cpp b/examples/exMat.cpp index 589e92b..02609d0 100644 --- a/examples/exMat.cpp +++ b/examples/exMat.cpp @@ -17,10 +17,10 @@ int main(void) F.open(fileName, File::Mode::read); A = F.read("A"); B = F.read("B"); - cout << "A=\n" << A << '\n' << endl; - cout << "B=\n" << B << '\n' << endl; - cout << "A*B=\n" << A*B << '\n' << endl; - cout << "cos(A)=\n" << A.unaryExpr(StdMath::cos) << '\n' << endl; + cout << "A=\n" << A << '\n' << endl; + cout << "B=\n" << B << '\n' << endl; + cout << "A*B=\n" << A*B << '\n' << endl; + cout << "cos(A)=\n" << A.unaryExpr(StdMath::cos) << '\n' << endl; F.close(); // write diff --git a/examples/exMat.dat b/examples/exMat.dat new file mode 100644 index 0000000..6a42143 --- /dev/null +++ b/examples/exMat.dat @@ -0,0 +1,20 @@ +#L latan_begin mat A +2 +2.3 5 +4.5 -1.15281 +#L latan_end mat + +#L latan_begin mat B +3 +1.1 +1.2 +1.3 +2 +2.2 +2.3 +#L latan_end mat +#L latan_begin mat AB +3 + 12.53 13.76 14.49 +2.64438 2.86382 3.19854 +#L latan_end mat diff --git a/examples/exMathCompiler.cpp b/examples/exMathCompiler.cpp deleted file mode 100644 index 227f2e7..0000000 --- a/examples/exMathCompiler.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include - -using namespace std; -using namespace Latan; - -int main(int argc, char* argv[]) -{ - string source; - - if (argc != 2) - { - cerr << "usage: " << argv[0] << " " << endl; - } - source = argv[1]; - - MathCompiler C(source); - VarTable vtable; - FunctionTable ftable; - stack dstack; - const VirtualProgram& P = C(); - - cout << "-- Source code:" << endl << source << endl << endl; - cout << "-- Abstract Syntax Tree:" << endl << *C.getAST() << endl; - cout << "-- Program:" << endl << P << endl; - StdMath::addStdMathFunc(ftable); - for (unsigned int i=0;i("bla"); - B = F.Read("bli"); - cout << A << endl; - cout << B << endl; - cout << A*B << endl; - - return EXIT_SUCCESS; -}*/ - -/* -int main(void) -{ - DMat m(2,2); - - m(0,6) = 3; - m(1,0) = 2.5; - m(0,1) = -1; - m(1,1) = m(1,0) + m(0,1); - cout << "Here is the matrix m:\n" << m << endl; - DVec v(2); - v(0) = 4; - v(1) = v(0) - 1; - cout << "Here is the vector v:\n" << v << endl; -} -*/ diff --git a/latan/CompiledFunction.cpp b/latan/CompiledFunction.cpp index 3fc77ab..3e4d2ab 100644 --- a/latan/CompiledFunction.cpp +++ b/latan/CompiledFunction.cpp @@ -30,31 +30,24 @@ using namespace Latan; // constructor ///////////////////////////////////////////////////////////////// CompiledDoubleFunction::CompiledDoubleFunction(const unsigned nArg) : DoubleFunction(nArg) -{ - interpreter_ = new MathInterpreter; - context_ = new RunContext; -} +{} CompiledDoubleFunction::CompiledDoubleFunction(const unsigned nArg, const string &code) : DoubleFunction(nArg) { - interpreter_ = new MathInterpreter; - context_ = new RunContext; setCode(code); } // destructor ////////////////////////////////////////////////////////////////// CompiledDoubleFunction::~CompiledDoubleFunction(void) -{ - delete interpreter_; - delete context_; -} +{} // access ////////////////////////////////////////////////////////////////////// void CompiledDoubleFunction::setCode(const string &code) { - interpreter_->setCode(code); + interpreter_.reset(new MathInterpreter(code)); + context_.reset(new RunContext); StdMath::addStdMathFunc(context_->fTable); } @@ -89,7 +82,7 @@ double CompiledDoubleFunction::evaluate(const vector &arg) const } // IO ////////////////////////////////////////////////////////////////////////// -ostream &Latan::operator<<(ostream &out, CompiledDoubleFunction &f) +ostream & Latan::operator<<(ostream &out, CompiledDoubleFunction &f) { f.interpreter_->compile(); out << *(f.interpreter_); diff --git a/latan/CompiledFunction.hpp b/latan/CompiledFunction.hpp index b9a2c33..e0f7d35 100644 --- a/latan/CompiledFunction.hpp +++ b/latan/CompiledFunction.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -46,13 +47,15 @@ public: // function call virtual double evaluate(const std::vector &arg) const; // IO - friend std::ostream &operator<<(std::ostream &out, - CompiledDoubleFunction &f); + friend std::ostream & operator<<(std::ostream &out, + CompiledDoubleFunction &f); private: - MathInterpreter* interpreter_; - RunContext* context_; + std::shared_ptr interpreter_; + std::shared_ptr context_; }; +std::ostream & operator<<(std::ostream &out, CompiledDoubleFunction &f); + END_NAMESPACE #endif // Latan_CompiledFunction_hpp_ diff --git a/latan/Function.cpp b/latan/Function.cpp index 714004d..099c661 100644 --- a/latan/Function.cpp +++ b/latan/Function.cpp @@ -61,21 +61,17 @@ unsigned int Function::getNArg(void) const /****************************************************************************** * DoubleFunction implementation * ******************************************************************************/ -DoubleFunction::DoubleFunction(const unsigned nArg, vecFunc *f) +DoubleFunction::DoubleFunction(const unsigned nArg, vecFunc f) : Function(nArg) +, buffer_(new vector(nArg)) , f_(f) -{ - buffer_ = new vector(nArg); -} +{} DoubleFunction::~DoubleFunction(void) -{ - delete buffer_; -} +{} double DoubleFunction::evaluate(const std::vector &arg) const { - std::cout << "double()" << endl; return f_(arg); } diff --git a/latan/Function.hpp b/latan/Function.hpp index b39ed62..1b51280 100644 --- a/latan/Function.hpp +++ b/latan/Function.hpp @@ -21,6 +21,8 @@ #define Latan_Function_hpp_ #include +#include +#include #include #include #include @@ -48,18 +50,18 @@ private: class DoubleFunction: public Function { private: - typedef double vecFunc(const std::vector &); + typedef std::function &)> vecFunc; public: // constructor/destructor - explicit DoubleFunction(const unsigned nArg, vecFunc *f = NULL); + explicit DoubleFunction(const unsigned nArg, vecFunc f = nullptr); virtual ~DoubleFunction(void); // function call virtual double evaluate(const std::vector &arg) const; double operator()(std::stack &arg) const; double operator()(const double x0, ...) const; private: - std::vector *buffer_; - vecFunc *f_; + std::shared_ptr> buffer_; + vecFunc f_; }; END_NAMESPACE diff --git a/latan/Global.hpp b/latan/Global.hpp index 44d1b13..f204e2f 100644 --- a/latan/Global.hpp +++ b/latan/Global.hpp @@ -77,13 +77,6 @@ std::string strFrom(const T x) return stream.str(); } -// key test in maps -template -bool keyExists(const K &key, const std::map &map) -{ - return (map.find(key) != map.end()); -} - END_NAMESPACE #include diff --git a/latan/Io.cpp b/latan/Io.cpp index 30aab5a..7166642 100644 --- a/latan/Io.cpp +++ b/latan/Io.cpp @@ -59,11 +59,9 @@ unsigned int File::getMode(void) const // internal functions ////////////////////////////////////////////////////////// void File::deleteData(void) { - IoDataTable::iterator i; - - for (i=data_.begin();i!=data_.end();++i) + for (auto &i : data_) { - delete i->second; + i.second.reset(); } data_.clear(); } @@ -80,8 +78,8 @@ void File::checkWritability(void) * AsciiFile implementation * ******************************************************************************/ // AsciiParserState constructor //////////////////////////////////////////////// -AsciiFile::AsciiParserState::AsciiParserState(istream* stream, string* name, - IoDataTable* data) +AsciiFile::AsciiParserState::AsciiParserState(istream *stream, string *name, + IoDataTable *data) : ParserState(stream, name, data) { initScanner(); @@ -97,7 +95,7 @@ AsciiFile::AsciiParserState::~AsciiParserState(void) AsciiFile::AsciiFile(void) : File(), fileStream_() , isParsed_(false) -, state_(NULL) +, state_(nullptr) {} AsciiFile::AsciiFile(const string &name, const unsigned int mode) @@ -140,8 +138,7 @@ bool AsciiFile::isOpen() const // IO ////////////////////////////////////////////////////////////////////////// void AsciiFile::close(void) { - delete state_; - state_ = NULL; + state_.reset(nullptr); if (isOpen()) { fileStream_.close(); @@ -160,7 +157,7 @@ void AsciiFile::open(const string &name, const unsigned int mode) } else { - ios_base::openmode stdMode = 0; + ios_base::openmode stdMode = static_cast(0); if (mode & Mode::write) { @@ -180,11 +177,11 @@ void AsciiFile::open(const string &name, const unsigned int mode) fileStream_.open(name_.c_str(), stdMode); if (mode_ & Mode::read) { - state_ = new AsciiParserState(&fileStream_, &name_, &data_); + state_.reset(new AsciiParserState(&fileStream_, &name_, &data_)); } else { - state_ = NULL; + state_.reset(nullptr); } } } @@ -214,11 +211,11 @@ void AsciiFile::load(const string &name __dumb) // parser ////////////////////////////////////////////////////////////////////// // Bison/Flex parser declaration -int _ioAscii_parse(AsciiFile::AsciiParserState* state); +int _ioAscii_parse(AsciiFile::AsciiParserState *state); void AsciiFile::parse() { fileStream_.seekg(0); - _ioAscii_parse(state_); + _ioAscii_parse(state_.get()); isParsed_ = true; } diff --git a/latan/Io.hpp b/latan/Io.hpp index ed383e9..a6c8077 100644 --- a/latan/Io.hpp +++ b/latan/Io.hpp @@ -21,10 +21,11 @@ #define Latan_Io_hpp_ #include -#include +#include #include #include #include +#include #include #include #include @@ -37,7 +38,7 @@ BEGIN_NAMESPACE /****************************************************************************** * Generic datafile class * ******************************************************************************/ -typedef std::map IoDataTable; +typedef std::unordered_map> IoDataTable; class File { @@ -98,13 +99,11 @@ const IoT& File::read(const std::string &name) template const IoT& File::getData(const std::string &name) const { - IoDataTable::const_iterator i = data_.find(name); - - if (i != data_.end()) + try { - return dynamic_cast(*(i->second)); + return dynamic_cast(*(data_.at(name))); } - else + catch(std::out_of_range) { LATAN_ERROR(Definition, "no data with name '" + name + "'"); } @@ -120,14 +119,16 @@ public: { public: // constructor - explicit AsciiParserState(std::istream *stream, std::string *name,\ + explicit AsciiParserState(std::istream *stream, std::string *name, IoDataTable *data); // destructor virtual ~AsciiParserState(void); - // public members - std::stack dMatBuf; - std::stack doubleBuf; - std::stack intBuf; + // parsing buffers + DMat dMatBuf; + RandGen::State stateBuf; + std::stack dMatStack; + std::stack doubleStack; + std::stack intStack; private: // allocation/deallocation functions defined in IoAsciiLexer.lpp virtual void initScanner(void); @@ -153,9 +154,9 @@ private: // parser void parse(void); private: - std::fstream fileStream_; - bool isParsed_; - AsciiParserState* state_; + std::fstream fileStream_; + bool isParsed_; + std::unique_ptr state_; }; END_NAMESPACE diff --git a/latan/IoAsciiParser.ypp b/latan/IoAsciiParser.ypp index cea7dc2..02044af 100644 --- a/latan/IoAsciiParser.ypp +++ b/latan/IoAsciiParser.ypp @@ -19,7 +19,9 @@ %{ #include + #include #include + #include #include #include #include @@ -29,6 +31,8 @@ using namespace std; using namespace Latan; + + #define STORE(ref) (*state->data)[(ref).first] = std::move((ref).second) %} %pure-parser @@ -42,20 +46,19 @@ %union { - int val_int; - double val_double; - char val_char; - char val_str[256]; + int val_int; + double val_double; + char val_char; + char val_str[256]; } -%token CLOSE %token ERR %token FLOAT %token INT %token ID -%token MAT -%token RG_STATE -%token OPEN +%token OPEN CLOSE MAT RG_STATE + +%type mat rg_state %{ int _ioAscii_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner); @@ -82,24 +85,25 @@ datas: data: mat + {(*state->data)[$1].reset(new DMat(state->dMatBuf));} | rg_state + {(*state->data)[$1].reset(new RandGen::State(state->stateBuf));} ; mat: OPEN MAT ID INT floats CLOSE MAT { - const int nRow = state->doubleBuf.size()/$INT, nCol = $INT; - (*state->data)[$ID] = new DMat(nRow, nCol); - DMat &m = static_cast(*((*state->data)[$ID])); + const int nRow = state->doubleStack.size()/$INT, nCol = $INT; int r, i, j; r = 0; - while (!state->doubleBuf.empty()) + state->dMatBuf.resize(nRow, nCol); + while (!state->doubleStack.empty()) { j = r % nCol; i = (r - j)/nCol; - m(i, j) = state->doubleBuf.top(); - state->doubleBuf.pop(); + state->dMatBuf(i, j) = state->doubleStack.top(); + state->doubleStack.pop(); ++r; } if (r != nRow*nCol) @@ -107,22 +111,19 @@ mat: LATAN_ERROR(Range, "matrix '" + *state->streamName + ":" + $ID + "' has a wrong size"); } + strcpy($$, $ID); } ; rg_state: OPEN RG_STATE ID ints CLOSE RG_STATE { - (*state->data)[$ID] = new RandGen::State; - RandGen::State &rgState = - static_cast(*((*state->data)[$ID])); - for (int i = 0; i < RLXG_STATE_SIZE; ++i) { - if (!state->intBuf.empty()) + if (!state->intStack.empty()) { - rgState[i] = state->intBuf.top(); - state->intBuf.pop(); + state->stateBuf[i] = state->intStack.top(); + state->intStack.pop(); } else { @@ -130,22 +131,23 @@ rg_state: *state->streamName + ":" + $ID + "' is too short"); } } - if (!state->intBuf.empty()) + if (!state->intStack.empty()) { LATAN_ERROR(Range, "random generator state '" + *state->streamName + ":" + $ID + "' is too long"); } + strcpy($$, $ID); } ; floats: - FLOAT floats {state->doubleBuf.push($1);} - | INT floats {state->doubleBuf.push(static_cast($1));} - | FLOAT {state->doubleBuf.push($1);} - | INT {state->doubleBuf.push(static_cast($1));} + FLOAT floats {state->doubleStack.push($1);} + | INT floats {state->doubleStack.push(static_cast($1));} + | FLOAT {state->doubleStack.push($1);} + | INT {state->doubleStack.push(static_cast($1));} ; ints: - INT ints {state->intBuf.push($1);} - | INT {state->intBuf.push($1);} + INT ints {state->intStack.push($1);} + | INT {state->intStack.push($1);} ; diff --git a/latan/IoObject.hpp b/latan/IoObject.hpp index 9ea1c13..55481a2 100644 --- a/latan/IoObject.hpp +++ b/latan/IoObject.hpp @@ -28,20 +28,16 @@ BEGIN_NAMESPACE class IoObject { public: - class IoType + enum class IoType { - public: - enum - { - noType = 0, - dMat = 1, - dMatSample = 2, - rgState = 3 - }; + noType = 0, + dMat = 1, + dMatSample = 2, + rgState = 3 }; public: virtual ~IoObject(void) {}; - virtual unsigned int getType(void) const = 0; + virtual IoType getType(void) const = 0; }; END_NAMESPACE diff --git a/latan/Mat.cpp b/latan/Mat.cpp index 974602d..e09004b 100644 --- a/latan/Mat.cpp +++ b/latan/Mat.cpp @@ -35,7 +35,7 @@ DMat::DMat(const unsigned int nRow, const unsigned int nCol) : Base(nRow, nCol) {} -unsigned int DMat::getType(void) const +IoObject::IoType DMat::getType(void) const { return IoType::dMat; } diff --git a/latan/Mat.hpp b/latan/Mat.hpp index e3875d5..87767b6 100644 --- a/latan/Mat.hpp +++ b/latan/Mat.hpp @@ -37,7 +37,7 @@ public: template DMat(const Eigen::EigenBase &m); // IO - virtual unsigned int getType(void) const; + virtual IoType getType(void) const; }; template diff --git a/latan/MathCompiler.cpp b/latan/MathCompiler.cpp deleted file mode 100644 index 50b17b4..0000000 --- a/latan/MathCompiler.cpp +++ /dev/null @@ -1,504 +0,0 @@ -#include -#include - -using namespace std; -using namespace Latan; - -// Math Bison/Flex parser declaration -int _math_parse(MathCompiler::MathParserState* state); - -/****************************************************************************** - * MathNode implementation * - ******************************************************************************/ -// constructor ///////////////////////////////////////////////////////////////// -MathNode::MathNode(const string &name, const unsigned int type) -: name_(name) -, type_(type) -, parent_(NULL) -{} - -MathNode::MathNode(const std::string &name, const unsigned int type,\ - const unsigned int nArg, ...) -: name_(name) -, type_(type) -, arg_(nArg) -, parent_(NULL) -{ - va_list va; - - va_start(va, nArg); - for (unsigned int i = 0; i < nArg; ++i) - { - arg_[i] = va_arg(va, MathNode *); - arg_[i]->parent_ = this; - } - va_end(va); -} - -// destructor ////////////////////////////////////////////////////////////////// -MathNode::~MathNode(void) -{ - vector::iterator i; - - for (i = arg_.begin(); i != arg_.end(); ++i) - { - delete *i; - } -} - -// access ////////////////////////////////////////////////////////////////////// -const string &MathNode::getName(void) const -{ - return name_; -} - -unsigned int MathNode::getType(void) const -{ - return type_; -} - -unsigned int MathNode::getNArg(void) const -{ - return static_cast(arg_.size()); -} - -const MathNode * MathNode::getParent(void) const -{ - return parent_; -} - -unsigned int MathNode::getLevel(void) const -{ - if (getParent()) - { - return getParent()->getLevel() + 1; - } - else - { - return 0; - } -} - -void MathNode::setName(const std::string &name) -{ - name_ = name; -} - -void MathNode::pushArg(MathNode *node) -{ - arg_.push_back(node); -} - -// operators /////////////////////////////////////////////////////////////////// -const MathNode &MathNode::operator[](const unsigned int i) const -{ - return *arg_[i]; -} - -ostream &Latan::operator<<(ostream &out, const MathNode &n) -{ - unsigned int level = n.getLevel(); - - for (unsigned int i = 0; i <= level; ++i) - { - if (i == level) - { - out << "_"; - } - else if (i == level - 1) - { - out << "|"; - } - else - { - out << " "; - } - } - out << " " << n.getName() << " (type " << n.getType() << ")" << endl; - for (unsigned int i = 0; i < n.getNArg(); ++i) - { - out << n[i]; - } - - return out; -} - -/****************************************************************************** - * Instruction set * - ******************************************************************************/ -#define CODE_WIDTH 6 -#define CODE_MOD setw(CODE_WIDTH) << left - -Instruction::~Instruction(void) -{} - -ostream &Latan::operator<<(ostream& out, const Instruction& ins) -{ - ins.print(out); - - return out; -} - -Push::Push(const double val) -: type_(ArgType::Constant) -, val_(val) -, name_("") -{} - -Push::Push(const string &name) -: type_(ArgType::Variable) -, val_(0.0) -, name_(name) -{} - -void Push::operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable __dumb) -{ - if (type_ == ArgType::Constant) - { - dStack.push(val_); - } - else - { - if (keyExists(name_, vTable)) - { - dStack.push(vTable[name_]); - } - else - { - LATAN_ERROR(Range, "unknown variable '" + name_ + "'"); - } - } -} - -void Push::print(std::ostream &out) const -{ - out << CODE_MOD << "push"; - if (type_ == ArgType::Constant) - { - out << CODE_MOD << val_; - } - else - { - out << CODE_MOD << name_; - } -} - -Pop::Pop(const string &name) -: name_(name) -{} - -void Pop::operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable __dumb) -{ - if (!name_.empty()) - { - vTable[name_] = dStack.top(); - } - dStack.pop(); -} - -void Pop::print(std::ostream &out) const -{ - out << CODE_MOD << "pop" << CODE_MOD << name_; -} - -Store::Store(const string &name) -: name_(name) -{} - -void Store::operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable __dumb) -{ - if (!name_.empty()) - { - vTable[name_] = dStack.top(); - } -} - -void Store::print(std::ostream &out) const -{ - out << CODE_MOD << "store" << CODE_MOD << name_; -} - -Call::Call(const string &name) -: name_(name) -{} - -void Call::operator()(std::stack &dStack, VarTable &vTable __dumb, - FunctionTable &fTable) -{ - if (keyExists(name_, fTable)) - { - dStack.push((*fTable[name_])(dStack)); - } - else - { - LATAN_ERROR(Range, "unknown function '" + name_ + "'"); - } -} - -void Call::print(std::ostream &out) const -{ - out << CODE_MOD << "call" << CODE_MOD << name_; -} - -#define DEF_OP(name, nArg, exp, insName)\ -void name::operator()(stack &dStack, VarTable &vTable __dumb,\ - FunctionTable &fTable __dumb)\ -{\ - double x[nArg];\ - for (int i = 0; i < nArg; ++i)\ - {\ - x[nArg-1-i] = dStack.top();\ - dStack.pop();\ - }\ - dStack.push(exp);\ -}\ -void name::print(std::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") - -ostream &Latan::operator<<(ostream &out, const VirtualProgram &prog) -{ - for (unsigned int i = 0; i < prog.size(); ++i) - { - out << *(prog[i]) << endl; - } - - return out; -} - -/****************************************************************************** - * MathCompiler implementation * - ******************************************************************************/ -// MathParserState constructor ///////////////////////////////////////////////// -MathCompiler::MathParserState::MathParserState(istream *stream, string *name, - MathNode **data) -: ParserState(stream, name, data) -{ - initScanner(); -} - -// MathParserState destructor ////////////////////////////////////////////////// -MathCompiler::MathParserState::~MathParserState(void) -{ - destroyScanner(); -} - -// constructors //////////////////////////////////////////////////////////////// -MathCompiler::MathCompiler(void) -: code_(NULL) -, codeName_("") -, state_(NULL) -, root_(NULL) -, gotReturn_(false) -, out_() -, status_(Status::none) -{} - -MathCompiler::MathCompiler(const std::string &code) -: root_(NULL) -, gotReturn_(false) -, out_() -{ - init(code); -} - -// destructor ////////////////////////////////////////////////////////////////// -MathCompiler::~MathCompiler(void) -{ - reset(); -} - -// access ////////////////////////////////////////////////////////////////////// -const MathNode * MathCompiler::getAST(void) const -{ - if (root_) - { - return root_; - } - else - { - return NULL; - } -} - -// public methods ////////////////////////////////////////////////////////////// -void MathCompiler::init(const std::string &code) -{ - if (status_) - { - reset(); - } - code_ = new stringstream(code); - codeName_ = ""; - state_ = new MathParserState(code_, &codeName_, &root_); - status_ = Status::initialised; -} - -const VirtualProgram& MathCompiler::operator()(void) -{ - if (!(status_ & Status::parsed)) - { - parse(); - status_ |= Status::parsed; - status_ -= status_ & Status::compiled; - } - if (!(status_ & Status::compiled)) - { - if (root_) - { - gotReturn_ = false; - compile(*root_); - if (!gotReturn_) - { - LATAN_ERROR(Syntax, "expected 'return' in program '" + - codeName_ + "'"); - } - } - status_ |= Status::compiled; - } - - return out_; -} - -// private methods ///////////////////////////////////////////////////////////// -void MathCompiler::parse(void) -{ - _math_parse(state_); -} - -#define IFNODE(name, nArg) if ((n.getName() == (name))&&(n.getNArg() == nArg)) -#define ELIFNODE(name, nArg) else IFNODE(name, nArg) -#define ELSE else -void MathCompiler::compile(const MathNode& n) -{ - if (!gotReturn_) - { - switch (n.getType()) - { - case MathNode::Type::cst: - out_.push_back(new Push(strTo(n.getName()))); - break; - case MathNode::Type::var: - out_.push_back(new Push(n.getName())); - break; - case MathNode::Type::op: - // semicolon - if (n.getName() == ";") - { - // compile relevant statements - for (unsigned int i = 0; i < n.getNArg(); ++i) - { - bool isAssign = - ((n[i].getType() == MathNode::Type::op)&& - (n[i].getName() == "=")); - bool isSemiColumn = - ((n[i].getType() == MathNode::Type::op)&& - (n[i].getName() == ";")); - bool isKeyword = - (n[i].getType() == MathNode::Type::keyw); - - if (isAssign||isSemiColumn||isKeyword) - { - compile(n[i]); - } - } - } - // assignment - else if (n.getName() == "=") - { - // variable assignement - if (n[0].getType() == MathNode::Type::var) - { - bool hasSemicolonParent = ((n.getParent() != NULL) && - (n.getParent()->getType() - == MathNode::Type::op)&& - (n.getParent()->getName() - == ";")); - // compile the RHS - compile(n[1]); - // pop instruction if at the end of a statement - if (hasSemicolonParent) - { - out_.push_back(new Pop(n[0].getName())); - } - // store instruction else - else - { - out_.push_back(new Store(n[0].getName())); - } - } - else - { - LATAN_ERROR(Compilation, "invalid LHS for '='"); - } - } - // arithmetic operators - else - { - for (unsigned int i = 0; i < n.getNArg(); ++i) - { - compile(n[i]); - } - IFNODE("-", 1) out_.push_back(new Neg); - ELIFNODE("+", 2) out_.push_back(new Add); - ELIFNODE("-", 2) out_.push_back(new Sub); - ELIFNODE("*", 2) out_.push_back(new Mul); - ELIFNODE("/", 2) out_.push_back(new Div); - ELIFNODE("^", 2) out_.push_back(new Pow); - ELSE LATAN_ERROR(Compilation, "unknown operator '" - + n.getName() + "'"); - } - break; - case MathNode::Type::keyw: - if (n.getName() == "return") - { - compile(n[0]); - gotReturn_ = true; - } - else - { - LATAN_ERROR(Compilation, "unknown keyword '" + n.getName() - + "'"); - } - break; - case MathNode::Type::func: - for (unsigned int i = 0; i < n.getNArg(); ++i) - { - compile(n[i]); - } - out_.push_back(new Call(n.getName())); - break; - default: - LATAN_ERROR(Compilation, - "unknown node type (node named '" + n.getName() - + "')"); - break; - } - } -} - -void MathCompiler::reset(void) -{ - delete code_; - codeName_ = ""; - delete state_; - delete root_; - for (VirtualProgram::iterator i = out_.begin(); i != out_.end(); ++i) - { - delete *i; - } - out_.clear(); - status_ = 0; -} - diff --git a/latan/MathCompiler.hpp b/latan/MathCompiler.hpp deleted file mode 100644 index 3f81487..0000000 --- a/latan/MathCompiler.hpp +++ /dev/null @@ -1,241 +0,0 @@ -#ifndef LATAN_MATHCOMPILER_HPP_ -#define LATAN_MATHCOMPILER_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAXIDLENGTH 256 - -LATAN_BEGIN_CPPDECL - -/****************************************************************************** - * Parser classes * - ******************************************************************************/ -class MathNode -{ -public: - class Type - { - public: - enum - { - undef = -1, - cst = 0, - op = 1, - var = 2, - keyw = 3, - func = 4 - }; - }; -public: - // constructor - MathNode(const std::string &name, const unsigned int type); - MathNode(const std::string &name, const unsigned int type, - const unsigned int nArg, ...); - // destructor - virtual ~MathNode(); - // access - const std::string& getName(void) const; - unsigned int getType(void) const; - unsigned int getNArg(void) const; - const MathNode * getParent(void) const; - unsigned int getLevel(void) const; - void setName(const std::string &name); - void pushArg(MathNode *node); - // operator - const MathNode &operator[](const unsigned int i) const; -private: - // IO - std::ostream &print(std::ostream &out) const; -private: - std::string name_; - unsigned int type_; - std::vector arg_; - const MathNode * parent_; -}; - -std::ostream &operator<<(std::ostream &out, const MathNode &n); - -/****************************************************************************** - * Virtual machine code classes * - ******************************************************************************/ -typedef std::map VarTable; -typedef std::map FunctionTable; - -// Abstract base -class Instruction -{ -public: - virtual ~Instruction(); - // instruction execution - virtual void operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable) = 0; - friend std::ostream& operator<<(std::ostream &out, const Instruction &ins); -private: - virtual void print(std::ostream &out) const = 0; -}; - -// Push -class Push: public Instruction -{ -private: - class ArgType - { - public: - enum - { - Constant = 0, - Variable = 1 - }; - }; -public: - //constructors - explicit Push(const double val); - explicit Push(const std::string &name); - // instruction execution - virtual void operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable); -private: - virtual void print(std::ostream& out) const; -private: - unsigned int type_; - double val_; - std::string name_; -}; - -// Pop -class Pop: public Instruction -{ -public: - //constructor - explicit Pop(const std::string &name); - // instruction execution - virtual void operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable); -private: - virtual void print(std::ostream& out) const; -private: - std::string name_; -}; - -// Store -class Store: public Instruction -{ -public: - //constructor - explicit Store(const std::string &name); - // instruction execution - virtual void operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable); -private: - virtual void print(std::ostream& out) const; -private: - std::string name_; -}; - -// Call function -class Call: public Instruction -{ -public: - //constructor - explicit Call(const std::string &name); - // instruction execution - virtual void operator()(std::stack &dStack, VarTable &vTable, - FunctionTable &fTable); -private: - virtual void print(std::ostream& out) const; -private: - std::string name_; -}; - -// Floating point operations -#define DECL_OP(name)\ -class name: public Instruction\ -{\ -public:\ -virtual void operator()(std::stack &dStack, VarTable &vTable,\ - FunctionTable &fTable);\ -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); - -// Virtual program type -typedef std::vector VirtualProgram; - -std::ostream &operator<<(std::ostream &out, const VirtualProgram &program); - -/****************************************************************************** - * Compiler class * - ******************************************************************************/ -class MathCompiler -{ -public: - // parser state - class MathParserState: public ParserState - { - public: - // constructor - explicit MathParserState(std::istream *stream, std::string *name, - MathNode **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 - MathCompiler(void); - MathCompiler(const std::string &code); - // destructor - ~MathCompiler(void); - // access - const MathNode * getAST(void) const; - // initialization - void init(const std::string &code); - // compilation - const VirtualProgram &operator()(void); -private: - void parse(void); - void compile(const MathNode &node); - void reset(void); -private: - std::istream *code_; - std::string codeName_; - MathParserState *state_; - MathNode *root_; - bool gotReturn_; - VirtualProgram out_; - unsigned int status_; -}; - -LATAN_END_CPPDECL - -#endif diff --git a/latan/MathInterpreter.cpp b/latan/MathInterpreter.cpp index f7c85f4..32526ac 100644 --- a/latan/MathInterpreter.cpp +++ b/latan/MathInterpreter.cpp @@ -26,26 +26,26 @@ using namespace Latan; /****************************************************************************** * MathNode implementation * ******************************************************************************/ -// constructor ///////////////////////////////////////////////////////////////// -MathNode::MathNode(const string &name, const unsigned int type) +// constructors //////////////////////////////////////////////////////////////// +MathNode::MathNode(const string &name, const Type type) : name_(name) , type_(type) -, parent_(NULL) +, parent_(nullptr) {} -MathNode::MathNode(const std::string &name, const unsigned int type,\ +MathNode::MathNode(const std::string &name, const Type type,\ const unsigned int nArg, ...) : name_(name) , type_(type) , arg_(nArg) -, parent_(NULL) +, parent_(nullptr) { va_list va; va_start(va, nArg); for (unsigned int i = 0; i < nArg; ++i) { - arg_[i] = va_arg(va, MathNode *); + arg_[i].reset(va_arg(va, MathNode *)); arg_[i]->parent_ = this; } va_end(va); @@ -53,14 +53,7 @@ MathNode::MathNode(const std::string &name, const unsigned int type,\ // destructor ////////////////////////////////////////////////////////////////// MathNode::~MathNode(void) -{ - vector::iterator i; - - for (i = arg_.begin(); i != arg_.end(); ++i) - { - delete *i; - } -} +{} // access ////////////////////////////////////////////////////////////////////// const string &MathNode::getName(void) const @@ -68,7 +61,7 @@ const string &MathNode::getName(void) const return name_; } -unsigned int MathNode::getType(void) const +MathNode::Type MathNode::getType(void) const { return type_; } @@ -102,7 +95,7 @@ void MathNode::setName(const std::string &name) void MathNode::pushArg(MathNode *node) { - arg_.push_back(node); + arg_.push_back(unique_ptr(node)); } // operators /////////////////////////////////////////////////////////////////// @@ -130,7 +123,8 @@ ostream &Latan::operator<<(ostream &out, const MathNode &n) out << " "; } } - out << " " << n.getName() << " (type " << n.getType() << ")" << endl; + out << " " << n.getName() << " (type " << static_cast(n.getType()) + << ")" << endl; for (unsigned int i = 0; i < n.getNArg(); ++i) { out << n[i]; @@ -175,11 +169,11 @@ void Push::operator()(RunContext &context) const } else { - if (keyExists(name_, context.vTable)) + try { - context.dStack.push(context.vTable[name_]); + context.dStack.push(context.vTable.at(name_)); } - else + catch (out_of_range) { LATAN_ERROR(Range, "unknown variable '" + name_ + "'"); } @@ -187,7 +181,7 @@ void Push::operator()(RunContext &context) const context.insIndex++; } -void Push::print(std::ostream &out) const +void Push::print(ostream &out) const { out << CODE_MOD << "push"; if (type_ == ArgType::Constant) @@ -214,7 +208,7 @@ void Pop::operator()(RunContext &context) const context.insIndex++; } -void Pop::print(std::ostream &out) const +void Pop::print(ostream &out) const { out << CODE_MOD << "pop" << CODE_MOD << name_; } @@ -232,7 +226,7 @@ void Store::operator()(RunContext &context) const context.insIndex++; } -void Store::print(std::ostream &out) const +void Store::print(ostream &out) const { out << CODE_MOD << "store" << CODE_MOD << name_; } @@ -243,18 +237,18 @@ Call::Call(const string &name) void Call::operator()(RunContext &context) const { - if (keyExists(name_, context.fTable)) + try { - context.dStack.push((*context.fTable[name_])(context.dStack)); + context.dStack.push((*context.fTable.at(name_))(context.dStack)); } - else + catch (out_of_range) { LATAN_ERROR(Range, "unknown function '" + name_ + "'"); } context.insIndex++; } -void Call::print(std::ostream &out) const +void Call::print(ostream &out) const { out << CODE_MOD << "call" << CODE_MOD << name_; } @@ -271,7 +265,7 @@ void name::operator()(RunContext &context) const\ context.dStack.push(exp);\ context.insIndex++;\ }\ -void name::print(std::ostream &out) const\ +void name::print(ostream &out) const\ {\ out << CODE_MOD << insName;\ } @@ -287,9 +281,9 @@ DEF_OP(Pow, 2, pow(x[0],x[1]), "pow") * MathInterpreter implementation * ******************************************************************************/ // MathParserState constructor ///////////////////////////////////////////////// -MathInterpreter::MathParserState::MathParserState(istream *stream, string *name, - MathNode **data) -: ParserState(stream, name, data) +MathInterpreter::MathParserState::MathParserState +(istream *stream, string *name, std::unique_ptr *data) +: ParserState>(stream, name, data) { initScanner(); } @@ -302,19 +296,19 @@ MathInterpreter::MathParserState::~MathParserState(void) // constructors //////////////////////////////////////////////////////////////// MathInterpreter::MathInterpreter(void) -: code_(NULL) +: code_(nullptr) , codeName_("") -, state_(NULL) -, root_(NULL) +, state_(nullptr) +, root_(nullptr) , gotReturn_(false) , status_(Status::none) {} MathInterpreter::MathInterpreter(const std::string &code) -: code_(NULL) +: code_(nullptr) , codeName_("") -, state_(NULL) -, root_(NULL) +, state_(nullptr) +, root_(nullptr) , gotReturn_(false) , status_(Status::none) { @@ -323,31 +317,22 @@ MathInterpreter::MathInterpreter(const std::string &code) // destructor ////////////////////////////////////////////////////////////////// MathInterpreter::~MathInterpreter(void) -{ - reset(); -} +{} // access ////////////////////////////////////////////////////////////////////// const Instruction * MathInterpreter::operator[](const unsigned int i) const { - return program_[i]; + return program_[i].get(); } const MathNode * MathInterpreter::getAST(void) const { - if (root_) - { - return root_; - } - else - { - return NULL; - } + return root_.get(); } void MathInterpreter::push(const Instruction *i) { - program_.push_back(i); + program_.push_back(unique_ptr(i)); } // initialization ////////////////////////////////////////////////////////////// @@ -357,24 +342,18 @@ void MathInterpreter::setCode(const std::string &code) { reset(); } - code_ = new stringstream(code); + code_.reset(new stringstream(code)); codeName_ = ""; - state_ = new MathParserState(code_, &codeName_, &root_); + state_.reset(new MathParserState(code_.get(), &codeName_, &root_)); status_ = Status::initialised; } void MathInterpreter::reset(void) { - InstructionContainer::iterator i; - - delete code_; + code_.reset(nullptr); codeName_ = ""; - delete state_; - delete root_; - for (i = program_.begin(); i != program_.end(); ++i) - { - delete *i; - } + state_.reset(nullptr); + root_.reset(nullptr); program_.clear(); status_ = 0; } @@ -382,11 +361,11 @@ void MathInterpreter::reset(void) // parser ////////////////////////////////////////////////////////////////////// // Bison/Flex parser declaration -int _math_parse(MathInterpreter::MathParserState* state); +int _math_parse(MathInterpreter::MathParserState *state); void MathInterpreter::parse(void) { - _math_parse(state_); + _math_parse(state_.get()); } // interpreter ///////////////////////////////////////////////////////////////// @@ -414,6 +393,9 @@ void MathInterpreter::compile(void) #define ELIFNODE(name, nArg) else IFNODE(name, nArg) #define ELSE else +#define PUSH_INS(type, ...) \ +program_.push_back(unique_ptr(new (type)(__VA_ARGS__))) + void MathInterpreter::compileNode(const MathNode& n) { if (!gotReturn_) @@ -421,10 +403,10 @@ void MathInterpreter::compileNode(const MathNode& n) switch (n.getType()) { case MathNode::Type::cst: - program_.push_back(new Push(strTo(n.getName()))); + PUSH_INS(Push, strTo(n.getName())); break; case MathNode::Type::var: - program_.push_back(new Push(n.getName())); + PUSH_INS(Push, n.getName()); break; case MathNode::Type::op: // semicolon @@ -464,12 +446,12 @@ void MathInterpreter::compileNode(const MathNode& n) // pop instruction if at the end of a statement if (hasSemicolonParent) { - program_.push_back(new Pop(n[0].getName())); + program_.push_back(unique_ptr(new Pop(n[0].getName()))); } // store instruction else else { - program_.push_back(new Store(n[0].getName())); + PUSH_INS(Store, n[0].getName()); } } else @@ -484,12 +466,12 @@ void MathInterpreter::compileNode(const MathNode& n) { compileNode(n[i]); } - IFNODE("-", 1) program_.push_back(new Neg); - ELIFNODE("+", 2) program_.push_back(new Add); - ELIFNODE("-", 2) program_.push_back(new Sub); - ELIFNODE("*", 2) program_.push_back(new Mul); - ELIFNODE("/", 2) program_.push_back(new Div); - ELIFNODE("^", 2) program_.push_back(new Pow); + IFNODE("-", 1) PUSH_INS(Neg,); + ELIFNODE("+", 2) PUSH_INS(Add,); + ELIFNODE("-", 2) PUSH_INS(Sub,); + ELIFNODE("*", 2) PUSH_INS(Mul,); + ELIFNODE("/", 2) PUSH_INS(Div,); + ELIFNODE("^", 2) PUSH_INS(Pow,); ELSE LATAN_ERROR(Compilation, "unknown operator '" + n.getName() + "'"); } @@ -511,7 +493,7 @@ void MathInterpreter::compileNode(const MathNode& n) { compileNode(n[i]); } - program_.push_back(new Call(n.getName())); + PUSH_INS(Call, n.getName()); break; default: LATAN_ERROR(Compilation, diff --git a/latan/MathInterpreter.hpp b/latan/MathInterpreter.hpp index 8ba26b3..39c67d9 100644 --- a/latan/MathInterpreter.hpp +++ b/latan/MathInterpreter.hpp @@ -39,29 +39,25 @@ BEGIN_NAMESPACE class MathNode { public: - class Type + enum class Type { - public: - enum - { - undef = -1, - cst = 0, - op = 1, - var = 2, - keyw = 3, - func = 4 - }; + undef = -1, + cst = 0, + op = 1, + var = 2, + keyw = 3, + func = 4 }; public: - // constructor - MathNode(const std::string &name, const unsigned int type); - MathNode(const std::string &name, const unsigned int type, + // constructors + MathNode(const std::string &name, const Type type); + MathNode(const std::string &name, const Type type, const unsigned int nArg, ...); // destructor virtual ~MathNode(); // access const std::string& getName(void) const; - unsigned int getType(void) const; + Type getType(void) const; unsigned int getNArg(void) const; const MathNode * getParent(void) const; unsigned int getLevel(void) const; @@ -70,10 +66,10 @@ public: // operator const MathNode &operator[](const unsigned int i) const; private: - std::string name_; - unsigned int type_; - std::vector arg_; - const MathNode * parent_; + std::string name_; + Type type_; + std::vector> arg_; + const MathNode * parent_; }; std::ostream &operator<<(std::ostream &out, const MathNode &n); @@ -99,23 +95,21 @@ public: virtual ~Instruction(); // instruction execution virtual void operator()(RunContext &context) const = 0; - friend std::ostream& operator<<(std::ostream &out, const Instruction &ins); + 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); + // Push class Push: public Instruction { private: - class ArgType + enum class ArgType { - public: - enum - { - Constant = 0, - Variable = 1 - }; + Constant = 0, + Variable = 1 }; public: //constructors @@ -126,7 +120,7 @@ public: private: virtual void print(std::ostream& out) const; private: - unsigned int type_; + ArgType type_; double val_; std::string name_; }; @@ -198,12 +192,12 @@ class MathInterpreter public: // parser state - class MathParserState: public ParserState + class MathParserState: public ParserState> { public: // constructor explicit MathParserState(std::istream *stream, std::string *name, - MathNode **data); + std::unique_ptr *data); // destructor virtual ~MathParserState(void); private: @@ -225,7 +219,7 @@ private: }; }; // instruction container - typedef std::vector InstructionContainer; + typedef std::vector> Program; public: // constructors MathInterpreter(void); @@ -242,8 +236,8 @@ public: // execution void operator()(RunContext &context); // IO - friend std::ostream &operator<<(std::ostream &out, - const MathInterpreter &program); + friend std::ostream & operator<<(std::ostream &out, + const MathInterpreter &program); private: // initialization void reset(void); @@ -256,15 +250,17 @@ private: // execution void execute(RunContext &context) const; private: - std::istream *code_; - std::string codeName_; - MathParserState *state_; - MathNode *root_; - bool gotReturn_; - InstructionContainer program_; - unsigned int status_; + std::unique_ptr code_; + std::string codeName_; + std::unique_ptr state_; + std::unique_ptr root_; + bool gotReturn_; + Program program_; + unsigned int status_; }; +std::ostream & operator<<(std::ostream &out, const MathInterpreter &program); + END_NAMESPACE #endif // Latan_MathInterpreter_hpp_ diff --git a/latan/MathParser.ypp b/latan/MathParser.ypp index 5953a88..c1b834c 100644 --- a/latan/MathParser.ypp +++ b/latan/MathParser.ypp @@ -39,9 +39,9 @@ %union { - double val_double; - char val_char; - char val_str[MAXIDLENGTH]; + double val_double; + char val_char; + char val_str[MAXIDLENGTH]; Latan::MathNode *val_node; } @@ -78,7 +78,7 @@ program: /* empty string */ - | stmt_list {*(state->data) = $1;} + | stmt_list {(*(state->data)).reset($1);} ; stmt: diff --git a/latan/ParserState.hpp b/latan/ParserState.hpp index f5b21d9..6cf8875 100644 --- a/latan/ParserState.hpp +++ b/latan/ParserState.hpp @@ -40,10 +40,10 @@ private: virtual void initScanner(void) = 0; virtual void destroyScanner(void) = 0; public: - DataObj *data; - void *scanner; - std::istream *stream; - std::string *streamName; + DataObj *data; + void *scanner; + std::istream *stream; + std::string *streamName; }; @@ -51,7 +51,7 @@ template ParserState::ParserState(std::istream *streamPt, std::string *namePt, DataObj *dataPt) : data(dataPt) -, scanner(NULL) +, scanner(nullptr) , stream(streamPt) , streamName(namePt) {} diff --git a/latan/Plot.hpp b/latan/Plot.hpp index 5d604b1..4cf84af 100644 --- a/latan/Plot.hpp +++ b/latan/Plot.hpp @@ -115,6 +115,8 @@ private: std::vector plotCommand_; }; +std::ostream & operator<<(std::ostream &out, const Plot &plot); + END_NAMESPACE #endif // Latan_Plot_hpp_ diff --git a/latan/RandGen.cpp b/latan/RandGen.cpp index 344ac65..61edaf4 100644 --- a/latan/RandGen.cpp +++ b/latan/RandGen.cpp @@ -37,7 +37,7 @@ RandGen::State::State(void) RandGen::State::~State(void) {} -unsigned int RandGen::State::getType(void) const +IoObject::IoType RandGen::State::getType(void) const { return IoType::rgState; } diff --git a/latan/RandGen.hpp b/latan/RandGen.hpp index dad08ac..3f10964 100644 --- a/latan/RandGen.hpp +++ b/latan/RandGen.hpp @@ -36,13 +36,15 @@ class RandGen public: class State: public Eigen::Array, public IoObject { + private: + typedef Eigen::Array Base; public: // constructor State(void); // destructor ~State(void); // IO type - unsigned int getType(void) const; + IoType getType(void) const; }; private: // Martin Luescher's ranlxd generator interface diff --git a/latan/Sample.cpp b/latan/Sample.cpp index 2d1c9dd..b21dad2 100644 --- a/latan/Sample.cpp +++ b/latan/Sample.cpp @@ -24,7 +24,7 @@ using namespace Latan; using namespace std; template <> -unsigned int Sample::getType(void) const +IoObject::IoType Sample::getType(void) const { return IoType::dMatSample; } diff --git a/latan/Sample.hpp b/latan/Sample.hpp index 228a1ce..7453da8 100644 --- a/latan/Sample.hpp +++ b/latan/Sample.hpp @@ -48,14 +48,14 @@ public: // operators T& operator[](const int s); // IO type - virtual unsigned int getType(void) const; + virtual IoType getType(void) const; private: // index of the first element to take into account for statistics virtual unsigned int getOffset(void) const; }; template <> -unsigned int Sample::getType(void) const; +IoObject::IoType Sample::getType(void) const; // specialization aliases typedef Sample DMatSample; @@ -101,7 +101,7 @@ T& Sample::operator[](const int s) // IO type ///////////////////////////////////////////////////////////////////// template -unsigned int Sample::getType(void) const +IoObject::IoType Sample::getType(void) const { return IoType::noType; } diff --git a/latan/includes.hpp b/latan/includes.hpp index 6e5d2ba..61f1c6d 100644 --- a/latan/includes.hpp +++ b/latan/includes.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/utils/Makefile.am b/utils/Makefile.am new file mode 100644 index 0000000..a367b13 --- /dev/null +++ b/utils/Makefile.am @@ -0,0 +1,24 @@ +if CC_GNU + COM_CFLAGS = -Wall -W -pedantic +else +if CC_INTEL + COM_CFLAGS = -Wall +endif +endif + +if CXX_GNU + COM_CXXFLAGS = -Wall -W -pedantic +else +if CXX_INTEL + COM_CXXFLAGS = -Wall +endif +endif + +noinst_PROGRAMS = \ + latan_sample_read + +latan_sample_read_SOURCES = sample_read.cpp +latan_sample_read_CFLAGS = -g -O2 +latan_sample_read_LDFLAGS = -L../latan/.libs -llatan + +ACLOCAL_AMFLAGS = -I .buildutils/m4 diff --git a/utils/latan b/utils/latan new file mode 120000 index 0000000..03578ae --- /dev/null +++ b/utils/latan @@ -0,0 +1 @@ +../latan \ No newline at end of file diff --git a/utils/sample_read.cpp b/utils/sample_read.cpp new file mode 100644 index 0000000..e253ac2 --- /dev/null +++ b/utils/sample_read.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +using namespace std; +using namespace Latan; + +int main(void) +{ + Dataset dataset; + DMatSample s, r; + RandGen g; + + dataset.load("man", "HVP_2_2_000_00_0_0"); + s = dataset.bootstrapMean(100, g); + + cout << "central value:\n" << s[central] << endl; + cout << "standard deviation:\n" << s.variance().cwiseSqrt() << endl; + + return EXIT_SUCCESS; +}