1 /////////////////////////////////////////////////////////////////////////////// 2 // // 3 // The Template Matrix/Vector Library for C++ was created by Mike Jarvis // 4 // Copyright (C) 1998 - 2016 // 5 // All rights reserved // 6 // // 7 // The project is hosted at https://code.google.com/p/tmv-cpp/ // 8 // where you can find the current version and current documention. // 9 // // 10 // For concerns or problems with the software, Mike may be contacted at // 11 // mike_jarvis17 [at] gmail. // 12 // // 13 // This software is licensed under a FreeBSD license. The file // 14 // TMV_LICENSE should have bee included with this distribution. // 15 // It not, you can get a copy from https://code.google.com/p/tmv-cpp/. // 16 // // 17 // Essentially, you can use this software however you want provided that // 18 // you include the TMV_LICENSE file in any distribution that uses it. // 19 // // 20 /////////////////////////////////////////////////////////////////////////////// 21 22 23 #ifndef TMV_IOStyle_H 24 #define TMV_IOStyle_H 25 26 namespace tmv { 27 28 class IOStyle 29 { 30 public: IOStyle()31 IOStyle() 32 { setToDefault(); } 33 34 // Use default copy, destructor, op= 35 36 // Handlers for setting features: noPrefix()37 IOStyle& noPrefix() 38 { usecode = false; writesize = false; return *this; } 39 useCode()40 IOStyle& useCode() 41 { usecode = true; return *this; } 42 noCode()43 IOStyle& noCode() 44 { usecode = false; return *this; } 45 noSize()46 IOStyle& noSize() 47 { writesize = false; return *this; } 48 simpleSize()49 IOStyle& simpleSize() 50 { writesize = true; simplesize = true; return *this; } 51 fullSize()52 IOStyle& fullSize() 53 { writesize = true; simplesize = false; return *this; } 54 markup(const std::string & s,const std::string & lp,const std::string & sp,const std::string & rp,const std::string & re,const std::string & f)55 IOStyle& markup( 56 const std::string& s, const std::string& lp, 57 const std::string& sp, const std::string& rp, 58 const std::string& re, const std::string& f) 59 { 60 start = s; lparen = lp; space = sp; 61 rparen = rp; rowend = re; final = f; 62 return *this; 63 } 64 fullMatrix()65 IOStyle& fullMatrix() 66 { usecompact = false; return *this; } 67 compact()68 IOStyle& compact() 69 { usecompact = true; return *this; } 70 setThresh(double t)71 IOStyle& setThresh(double t) 72 { thresh = t; return *this; } 73 setPrecision(int p)74 IOStyle& setPrecision(int p) 75 { prec = p; return *this; } 76 useDefaultPrecision()77 IOStyle& useDefaultPrecision() 78 { prec = -1; return *this; } 79 80 // Revert to the default values. setToDefault()81 IOStyle& setToDefault() 82 { *this = getDefaultSingleton(); return *this; } 83 84 // Declare current state to be default IOStyle from now on. makeDefault()85 void makeDefault() 86 { getDefaultSingleton() = *this; } 87 88 // Revert the default IO to the original default style. revertDefault()89 static void revertDefault() 90 { getDefaultSingleton() = IOStyle(0); } 91 92 93 private : 94 95 bool usecode; 96 bool writesize; 97 bool simplesize; 98 bool usecompact; 99 std::string start; 100 std::string lparen; 101 std::string space; 102 std::string rparen; 103 std::string rowend; 104 std::string final; 105 double thresh; 106 int prec; // -1 = don't change precision. 107 write(std::ostream & os)108 void write(std::ostream& os) 109 { 110 os << usecode << " " << writesize << " " 111 << simplesize << " " << usecompact << " '" 112 << start << "' '" << lparen << "' '" << space << "' '" 113 << rparen << "' '" << rowend << "' '" << final << "' " 114 << thresh << " " << prec; 115 } 116 117 // Helper for dealing with threshold writing. 118 template <typename T> outVal(const T & val)119 T outVal(const T& val) const 120 { return (thresh > 0. && TMV_ABS(val) < thresh) ? T(0) : val; } 121 122 template <typename T> outVal(const std::complex<T> & val)123 std::complex<T> outVal(const std::complex<T>& val) const 124 { 125 return thresh > 0. ? 126 std::complex<T>(outVal(real(val)),outVal(imag(val))) : val; 127 } 128 129 // Private constructor with initial default values. 130 // (The int is just to make it easy to resolve on the signature.) IOStyle(int)131 IOStyle(int) : 132 usecode(false), writesize(true), simplesize(true), 133 usecompact(false), 134 start("\n"), lparen("( "), space(" "), 135 rparen(" )"), rowend("\n"), final("\n"), 136 thresh(0.), prec(-1) {} 137 138 // Use a singleton idiom for the default IOStyle: getDefaultSingleton()139 static inline IOStyle& getDefaultSingleton() 140 { 141 static IOStyle def(0); 142 return def; 143 } 144 145 // All actual usage of this class is mediated through a 146 // Writer or Reader. 147 friend class TMV_Writer; 148 friend class TMV_Reader; 149 }; 150 151 // Some IOStyles that might be typically useful: NormalIO()152 inline IOStyle NormalIO() 153 { 154 return IOStyle().noCode().simpleSize().fullMatrix(). 155 markup("\n","( "," "," )","\n","\n"); 156 } 157 CompactIO()158 inline IOStyle CompactIO() 159 { 160 return IOStyle().useCode().fullSize().compact(). 161 markup("",""," ",""," ",""); 162 } 163 ThreshIO(double thresh)164 inline IOStyle ThreshIO(double thresh) 165 { return IOStyle().setThresh(thresh); } 166 PrecIO(int prec)167 inline IOStyle PrecIO(int prec) 168 { return IOStyle().setPrecision(prec); } 169 EigenIO()170 inline IOStyle EigenIO() 171 { return IOStyle().noPrefix().fullMatrix().markup("",""," ","","\n",""); } 172 173 class TMV_Writer 174 { 175 public : TMV_Writer(std::ostream & _os,const IOStyle & _s)176 TMV_Writer(std::ostream& _os, const IOStyle& _s) : os(_os), s(_s) {} 177 // Use default copy, op=, destr 178 begin()179 void begin() const 180 { 181 if (s.prec >= 0) { 182 oldprec = os.precision(s.prec); 183 } 184 } 185 end()186 void end() const 187 { 188 if (s.prec >= 0) { 189 os.precision(oldprec); 190 } 191 } 192 writeCode(const std::string & code)193 void writeCode(const std::string& code) const 194 { if (s.usecode) os << code << s.space; } 195 writeSize(ptrdiff_t n)196 void writeSize(ptrdiff_t n) const 197 { if (s.writesize) os << n << s.space; } writeSimpleSize(ptrdiff_t n)198 void writeSimpleSize(ptrdiff_t n) const 199 { if (s.simplesize) writeSize(n); } writeFullSize(ptrdiff_t n)200 void writeFullSize(ptrdiff_t n) const 201 { if (!s.simplesize) writeSize(n); } 202 writeStart()203 void writeStart() const 204 { os << s.start; } writeLParen()205 void writeLParen() const 206 { os << s.lparen; } writeSpace()207 void writeSpace() const 208 { os << s.space; } writeRParen()209 void writeRParen() const 210 { os << s.rparen; } writeRowEnd()211 void writeRowEnd() const 212 { os << s.rowend; } writeFinal()213 void writeFinal() const 214 { os << s.final; } 215 216 template <typename T> writeValue(const T & x)217 void writeValue(const T& x) const 218 { os << Value(s.outVal(x)); } 219 isCompact()220 bool isCompact() const 221 { return s.usecompact; } 222 getos()223 std::ostream& getos() const { return os; } getstyle()224 const IOStyle& getstyle() const { return s; } 225 226 private : 227 std::ostream& os; 228 IOStyle s; 229 230 mutable std::streamsize oldprec; 231 232 // This bit is to workaround a bug in pgCC that was fixed in version 7. 233 // I don't know if versions earlier than 6.1 had the bug, but 234 // I apply the workaround to all version before 7. 235 template <typename T> Value(const T & x)236 static inline T Value(const T& x) { return x; } 237 #if defined(__PGI) && (!defined(__PGIC__) || __PGIC__ < 7) Value(const long double & x)238 static inline double Value(const long double& x) 239 { return double(x); } Value(const std::complex<long double> & x)240 static inline std::complex<double> Value( 241 const std::complex<long double>& x) 242 { return std::complex<double>(x); } 243 #endif 244 }; 245 246 inline TMV_Writer operator<<(std::ostream& os, const IOStyle& style) 247 { return TMV_Writer(os,style); } 248 249 class TMV_Reader 250 { 251 public : TMV_Reader(std::istream & _is,const IOStyle & _s)252 TMV_Reader(std::istream& _is, const IOStyle& _s) : is(_is), s(_s) {} 253 // Use default copy, op=, destr 254 readStr(const std::string & str,std::string & exp,std::string & got)255 bool readStr( 256 const std::string& str, std::string& exp, std::string& got) const 257 { 258 if (str.size() == 0) return true; 259 else { 260 skipWhiteSpace(); 261 std::string getstr(str.size(),' '); 262 for(size_t i=0;i<str.size();++i) is.get(getstr[i]); 263 if (getstr != str) { 264 exp = str; 265 got = getstr; 266 return false; 267 } 268 if (!is) return false; 269 else return true; 270 } 271 } 272 readCode(const std::string & code,std::string & exp,std::string & got)273 bool readCode( 274 const std::string& code, std::string& exp, std::string& got) const 275 { 276 if (s.usecode) { 277 if (readStr(trim(code),exp,got)) { 278 return readSpace(exp,got); 279 } else { 280 return false; 281 } 282 } else { 283 return true; 284 } 285 } 286 287 // For real SymMatrix, there are two valid codes. readCode(const std::string & code1,const std::string & code2,std::string & exp,std::string & got)288 bool readCode( 289 const std::string& code1, const std::string& code2, 290 std::string& exp, std::string& got) const 291 { 292 if (s.usecode) { 293 if (readStr(trim(code1),exp,got)) { 294 return readSpace(exp,got); 295 } else if (got == code2) { 296 exp = got = ""; 297 return readSpace(exp,got); 298 } else { 299 return false; 300 } 301 } else { 302 return true; 303 } 304 } 305 readStart(std::string & exp,std::string & got)306 bool readStart(std::string& exp, std::string& got) const 307 { return readStr(trim(s.start),exp,got); } 308 readLParen(std::string & exp,std::string & got)309 bool readLParen(std::string& exp, std::string& got) const 310 { return readStr(trim(s.lparen),exp,got); } 311 readSpace(std::string & exp,std::string & got)312 bool readSpace(std::string& exp, std::string& got) const 313 { return readStr(trim(s.space),exp,got); } 314 readRParen(std::string & exp,std::string & got)315 bool readRParen(std::string& exp, std::string& got) const 316 { return readStr(trim(s.rparen),exp,got); } 317 readRowEnd(std::string & exp,std::string & got)318 bool readRowEnd(std::string& exp, std::string& got) const 319 { return readStr(trim(s.rowend),exp,got); } 320 readFinal(std::string & exp,std::string & got)321 bool readFinal(std::string& exp, std::string& got) const 322 { return readStr(trim(s.final),exp,got); } 323 readSize(ptrdiff_t & n,std::string & exp,std::string & got)324 bool readSize(ptrdiff_t& n, std::string& exp, std::string& got) const 325 { 326 if (s.writesize) { 327 skipWhiteSpace(); 328 is >> n; 329 if (!is) return false; 330 else return readSpace(exp,got); 331 } else { 332 return true; 333 } 334 } 335 readSimpleSize(ptrdiff_t & n,std::string & exp,std::string & got)336 bool readSimpleSize(ptrdiff_t& n, std::string& exp, std::string& got) const 337 { return s.simplesize ? readSize(n,exp,got) : true; } 338 readFullSize(ptrdiff_t & n,std::string & exp,std::string & got)339 bool readFullSize(ptrdiff_t& n, std::string& exp, std::string& got) const 340 { return !s.simplesize ? readSize(n,exp,got) : true; } 341 342 template <typename T> readValue(T & x)343 bool readValue(T& x) const 344 { 345 skipWhiteSpace(); 346 is >> x; 347 if (!is) return false; 348 else return true; 349 } 350 isCompact()351 bool isCompact() const 352 { return s.usecompact; } 353 getis()354 std::istream& getis() const { return is; } getstyle()355 const IOStyle& getstyle() const { return s; } 356 357 private : 358 std::istream& is; 359 IOStyle s; 360 skipWhiteSpace()361 void skipWhiteSpace() const 362 { 363 static std::string whitespace = " \n\t\v\r\f"; 364 char c; 365 do { is.get(c); } while (whitespace.find(c) != std::string::npos); 366 is.unget(); 367 } 368 trim(std::string s)369 static std::string trim(std::string s) 370 { 371 static std::string whitespace = " \n\t\v\r\f"; 372 size_t i1 = s.find_first_not_of(whitespace); 373 if (i1 == std::string::npos) return ""; 374 else { 375 size_t i2 = s.find_last_not_of(whitespace); 376 return std::string(s,i1,i2-i1+1); 377 } 378 } 379 }; 380 381 inline TMV_Reader operator>>(std::istream& is, const IOStyle& style) 382 { return TMV_Reader(is,style); } 383 384 } // namespace tmv 385 386 #endif 387