1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2024-11-10 00:45:36 +00:00

simplification of IO interface

This commit is contained in:
Antonin Portelli 2014-02-20 23:52:45 +00:00
parent 9ce04cd7d6
commit 157fda5445
15 changed files with 870 additions and 67 deletions

View File

@ -1,5 +1,5 @@
#include <iostream> #include <iostream>
#include <latan/Io.hpp> #include <latan/AsciiFile.hpp>
#include <latan/Mat.hpp> #include <latan/Mat.hpp>
#include <latan/Math.hpp> #include <latan/Math.hpp>

View File

@ -1,5 +1,5 @@
#include <iostream> #include <iostream>
#include <latan/Io.hpp> #include <latan/AsciiFile.hpp>
#include <latan/RandGen.hpp> #include <latan/RandGen.hpp>
using namespace std; using namespace std;
@ -11,7 +11,7 @@ const string stateFileName = "exRand.seed";
int main(void) int main(void)
{ {
RandGen::State state; RandGenState state;
RandGen gen[2]; RandGen gen[2];
AsciiFile stateFile(stateFileName, File::Mode::write|File::Mode::read); AsciiFile stateFile(stateFileName, File::Mode::write|File::Mode::read);
@ -31,7 +31,7 @@ int main(void)
} }
cout << "-- setting up another generator from '" << stateFileName << "'..." cout << "-- setting up another generator from '" << stateFileName << "'..."
<< endl; << endl;
gen[1].setState(stateFile.read<RandGen::State>("exRand")); gen[1].setState(stateFile.read<RandGenState>("exRand"));
cout << "-- generating a " << seqLength << " steps random sequence..." cout << "-- generating a " << seqLength << " steps random sequence..."
<< endl; << endl;
for (int i = 0; i < seqLength; ++i) for (int i = 0; i < seqLength; ++i)

193
latan/AsciiFile.cpp Normal file
View File

@ -0,0 +1,193 @@
/*
* AsciiFile.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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 <latan/AsciiFile.hpp>
#include <latan/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* AsciiFile implementation *
******************************************************************************/
// AsciiParserState constructor ////////////////////////////////////////////////
AsciiFile::AsciiParserState::AsciiParserState(istream *stream, string *name,
IoDataTable *data)
: ParserState<IoDataTable>(stream, name, data)
{
initScanner();
}
// AsciiParserState destructor /////////////////////////////////////////////////
AsciiFile::AsciiParserState::~AsciiParserState(void)
{
destroyScanner();
}
// constructor /////////////////////////////////////////////////////////////////
AsciiFile::AsciiFile(void)
: File(), fileStream_()
, isParsed_(false)
, state_(nullptr)
{}
AsciiFile::AsciiFile(const string &name, const unsigned int mode)
{
open(name, mode);
}
// destructor //////////////////////////////////////////////////////////////////
AsciiFile::~AsciiFile(void)
{
close();
}
// access //////////////////////////////////////////////////////////////////////
void AsciiFile::save(const DMat &m, const std::string &name)
{
checkWritability();
isParsed_ = false;
fileStream_ << "#L latan_begin mat " << name << endl;
fileStream_ << m.cols() << endl;
fileStream_ << scientific << m << 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<int>(s.size()); ++i)
{
save(s[i], name + "_S_" + strFrom(i));
}
fileStream_ << "#L latan_end rs_sample " << endl;
}
void AsciiFile::save(const RandGenState &state, const std::string &name)
{
checkWritability();
isParsed_ = false;
fileStream_ << "#L latan_begin rg_state " << name << endl;
fileStream_ << state << endl;
fileStream_ << "#L latan_end rg_state " << endl;
}
// tests ///////////////////////////////////////////////////////////////////////
bool AsciiFile::isOpen() const
{
return fileStream_.is_open();
}
// IO //////////////////////////////////////////////////////////////////////////
void AsciiFile::close(void)
{
state_.reset();
if (isOpen())
{
fileStream_.close();
}
name_ = "";
mode_ = Mode::null;
isParsed_ = false;
deleteData();
}
void AsciiFile::open(const string &name, const unsigned int mode)
{
if (isOpen())
{
LATAN_ERROR(Io, "file already opened with name '" + name_ + "'");
}
else
{
ios_base::openmode stdMode = static_cast<ios_base::openmode>(0);
if (mode & Mode::write)
{
stdMode |= ios::out|ios::trunc;
}
if (mode & Mode::read)
{
stdMode |= ios::in;
}
if (mode & Mode::append)
{
stdMode |= ios::out|ios::app;
}
name_ = name;
mode_ = mode;
isParsed_ = false;
fileStream_.open(name_.c_str(), stdMode);
if (mode_ & Mode::read)
{
state_.reset(new AsciiParserState(&fileStream_, &name_, &data_));
}
else
{
state_.reset();
}
}
}
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
{
if (isOpen())
{
LATAN_ERROR(Io, "file '" + name_ + "' is not opened in read mode");
}
else
{
LATAN_ERROR(Io, "file not opened");
}
}
}
// parser //////////////////////////////////////////////////////////////////////
//// Bison/Flex parser declaration
int _Ascii_parse(AsciiFile::AsciiParserState *state);
void AsciiFile::parse()
{
fileStream_.seekg(0);
_Ascii_parse(state_.get());
isParsed_ = true;
}

87
latan/AsciiFile.hpp Normal file
View File

@ -0,0 +1,87 @@
/*
* AsciiFile.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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_AsciiFile_hpp_
#define Latan_AsciiFile_hpp_
#include <latan/Global.hpp>
#include <latan/File.hpp>
#include <latan/Mat.hpp>
#include <latan/RandGen.hpp>
#include <latan/Sample.hpp>
BEGIN_NAMESPACE
/******************************************************************************
* ASCII datafile class *
******************************************************************************/
class AsciiFile: public File
{
public:
class AsciiParserState: public ParserState<IoDataTable>
{
public:
// constructor
explicit AsciiParserState(std::istream *stream, std::string *name,
IoDataTable *data);
// destructor
virtual ~AsciiParserState(void);
// first element reference
bool isFirst;
std::string first;
// parsing buffers
RandGenState stateBuf;
DMatSample dMatSampleBuf;
std::queue<DMat> dMatQueue;
std::queue<double> doubleQueue;
std::queue<int> intQueue;
private:
// allocation/deallocation functions defined in IoAsciiLexer.lpp
virtual void initScanner(void);
virtual void destroyScanner(void);
};
public:
// constructors
AsciiFile(void);
AsciiFile(const std::string &name, const unsigned int mode);
// destructor
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 RandGenState &state, const std::string &name);
// tests
virtual bool isOpen(void) const;
// IO
virtual void close(void);
virtual void open(const std::string &name, const unsigned int mode);
private:
// IO
virtual std::string load(const std::string &name = "");
// parser
void parse(void);
private:
std::fstream fileStream_;
bool isParsed_;
std::unique_ptr<AsciiParserState> state_;
};
END_NAMESPACE
#endif // Latan_AsciiFile_hpp_

95
latan/AsciiLexer.lpp Normal file
View File

@ -0,0 +1,95 @@
/*
* IoAsciiLexer.lpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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="_Ascii_"
%option bison-bridge
%option bison-locations
%option noyywrap
%option yylineno
%{
#include <iostream>
#include <latan/AsciiFile.hpp>
#include <latan/IOASCIIParser.hpp>
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std;
using namespace Latan;
#define YY_EXTRA_TYPE AsciiFile::AsciiParserState*
#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 RETTOK(tok) cout << #tok << "(" << yytext << ")" << endl; return tok
#else
#define RETTOK(tok) return tok
#endif
%}
DIGIT [0-9]
ALPHA [a-zA-Z_\-]
SIGN \+|-
EXP e|E
INT {SIGN}?{DIGIT}+
FLOAT {SIGN}?(({DIGIT}+\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))({EXP}{SIGN}?{INT}+)?
LMARK #L
BLANK [ \t]
%x MARK TYPE
%%
{LMARK} {BEGIN(MARK);}
{INT} {yylval->val_int = strTo<int>(yytext); RETTOK(INT);}
{FLOAT} {yylval->val_double = strTo<double>(yytext); RETTOK(FLOAT);}
({ALPHA}|{DIGIT})+ {strcpy(yylval->val_str,yytext); RETTOK(ID);}
<MARK>latan_begin {BEGIN(TYPE); RETTOK(OPEN);}
<MARK>latan_end {BEGIN(TYPE); RETTOK(CLOSE);}
<TYPE>mat {BEGIN(INITIAL); RETTOK(MAT);}
<TYPE>rs_sample {BEGIN(INITIAL); RETTOK(SAMPLE);}
<TYPE>rg_state {BEGIN(INITIAL); RETTOK(RG_STATE);}
<*>\n {yylloc->last_column = 0;}
<*>[ \t]
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
%%
void AsciiFile::AsciiParserState::initScanner()
{
yylex_init(&scanner);
yyset_extra(this, scanner);
}
void AsciiFile::AsciiParserState::destroyScanner()
{
yylex_destroy(scanner);
}

188
latan/AsciiParser.ypp Normal file
View File

@ -0,0 +1,188 @@
/*
* IoAsciiParser.ypp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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 <iostream>
#include <memory>
#include <sstream>
#include <utility>
#include <cstring>
#include <latan/Global.hpp>
#include <latan/AsciiFile.hpp>
#include <latan/Mat.hpp>
#include <latan/RandGen.hpp>
#include <latan/Sample.hpp>
using namespace std;
using namespace Latan;
#define TEST_FIRST(name) \
if (state->isFirst)\
{\
state->first = (name);\
state->isFirst = false;\
}
%}
%pure-parser
%name-prefix="_Ascii_"
%locations
%defines
%error-verbose
%parse-param { Latan::AsciiFile::AsciiParserState* state }
%initial-action {yylloc.last_column = 0;}
%lex-param { void* scanner }
%union
{
int val_int;
double val_double;
char val_char;
char val_str[256];
}
%token <val_char> ERR
%token <val_double> FLOAT
%token <val_int> INT
%token <val_str> ID
%token OPEN CLOSE MAT SAMPLE RG_STATE
%type <val_str> mat sample rg_state
%{
int _Ascii_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
void _Ascii_error(YYLTYPE* locp, AsciiFile::AsciiParserState* state,
const char* err)
{
stringstream buf;
buf << *state->streamName << ":" << locp->first_line << ":"\
<< locp->first_column << ": " << err;
LATAN_ERROR(Parsing, buf.str());
}
#define scanner state->scanner
%}
%%
datas:
/* empty string */
| datas data
;
data:
mat
{
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
{
TEST_FIRST($1);
(*state->data)[$1].reset(new RandGenState(state->stateBuf));
}
;
mat:
OPEN MAT ID INT floats CLOSE MAT
{
const unsigned int nRow = state->doubleQueue.size()/$INT, nCol = $INT;
int i, j, r = 0;
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->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
{
if (state->intQueue.size() != RLXG_STATE_SIZE)
{
LATAN_ERROR(Size, "random generator state '" + *state->streamName
+ ":" + $ID + "' has a wrong size");
}
for (unsigned int i = 0; i < RLXG_STATE_SIZE; ++i)
{
state->stateBuf[i] = state->intQueue.front();
state->intQueue.pop();
}
strcpy($$, $ID);
}
;
mats:
mats mat
| mat
;
floats:
floats FLOAT {state->doubleQueue.push($FLOAT);}
| floats INT {state->doubleQueue.push(static_cast<double>($INT));}
| FLOAT {state->doubleQueue.push($FLOAT);}
| INT {state->doubleQueue.push(static_cast<double>($INT));}
;
ints:
ints INT {state->intQueue.push($INT);}
| INT {state->intQueue.push($INT);}
;

View File

@ -21,7 +21,7 @@
#define Latan_Dataset_hpp_ #define Latan_Dataset_hpp_
#include <latan/Global.hpp> #include <latan/Global.hpp>
#include <latan/Io.hpp> #include <latan/File.hpp>
#include <latan/Sample.hpp> #include <latan/Sample.hpp>
#include <latan/RandGen.hpp> #include <latan/RandGen.hpp>
#include <fstream> #include <fstream>
@ -32,7 +32,7 @@ BEGIN_NAMESPACE
/****************************************************************************** /******************************************************************************
* Dataset class * * Dataset class *
******************************************************************************/ ******************************************************************************/
template <typename T, typename FileType> template <typename T>
class Dataset: public StatArray<T> class Dataset: public StatArray<T>
{ {
private: private:
@ -41,40 +41,43 @@ public:
// constructors // constructors
using Base::Base; using Base::Base;
Dataset(void); Dataset(void);
template <typename FileType>
Dataset(const std::string &listFileName, const std::string &dataName); Dataset(const std::string &listFileName, const std::string &dataName);
// destructor // destructor
virtual ~Dataset(void) = default; virtual ~Dataset(void) = default;
// IO // IO
template <typename FileType>
void load(const std::string &listFileName, const std::string &dataName); void load(const std::string &listFileName, const std::string &dataName);
// resampling // resampling
Sample<T> bootstrapMean(const unsigned int nSample, RandGen& generator); Sample<T> bootstrapMean(const unsigned int nSample, RandGen& generator);
private: private:
// mean from pointer vector for resampling // mean from pointer vector for resampling
void ptVectorMean(T &m, const std::vector<const T *> &v); void ptVectorMean(T &m, const std::vector<const T *> &v);
private:
FileType file_;
}; };
/****************************************************************************** /******************************************************************************
* Dataset template implementation * * Dataset template implementation *
******************************************************************************/ ******************************************************************************/
// constructor ///////////////////////////////////////////////////////////////// // constructor /////////////////////////////////////////////////////////////////
template <typename T, typename FileType> template <typename T>
Dataset<T, FileType>::Dataset(void) Dataset<T>::Dataset(void)
{} {}
template <typename T, typename FileType> template <typename T>
Dataset<T, FileType>::Dataset(const std::string &listFileName, template <typename FileType>
const std::string &dataName) Dataset<T>::Dataset(const std::string &listFileName,
const std::string &dataName)
{ {
load(listFileName, dataName); load<FileType>(listFileName, dataName);
} }
// IO ////////////////////////////////////////////////////////////////////////// // IO //////////////////////////////////////////////////////////////////////////
template <typename T, typename FileType> template <typename T>
void Dataset<T, FileType>::load(const std::string &listFileName, template <typename FileType>
const std::string &dataName) void Dataset<T>::load(const std::string &listFileName,
const std::string &dataName)
{ {
FileType file;
std::ifstream listFile; std::ifstream listFile;
char dataFileNameBuf[MAX_PATH_LENGTH]; char dataFileNameBuf[MAX_PATH_LENGTH];
std::vector<std::string> dataFileName; std::vector<std::string> dataFileName;
@ -92,16 +95,16 @@ void Dataset<T, FileType>::load(const std::string &listFileName,
this->resize(dataFileName.size()); this->resize(dataFileName.size());
for (unsigned int i = 0; i < dataFileName.size(); ++i) for (unsigned int i = 0; i < dataFileName.size(); ++i)
{ {
file_.open(dataFileName[i], File::Mode::read); file.open(dataFileName[i], File::Mode::read);
(*this)[i] = file_.template read<T>(dataName); (*this)[i] = file.template read<T>(dataName);
file_.close(); file.close();
} }
} }
// resampling ////////////////////////////////////////////////////////////////// // resampling //////////////////////////////////////////////////////////////////
template <typename T, typename FileType> template <typename T>
Sample<T> Dataset<T, FileType>::bootstrapMean(const unsigned int nSample, Sample<T> Dataset<T>::bootstrapMean(const unsigned int nSample,
RandGen& generator) RandGen& generator)
{ {
unsigned int nData = this->size(); unsigned int nData = this->size();
std::vector<const T *> data(nData); std::vector<const T *> data(nData);
@ -124,8 +127,8 @@ Sample<T> Dataset<T, FileType>::bootstrapMean(const unsigned int nSample,
return s; return s;
} }
template <typename T, typename FileType> template <typename T>
void Dataset<T, FileType>::ptVectorMean(T &m, const std::vector<const T *> &v) void Dataset<T>::ptVectorMean(T &m, const std::vector<const T *> &v)
{ {
if (v.size()) if (v.size())
{ {

75
latan/File.cpp Normal file
View File

@ -0,0 +1,75 @@
/*
* File.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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 <latan/File.hpp>
#include <latan/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* File implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
File::File(void)
: name_("")
, mode_(Mode::null)
, data_()
{}
File::File(const string &name, const unsigned int mode)
: name_(name)
, mode_(mode)
, data_()
{}
// destructor //////////////////////////////////////////////////////////////////
File::~File(void)
{
deleteData();
}
// access //////////////////////////////////////////////////////////////////////
const string & File::getName(void) const
{
return name_;
}
unsigned int File::getMode(void) const
{
return mode_;
}
// internal functions //////////////////////////////////////////////////////////
void File::deleteData(void)
{
for (auto &i : data_)
{
i.second.reset();
}
data_.clear();
}
void File::checkWritability(void)
{
if (!((mode_ & Mode::write)||(mode_ & Mode::append))||!isOpen())
{
LATAN_ERROR(Io, "file '" + name_ + "' is not writable");
}
}

161
latan/File.hpp Normal file
View File

@ -0,0 +1,161 @@
/*
* File.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 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_Io_hpp_
#define Latan_Io_hpp_
#include <fstream>
#include <memory>
#include <queue>
#include <sstream>
#include <string>
#include <unordered_map>
#include <latan/Global.hpp>
#include <latan/IoObject.hpp>
#include <latan/ParserState.hpp>
BEGIN_NAMESPACE
// forward declaration of IO types
class DMat;
class DMatSample;
class RandGen;
class RandGenState;
/******************************************************************************
* Abstract datafile class *
******************************************************************************/
typedef std::unordered_map<std::string, std::unique_ptr<IoObject>> IoDataTable;
class File
{
public:
class Mode
{
public:
enum
{
null = 0,
write = 1 << 0,
read = 1 << 1,
append = 1 << 2
};
};
public:
// constructors
File(void);
File(const std::string &name, const unsigned int mode);
// destructor
virtual ~File(void);
// access
const std::string & getName(void) const;
unsigned int getMode(void) const;
template <typename IoT>
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 RandGenState &state, const std::string &name) = 0;
// tests
virtual bool isOpen(void) const = 0;
// IO
virtual void close(void) = 0;
virtual void open(const std::string &name, const unsigned int mode) = 0;
// static IO functions
protected:
// access
void setName(const std::string &name);
void setMode(const unsigned int mode);
// data access
void deleteData(void);
// error checking
void checkWritability(void);
private:
// data access
template <typename IoT>
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_;
IoDataTable data_;
};
// Template implementations
template <typename IoT>
const IoT& File::read(const std::string &name)
{
std::string dataName;
dataName = load(name);
return getData<IoT>(dataName);
}
template <typename IoT>
const IoT& File::getData(const std::string &name) const
{
try
{
return dynamic_cast<const IoT &>(*(data_.at(name)));
}
catch(std::out_of_range)
{
LATAN_ERROR(Definition, "no data with name '" + name + "' in file "
+ name_);
}
}
/******************************************************************************
* Static IO functions *
******************************************************************************/
class Io
{
public:
template <typename IoT, typename FileType>
static IoT load(const std::string &fileName, const std::string &name = "");
template <typename IoT, typename FileType>
static void save(const IoT &data, const std::string &fileName,
const unsigned int mode = File::Mode::append,
const std::string &name = "");
};
// template implementation /////////////////////////////////////////////////////
template <typename IoT, typename FileType>
IoT Io::load(const std::string &fileName, const std::string &name)
{
FileType file(fileName, File::Mode::read);
return file.template read<IoT>(name);
}
template <typename IoT, typename FileType>
void Io::save(const IoT &data, const std::string &fileName,
const unsigned int mode, const std::string &name)
{
FileType file(fileName, mode);
std::string realName = (name.empty()) ? fileName : name;
file.template save(data, realName);
}
END_NAMESPACE
#endif

View File

@ -24,7 +24,9 @@
BEGIN_NAMESPACE BEGIN_NAMESPACE
// Abstract base for IO objects /******************************************************************************
* Abstract class for IO objects *
******************************************************************************/
class IoObject class IoObject
{ {
public: public:

View File

@ -20,19 +20,20 @@ AM_YFLAGS = -d
include eigen_files.mk include eigen_files.mk
nobase_dist_pkginclude_HEADERS = $(eigen_files) nobase_dist_pkginclude_HEADERS = $(eigen_files)
BUILT_SOURCES = IoAsciiParser.hpp MathParser.hpp BUILT_SOURCES = AsciiParser.hpp MathParser.hpp
lib_LTLIBRARIES = liblatan.la lib_LTLIBRARIES = liblatan.la
liblatan_la_SOURCES = \ liblatan_la_SOURCES = \
AsciiFile.cpp \
AsciiParser.ypp \
AsciiLexer.lpp \
CompiledFunction.cpp\ CompiledFunction.cpp\
Exceptions.cpp \ Exceptions.cpp \
Function.cpp \ Function.cpp \
Global.cpp \ Global.cpp \
includes.hpp \ includes.hpp \
Io.cpp \ File.cpp \
IoAsciiParser.ypp \
IoAsciiLexer.lpp \
Mat.cpp \ Mat.cpp \
Math.cpp \ Math.cpp \
MathInterpreter.cpp \ MathInterpreter.cpp \
@ -45,11 +46,12 @@ liblatan_la_SOURCES = \
../config.h ../config.h
liblatan_ladir = $(pkgincludedir) liblatan_ladir = $(pkgincludedir)
liblatan_la_HEADERS = \ liblatan_la_HEADERS = \
AsciiFile.hpp \
CompiledFunction.hpp\ CompiledFunction.hpp\
Dataset.hpp \ Dataset.hpp \
Function.hpp \ Function.hpp \
Global.hpp \ Global.hpp \
Io.hpp \ File.hpp \
IoObject.hpp \ IoObject.hpp \
Mat.hpp \ Mat.hpp \
Math.hpp \ Math.hpp \

View File

@ -28,18 +28,17 @@ using namespace std;
using namespace Latan; using namespace Latan;
/****************************************************************************** /******************************************************************************
* RandGen implementation * * RandGenState implementation *
******************************************************************************/ ******************************************************************************/
// State constructor /////////////////////////////////////////////////////////// // IO type ///////////////////////////////////////////////////////////////
RandGen::State::State(void) IoObject::IoType RandGenState::getType(void) const
{}
// State IO type ///////////////////////////////////////////////////////////////
IoObject::IoType RandGen::State::getType(void) const
{ {
return IoType::rgState; return IoType::rgState;
} }
/******************************************************************************
* RandGen implementation *
******************************************************************************/
// RanLxd implementation /////////////////////////////////////////////////////// // RanLxd implementation ///////////////////////////////////////////////////////
RandGen::RanLxd::RanLxd(void) RandGen::RanLxd::RanLxd(void)
: init(0) : init(0)
@ -640,22 +639,22 @@ RandGen::RandGen(const int seed)
generator_.rlxd_init(RLXD_LEVEL, seed); generator_.rlxd_init(RLXD_LEVEL, seed);
} }
RandGen::RandGen(const State &state) RandGen::RandGen(const RandGenState &state)
{ {
setState(state); setState(state);
} }
// state management //////////////////////////////////////////////////////////// // state management ////////////////////////////////////////////////////////////
RandGen::State RandGen::getState(void) const RandGenState RandGen::getState(void) const
{ {
State state; RandGenState state;
generator_.rlxd_get(state.data()); generator_.rlxd_get(state.data());
return state; return state;
} }
void RandGen::setState(const State &state) void RandGen::setState(const RandGenState &state)
{ {
generator_.rlxd_reset(state.data()); generator_.rlxd_reset(state.data());
} }

View File

@ -27,25 +27,24 @@
BEGIN_NAMESPACE BEGIN_NAMESPACE
class RandGenState: public Eigen::Array<int, RLXG_STATE_SIZE, 1>,
public IoObject
{
private:
typedef Eigen::Array<int, RLXG_STATE_SIZE, 1> Base;
public:
// destructor
virtual ~RandGenState(void) = default;
// IO type
IoType getType(void) const;
};
/****************************************************************************** /******************************************************************************
* Random generator class * * Random generator class *
******************************************************************************/ ******************************************************************************/
class RandGen class RandGen
{ {
public:
class State: public Eigen::Array<int, RLXG_STATE_SIZE, 1>, public IoObject
{
private:
typedef Eigen::Array<int, RLXG_STATE_SIZE, 1> Base;
public:
// constructor
State(void);
// destructor
virtual ~State(void) = default;
// IO type
IoType getType(void) const;
};
private: private:
// Martin Luescher's ranlxd generator interface // Martin Luescher's ranlxd generator interface
class RanLxd class RanLxd
@ -85,12 +84,12 @@ public:
// constructors // constructors
RandGen(void); RandGen(void);
RandGen(const int seed); RandGen(const int seed);
RandGen(const State &state); RandGen(const RandGenState &state);
// destructor // destructor
virtual ~RandGen(void) = default; virtual ~RandGen(void) = default;
// state management // state management
State getState(void) const; RandGenState getState(void) const;
void setState(const State &state); void setState(const RandGenState &state);
// generators // generators
double uniform(const double a = 0.0, const double b = 1.0); double uniform(const double a = 0.0, const double b = 1.0);
double discreteUniform(const unsigned int n); double discreteUniform(const unsigned int n);

View File

@ -1,8 +1,8 @@
#include <iostream> #include <iostream>
#include <libgen.h> #include <libgen.h>
#include <unistd.h> #include <unistd.h>
#include <latan/AsciiFile.hpp>
#include <latan/Dataset.hpp> #include <latan/Dataset.hpp>
#include <latan/Io.hpp>
#ifndef DEF_NSAMPLE #ifndef DEF_NSAMPLE
#define DEF_NSAMPLE 100u #define DEF_NSAMPLE 100u
@ -60,25 +60,25 @@ int main(int argc, char *argv[])
usage(cmdName); usage(cmdName);
} }
Dataset<DMat, AsciiFile> dataset; Dataset<DMat> dataset;
DMatSample s; DMatSample s;
RandGen g; RandGen g;
if (!stateFileName.empty()) if (!stateFileName.empty())
{ {
AsciiFile f(stateFileName, File::Mode::read); AsciiFile f(stateFileName, File::Mode::read);
g.setState(f.read<RandGen::State>()); g.setState(f.read<RandGenState>());
} }
cout << "-- loading data from manifest '" << manFileName << "'..." << endl; cout << "-- loading data from manifest '" << manFileName << "'..." << endl;
dataset.load(manFileName, name); dataset.load<AsciiFile>(manFileName, name);
s = dataset.bootstrapMean(nSample, g); s = dataset.bootstrapMean(nSample, g);
cout << scientific; cout << scientific;
cout << "central value:\n" << s[central] << endl; cout << "central value:\n" << s[central] << endl;
cout << "standard deviation:\n" << s.variance().cwiseSqrt() << endl; cout << "standard deviation:\n" << s.variance().cwiseSqrt() << endl;
if (!outFileName.empty()) if (!outFileName.empty())
{ {
AsciiFile f(outFileName, File::Mode::write); Io::save<DMatSample, AsciiFile>(s, outFileName, File::Mode::write,
f.save(s, manFileName + "_" + name); manFileName + "_" + name);
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -1,5 +1,5 @@
#include <iostream> #include <iostream>
#include <latan/Io.hpp> #include <latan/AsciiFile.hpp>
using namespace std; using namespace std;
using namespace Latan; using namespace Latan;
@ -13,10 +13,9 @@ int main(int argc, char *argv[])
} }
string fileName = argv[1]; string fileName = argv[1];
AsciiFile f(fileName, File::Mode::read);
cout << "-- loading sample from '" << fileName << "'..." << endl; cout << "-- loading sample from '" << fileName << "'..." << endl;
const DMatSample &s = f.read<DMatSample>(); const DMatSample &s = Io::load<DMatSample, AsciiFile>(fileName);
cout << scientific; cout << scientific;
cout << "central value:\n" << s[central] << endl; cout << "central value:\n" << s[central] << endl;
cout << "standard deviation:\n" << s.variance().cwiseSqrt() << endl; cout << "standard deviation:\n" << s.variance().cwiseSqrt() << endl;