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