summaryrefslogtreecommitdiff
path: root/geom_bottleneck/include/diagram_reader.h
diff options
context:
space:
mode:
Diffstat (limited to 'geom_bottleneck/include/diagram_reader.h')
-rw-r--r--geom_bottleneck/include/diagram_reader.h217
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