diff options
Diffstat (limited to 'geom_bottleneck/include/diagram_reader.h')
-rw-r--r-- | geom_bottleneck/include/diagram_reader.h | 217 |
1 files changed, 137 insertions, 80 deletions
diff --git a/geom_bottleneck/include/diagram_reader.h b/geom_bottleneck/include/diagram_reader.h index 5bf106d..08d9e2b 100644 --- a/geom_bottleneck/include/diagram_reader.h +++ b/geom_bottleneck/include/diagram_reader.h @@ -1,5 +1,4 @@ /* - Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov All rights reserved. @@ -39,101 +38,159 @@ derivative works thereof, in binary and source code form. #include <cctype> namespace hera { + +// cannot choose stod, stof or stold based on RealType, +// lazy solution: partial specialization + template<class RealType = double> + inline RealType parse_real_from_str(const std::string& s); + + template <> + inline double parse_real_from_str<double>(const std::string& s) + { + return std::stod(s); + } + + + template <> + inline long double parse_real_from_str<long double>(const std::string& s) + { + return std::stold(s); + } + + + template <> + inline float parse_real_from_str<float>(const std::string& s) + { + return std::stof(s); + } + + + template<class RealType> + inline RealType parse_real_from_str(const std::string& s) + { + static_assert(sizeof(RealType) != sizeof(RealType), "Must be specialized for each type you want to use, see above"); + } + // fill in result with points from file fname // return false if file can't be opened // or error occurred while reading // decPrecision is the maximal decimal precision in the input, // it is zero if all coordinates in the input are integers -template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> -bool readDiagramPointSet(const char* fname, ContType_& result, int& decPrecision) -{ - size_t lineNumber { 0 }; - result.clear(); - std::ifstream f(fname); - if (!f.good()) { + + template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> + inline bool readDiagramPointSet(const char* fname, ContType_& result, int& decPrecision) + { + using RealType = RealType_; + + size_t lineNumber { 0 }; + result.clear(); + std::ifstream f(fname); + if (!f.good()) { #ifndef FOR_R_TDA - std::cerr << "Cannot open file " << fname << std::endl; + std::cerr << "Cannot open file " << fname << std::endl; #endif - return false; - } - std::string line; - while(std::getline(f, line)) { - lineNumber++; - // process comments: remove everything after hash - auto hashPos = line.find_first_of("#", 0); - if( std::string::npos != hashPos) { - line = std::string(line.begin(), line.begin() + hashPos); - } - if (line.empty()) { - continue; - } - // trim whitespaces - auto whiteSpaceFront = std::find_if_not(line.begin(),line.end(),isspace); - auto whiteSpaceBack = std::find_if_not(line.rbegin(),line.rend(),isspace).base(); - if (whiteSpaceBack <= whiteSpaceFront) { - // line consists of spaces only - move to the next line - continue; + return false; } - line = std::string(whiteSpaceFront,whiteSpaceBack); - bool fracPart = false; - int currDecPrecision = 0; - for(auto c : line) { - if (c == '.') { - fracPart = true; - } else if (fracPart) { - if (isdigit(c)) { - currDecPrecision++; + std::locale loc; + std::string line; + while(std::getline(f, line)) { + lineNumber++; + // process comments: remove everything after hash + auto hashPos = line.find_first_of("#", 0); + if( std::string::npos != hashPos) { + line = std::string(line.begin(), line.begin() + hashPos); + } + if (line.empty()) { + continue; + } + // trim whitespaces + auto whiteSpaceFront = std::find_if_not(line.begin(),line.end(),isspace); + auto whiteSpaceBack = std::find_if_not(line.rbegin(),line.rend(),isspace).base(); + if (whiteSpaceBack <= whiteSpaceFront) { + // line consists of spaces only - move to the next line + continue; + } + line = std::string(whiteSpaceFront,whiteSpaceBack); + + // transform line to lower case + // to parse Infinity + for(auto& c : line) { + c = std::tolower(c, loc); + } + + bool fracPart = false; + int currDecPrecision = 0; + for(auto c : line) { + if (c == '.') { + fracPart = true; + } else if (fracPart) { + if (isdigit(c)) { + currDecPrecision++; + } else { + fracPart = false; + if (currDecPrecision > decPrecision) + decPrecision = currDecPrecision; + currDecPrecision = 0; + } + } + } + + RealType x, y; + std::string str_x, str_y; + std::istringstream iss(line); + try { + iss >> str_x >> str_y; + + x = parse_real_from_str<RealType>(str_x); + y = parse_real_from_str<RealType>(str_y); + + if (x != y) { + result.push_back(std::make_pair(x, y)); } else { - fracPart = false; - if (currDecPrecision > decPrecision) - decPrecision = currDecPrecision; - currDecPrecision = 0; +#ifndef FOR_R_TDA + std::cerr << "Warning: point with 0 persistence ignored in " << fname << ":" << lineNumber << "\n"; +#endif } } - } - RealType_ x, y; - std::istringstream iss(line); - if (not(iss >> x >> y)) { + catch (const std::invalid_argument& e) { #ifndef FOR_R_TDA - std::cerr << "Error in file " << fname << ", line number " << lineNumber << ": cannot parse \"" << line << "\"" << std::endl; + std::cerr << "Error in file " << fname << ", line number " << lineNumber << ": cannot parse \"" << line << "\"" << std::endl; #endif - return false; - } - if ( x != y ) { - result.push_back(std::make_pair(x,y)); - } else { -#ifdef VERBOSE_BOTTLENECK - std::cerr << "Warning: in file " << fname << ", line number " << lineNumber << ", zero persistence point ignored: \"" << line << "\"" << std::endl; + return false; + } + catch (const std::out_of_range&) { +#ifndef FOR_R_TDA + std::cerr << "Error while reading file " << fname << ", line number " << lineNumber << ": value too large in \"" << line << "\"" << std::endl; #endif + return false; + } } + f.close(); + return true; + } + + // wrappers + template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> + inline bool readDiagramPointSet(const std::string& fname, ContType_& result, int& decPrecision) + { + return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision); + } + + // these two functions are now just wrappers for the previous ones, + // in case someone needs them; decPrecision is ignored + template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> + inline bool readDiagramPointSet(const char* fname, ContType_& result) + { + int decPrecision; + return readDiagramPointSet<RealType_, ContType_>(fname, result, decPrecision); + } + + template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> + inline bool readDiagramPointSet(const std::string& fname, ContType_& result) + { + int decPrecision; + return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision); } - f.close(); - return true; -} - - -// wrappers -template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> -bool readDiagramPointSet(const std::string& fname, ContType_& result, int& decPrecision) -{ - return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision); -} - -// these two functions are now just wrappers for the previous ones, -// in case someone needs them; decPrecision is ignored -template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> -bool readDiagramPointSet(const char* fname, ContType_& result) -{ - int decPrecision; - return readDiagramPointSet<RealType_, ContType_>(fname, result, decPrecision); -} - -template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>> -bool readDiagramPointSet(const std::string& fname, ContType_& result) -{ - int decPrecision; - return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision); -} } // end namespace hera #endif // HERA_DIAGRAM_READER_H |