diff --git a/latan/Io.cpp b/latan/Io.cpp index 39e7fce..14036b6 100644 --- a/latan/Io.cpp +++ b/latan/Io.cpp @@ -46,7 +46,7 @@ File::~File(void) } // access ////////////////////////////////////////////////////////////////////// -string File::getName(void) const +const string & File::getName(void) const { return name_; } @@ -116,10 +116,24 @@ void AsciiFile::save(const DMat &m, const std::string &name) isParsed_ = false; fileStream_ << "#L latan_begin mat " << name << endl; fileStream_ << m.cols() << endl; - fileStream_ << m << endl; + fileStream_ << scientific << m << defaultfloat << endl; fileStream_ << "#L latan_end mat " << endl; } +void AsciiFile::save(const DMatSample &s, const std::string &name) +{ + checkWritability(); + isParsed_ = false; + fileStream_ << "#L latan_begin rs_sample " << name << endl; + fileStream_ << s.size() << endl; + save(s[central], name + "_C"); + for (int i = 0; i < static_cast(s.size()); ++i) + { + save(s[i], name + "_S_" + strFrom(i)); + } + fileStream_ << "#L latan_end rs_sample " << endl; +} + void AsciiFile::save(const RandGen::State &state, const std::string &name) { checkWritability(); @@ -186,14 +200,23 @@ void AsciiFile::open(const string &name, const unsigned int mode) } } -void AsciiFile::load(const string &name __dumb) +std::string AsciiFile::load(const string &name) { if ((mode_ & Mode::read)&&(isOpen())) { if (!isParsed_) { + state_->isFirst = true; parse(); } + if (name.empty()) + { + return state_->first; + } + else + { + return name; + } } else { @@ -210,7 +233,7 @@ void AsciiFile::load(const string &name __dumb) // parser ////////////////////////////////////////////////////////////////////// -// Bison/Flex parser declaration +//// Bison/Flex parser declaration int _ioAscii_parse(AsciiFile::AsciiParserState *state); void AsciiFile::parse() diff --git a/latan/Io.hpp b/latan/Io.hpp index a6c8077..5ffd986 100644 --- a/latan/Io.hpp +++ b/latan/Io.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include @@ -61,11 +61,12 @@ public: // destructor virtual ~File(void); // access - std::string getName(void) const; - unsigned int getMode(void) const; + const std::string & getName(void) const; + unsigned int getMode(void) const; template - const IoT & read(const std::string &name); + const IoT & read(const std::string &name = ""); virtual void save(const DMat &m, const std::string &name) = 0; + virtual void save(const DMatSample &state, const std::string &name) = 0; virtual void save(const RandGen::State &state, const std::string &name) = 0; // tests virtual bool isOpen(void) const = 0; @@ -73,14 +74,19 @@ public: virtual void close(void) = 0; virtual void open(const std::string &name, const unsigned int mode) = 0; protected: + // access + void setName(const std::string &name); + void setMode(const unsigned int mode); // data access - void deleteData(void); - template - const IoT& getData(const std::string &name) const; - // IO - virtual void load(const std::string &name) = 0; + void deleteData(void); // error checking void checkWritability(void); +private: + // data access + template + const IoT& getData(const std::string &name = "") const; + // IO + virtual std::string load(const std::string &name = "") = 0; protected: std::string name_; unsigned int mode_; @@ -91,9 +97,11 @@ protected: template const IoT& File::read(const std::string &name) { - load(name); + std::string dataName; - return getData(name); + dataName = load(name); + + return getData(dataName); } template @@ -105,7 +113,8 @@ const IoT& File::getData(const std::string &name) const } catch(std::out_of_range) { - LATAN_ERROR(Definition, "no data with name '" + name + "'"); + LATAN_ERROR(Definition, "no data with name '" + name + "' in file " + + name_); } } @@ -123,12 +132,15 @@ public: IoDataTable *data); // destructor virtual ~AsciiParserState(void); + // first element reference + bool isFirst; + std::string first; // parsing buffers - DMat dMatBuf; RandGen::State stateBuf; - std::stack dMatStack; - std::stack doubleStack; - std::stack intStack; + DMatSample dMatSampleBuf; + std::queue dMatQueue; + std::queue doubleQueue; + std::queue intQueue; private: // allocation/deallocation functions defined in IoAsciiLexer.lpp virtual void initScanner(void); @@ -142,6 +154,7 @@ public: virtual ~AsciiFile(void); // access virtual void save(const DMat &m, const std::string &name); + virtual void save(const DMatSample &s, const std::string &name); virtual void save(const RandGen::State &state, const std::string &name); // tests virtual bool isOpen(void) const; @@ -150,7 +163,7 @@ public: virtual void open(const std::string &name, const unsigned int mode); private: // IO - virtual void load(const std::string &name); + virtual std::string load(const std::string &name = ""); // parser void parse(void); private: diff --git a/latan/IoAsciiLexer.lpp b/latan/IoAsciiLexer.lpp index 2437782..ef54ddb 100644 --- a/latan/IoAsciiLexer.lpp +++ b/latan/IoAsciiLexer.lpp @@ -69,12 +69,13 @@ BLANK [ \t] %% {LMARK} {BEGIN(MARK);} -{INT} {yylval->val_int = strTo(yytext); RETTOK(INT);} +{INT} {yylval->val_int = strTo(yytext); RETTOK(INT);} {FLOAT} {yylval->val_double = strTo(yytext); RETTOK(FLOAT);} ({ALPHA}|{DIGIT})+ {strcpy(yylval->val_str,yytext); RETTOK(ID);} latan_begin {BEGIN(TYPE); RETTOK(OPEN);} latan_end {BEGIN(TYPE); RETTOK(CLOSE);} mat {BEGIN(INITIAL); RETTOK(MAT);} +rs_sample {BEGIN(INITIAL); RETTOK(SAMPLE);} rg_state {BEGIN(INITIAL); RETTOK(RG_STATE);} <*>\n {yylloc->last_column = 0;} <*>[ \t] diff --git a/latan/IoAsciiParser.ypp b/latan/IoAsciiParser.ypp index 02044af..847a28f 100644 --- a/latan/IoAsciiParser.ypp +++ b/latan/IoAsciiParser.ypp @@ -32,7 +32,12 @@ using namespace std; using namespace Latan; - #define STORE(ref) (*state->data)[(ref).first] = std::move((ref).second) + #define TEST_FIRST(name) \ + if (state->isFirst)\ + {\ + state->first = (name);\ + state->isFirst = false;\ + } %} %pure-parser @@ -56,9 +61,9 @@ %token FLOAT %token INT %token ID -%token OPEN CLOSE MAT RG_STATE +%token OPEN CLOSE MAT SAMPLE RG_STATE -%type mat rg_state +%type mat sample rg_state %{ int _ioAscii_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner); @@ -85,69 +90,99 @@ datas: data: mat - {(*state->data)[$1].reset(new DMat(state->dMatBuf));} + { + TEST_FIRST($1); + (*state->data)[$1].reset(new DMat(state->dMatQueue.front())); + state->dMatQueue.pop(); + } + | sample + { + TEST_FIRST($1); + (*state->data)[$1].reset(new DMatSample(state->dMatSampleBuf)); + } | rg_state - {(*state->data)[$1].reset(new RandGen::State(state->stateBuf));} + { + TEST_FIRST($1); + (*state->data)[$1].reset(new RandGen::State(state->stateBuf)); + } ; mat: OPEN MAT ID INT floats CLOSE MAT { - const int nRow = state->doubleStack.size()/$INT, nCol = $INT; - int r, i, j; + const unsigned int nRow = state->doubleQueue.size()/$INT, nCol = $INT; + int i, j, r = 0; - r = 0; - state->dMatBuf.resize(nRow, nCol); - while (!state->doubleStack.empty()) + if (state->doubleQueue.size() != nRow*nCol) + { + LATAN_ERROR(Size, "matrix '" + *state->streamName + ":" + $ID + + "' has a wrong size"); + } + + state->dMatQueue.push(DMat(nRow, nCol)); + while (!state->doubleQueue.empty()) { j = r % nCol; i = (r - j)/nCol; - state->dMatBuf(i, j) = state->doubleStack.top(); - state->doubleStack.pop(); - ++r; - } - if (r != nRow*nCol) - { - LATAN_ERROR(Range, "matrix '" + *state->streamName + ":" + $ID + - "' has a wrong size"); + state->dMatQueue.back()(i, j) = state->doubleQueue.front(); + state->doubleQueue.pop(); + r++; } strcpy($$, $ID); } ; +sample: + OPEN SAMPLE ID INT mats CLOSE SAMPLE + { + const unsigned int nSample = $INT + 1; + + if (state->dMatQueue.size() != nSample) + { + LATAN_ERROR(Size, "sample '" + *state->streamName + ":" + $ID + + "' has a wrong size"); + } + state->dMatSampleBuf.resize(nSample); + state->dMatSampleBuf[central] = state->dMatQueue.front(); + state->dMatQueue.pop(); + for (int i = 0; i < $INT; ++i) + { + state->dMatSampleBuf[i] = state->dMatQueue.front(); + state->dMatQueue.pop(); + } + strcpy($$, $ID); + } + rg_state: OPEN RG_STATE ID ints CLOSE RG_STATE { - for (int i = 0; i < RLXG_STATE_SIZE; ++i) + if (state->intQueue.size() != RLXG_STATE_SIZE) { - if (!state->intStack.empty()) - { - state->stateBuf[i] = state->intStack.top(); - state->intStack.pop(); - } - else - { - LATAN_ERROR(Range, "random generator state '" + - *state->streamName + ":" + $ID + "' is too short"); - } + LATAN_ERROR(Size, "random generator state '" + *state->streamName + + ":" + $ID + "' has a wrong size"); } - if (!state->intStack.empty()) + for (unsigned int i = 0; i < RLXG_STATE_SIZE; ++i) { - LATAN_ERROR(Range, "random generator state '" + - *state->streamName + ":" + $ID + "' is too long"); + state->stateBuf[i] = state->intQueue.front(); + state->intQueue.pop(); } strcpy($$, $ID); } ; +mats: + mats mat + | mat + ; + floats: - 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));} + floats FLOAT {state->doubleQueue.push($FLOAT);} + | floats INT {state->doubleQueue.push(static_cast($INT));} + | FLOAT {state->doubleQueue.push($FLOAT);} + | INT {state->doubleQueue.push(static_cast($INT));} ; ints: - INT ints {state->intStack.push($1);} - | INT {state->intStack.push($1);} + ints INT {state->intQueue.push($INT);} + | INT {state->intQueue.push($INT);} ;