Chris@16
|
1 //
|
Chris@16
|
2 // Copyright (c) 2000-2010
|
Chris@16
|
3 // Joerg Walter, Mathias Koch, David Bellot
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //
|
Chris@16
|
9 // The authors gratefully acknowledge the support of
|
Chris@16
|
10 // GeNeSys mbH & Co. KG in producing this work.
|
Chris@16
|
11 //
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef _BOOST_UBLAS_IO_
|
Chris@16
|
14 #define _BOOST_UBLAS_IO_
|
Chris@16
|
15
|
Chris@16
|
16 // Only forward definition required to define stream operations
|
Chris@16
|
17 #include <iosfwd>
|
Chris@16
|
18 #include <sstream>
|
Chris@16
|
19 #include <boost/numeric/ublas/matrix_expression.hpp>
|
Chris@16
|
20
|
Chris@16
|
21
|
Chris@16
|
22 namespace boost { namespace numeric { namespace ublas {
|
Chris@16
|
23
|
Chris@16
|
24 /** \brief output stream operator for vector expressions
|
Chris@16
|
25 *
|
Chris@16
|
26 * Any vector expressions can be written to a standard output stream
|
Chris@16
|
27 * as defined in the C++ standard library. For example:
|
Chris@16
|
28 * \code
|
Chris@16
|
29 * vector<float> v1(3),v2(3);
|
Chris@16
|
30 * for(size_t i=0; i<3; i++)
|
Chris@16
|
31 * {
|
Chris@16
|
32 * v1(i) = i+0.2;
|
Chris@16
|
33 * v2(i) = i+0.3;
|
Chris@16
|
34 * }
|
Chris@16
|
35 * cout << v1+v2 << endl;
|
Chris@16
|
36 * \endcode
|
Chris@16
|
37 * will display the some of the 2 vectors like this:
|
Chris@16
|
38 * \code
|
Chris@16
|
39 * [3](0.5,2.5,4.5)
|
Chris@16
|
40 * \endcode
|
Chris@16
|
41 *
|
Chris@16
|
42 * \param os is a standard basic output stream
|
Chris@16
|
43 * \param v is a vector expression
|
Chris@16
|
44 * \return a reference to the resulting output stream
|
Chris@16
|
45 */
|
Chris@16
|
46 template<class E, class T, class VE>
|
Chris@16
|
47 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
|
Chris@16
|
48 std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os,
|
Chris@16
|
49 const vector_expression<VE> &v) {
|
Chris@16
|
50 typedef typename VE::size_type size_type;
|
Chris@16
|
51 size_type size = v ().size ();
|
Chris@16
|
52 std::basic_ostringstream<E, T, std::allocator<E> > s;
|
Chris@16
|
53 s.flags (os.flags ());
|
Chris@16
|
54 s.imbue (os.getloc ());
|
Chris@16
|
55 s.precision (os.precision ());
|
Chris@16
|
56 s << '[' << size << "](";
|
Chris@16
|
57 if (size > 0)
|
Chris@16
|
58 s << v () (0);
|
Chris@16
|
59 for (size_type i = 1; i < size; ++ i)
|
Chris@16
|
60 s << ',' << v () (i);
|
Chris@16
|
61 s << ')';
|
Chris@16
|
62 return os << s.str ().c_str ();
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 /** \brief input stream operator for vectors
|
Chris@16
|
66 *
|
Chris@16
|
67 * This is used to feed in vectors with data stored as an ASCII representation
|
Chris@16
|
68 * from a standard input stream.
|
Chris@16
|
69 *
|
Chris@16
|
70 * From a file or any valid stream, the format is:
|
Chris@16
|
71 * \c [<vector size>](<data1>,<data2>,...<dataN>) like for example:
|
Chris@16
|
72 * \code
|
Chris@16
|
73 * [5](1,2.1,3.2,3.14,0.2)
|
Chris@16
|
74 * \endcode
|
Chris@16
|
75 *
|
Chris@16
|
76 * You can use it like this
|
Chris@16
|
77 * \code
|
Chris@16
|
78 * my_input_stream >> my_vector;
|
Chris@16
|
79 * \endcode
|
Chris@16
|
80 *
|
Chris@16
|
81 * You can only put data into a valid \c vector<> not a \c vector_expression
|
Chris@16
|
82 *
|
Chris@16
|
83 * \param is is a standard basic input stream
|
Chris@16
|
84 * \param v is a vector
|
Chris@16
|
85 * \return a reference to the resulting input stream
|
Chris@16
|
86 */
|
Chris@16
|
87 template<class E, class T, class VT, class VA>
|
Chris@16
|
88 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
|
Chris@16
|
89 std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
|
Chris@16
|
90 vector<VT, VA> &v) {
|
Chris@16
|
91 typedef typename vector<VT, VA>::size_type size_type;
|
Chris@16
|
92 E ch;
|
Chris@16
|
93 size_type size;
|
Chris@16
|
94 if (is >> ch && ch != '[') {
|
Chris@16
|
95 is.putback (ch);
|
Chris@16
|
96 is.setstate (std::ios_base::failbit);
|
Chris@16
|
97 } else if (is >> size >> ch && ch != ']') {
|
Chris@16
|
98 is.putback (ch);
|
Chris@16
|
99 is.setstate (std::ios_base::failbit);
|
Chris@16
|
100 } else if (! is.fail ()) {
|
Chris@16
|
101 vector<VT, VA> s (size);
|
Chris@16
|
102 if (is >> ch && ch != '(') {
|
Chris@16
|
103 is.putback (ch);
|
Chris@16
|
104 is.setstate (std::ios_base::failbit);
|
Chris@16
|
105 } else if (! is.fail ()) {
|
Chris@16
|
106 for (size_type i = 0; i < size; i ++) {
|
Chris@16
|
107 if (is >> s (i) >> ch && ch != ',') {
|
Chris@16
|
108 is.putback (ch);
|
Chris@16
|
109 if (i < size - 1)
|
Chris@16
|
110 is.setstate (std::ios_base::failbit);
|
Chris@16
|
111 break;
|
Chris@16
|
112 }
|
Chris@16
|
113 }
|
Chris@16
|
114 if (is >> ch && ch != ')') {
|
Chris@16
|
115 is.putback (ch);
|
Chris@16
|
116 is.setstate (std::ios_base::failbit);
|
Chris@16
|
117 }
|
Chris@16
|
118 }
|
Chris@16
|
119 if (! is.fail ())
|
Chris@16
|
120 v.swap (s);
|
Chris@16
|
121 }
|
Chris@16
|
122 return is;
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125 /** \brief output stream operator for matrix expressions
|
Chris@16
|
126 *
|
Chris@16
|
127 * it outpus the content of a \f$(M \times N)\f$ matrix to a standard output
|
Chris@16
|
128 * stream using the following format:
|
Chris@16
|
129 * \c[<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>))
|
Chris@16
|
130 *
|
Chris@16
|
131 * For example:
|
Chris@16
|
132 * \code
|
Chris@16
|
133 * matrix<float> m(3,3) = scalar_matrix<float>(3,3,1.0) - diagonal_matrix<float>(3,3,1.0);
|
Chris@16
|
134 * cout << m << endl;
|
Chris@16
|
135 * \encode
|
Chris@16
|
136 * will display
|
Chris@16
|
137 * \code
|
Chris@16
|
138 * [3,3]((0,1,1),(1,0,1),(1,1,0))
|
Chris@16
|
139 * \endcode
|
Chris@16
|
140 * This output is made for storing and retrieving matrices in a simple way but you can
|
Chris@16
|
141 * easily recognize the following:
|
Chris@16
|
142 * \f[ \left( \begin{array}{ccc} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{array} \right) - \left( \begin{array}{ccc} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{array} \right) = \left( \begin{array}{ccc} 0 & 1 & 1\\ 1 & 0 & 1\\ 1 & 1 & 0 \end{array} \right) \f]
|
Chris@16
|
143 *
|
Chris@16
|
144 * \param os is a standard basic output stream
|
Chris@16
|
145 * \param m is a matrix expression
|
Chris@16
|
146 * \return a reference to the resulting output stream
|
Chris@16
|
147 */
|
Chris@16
|
148 template<class E, class T, class ME>
|
Chris@16
|
149 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
|
Chris@16
|
150 std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os,
|
Chris@16
|
151 const matrix_expression<ME> &m) {
|
Chris@16
|
152 typedef typename ME::size_type size_type;
|
Chris@16
|
153 size_type size1 = m ().size1 ();
|
Chris@16
|
154 size_type size2 = m ().size2 ();
|
Chris@16
|
155 std::basic_ostringstream<E, T, std::allocator<E> > s;
|
Chris@16
|
156 s.flags (os.flags ());
|
Chris@16
|
157 s.imbue (os.getloc ());
|
Chris@16
|
158 s.precision (os.precision ());
|
Chris@16
|
159 s << '[' << size1 << ',' << size2 << "](";
|
Chris@16
|
160 if (size1 > 0) {
|
Chris@16
|
161 s << '(' ;
|
Chris@16
|
162 if (size2 > 0)
|
Chris@16
|
163 s << m () (0, 0);
|
Chris@16
|
164 for (size_type j = 1; j < size2; ++ j)
|
Chris@16
|
165 s << ',' << m () (0, j);
|
Chris@16
|
166 s << ')';
|
Chris@16
|
167 }
|
Chris@16
|
168 for (size_type i = 1; i < size1; ++ i) {
|
Chris@16
|
169 s << ",(" ;
|
Chris@16
|
170 if (size2 > 0)
|
Chris@16
|
171 s << m () (i, 0);
|
Chris@16
|
172 for (size_type j = 1; j < size2; ++ j)
|
Chris@16
|
173 s << ',' << m () (i, j);
|
Chris@16
|
174 s << ')';
|
Chris@16
|
175 }
|
Chris@16
|
176 s << ')';
|
Chris@16
|
177 return os << s.str ().c_str ();
|
Chris@16
|
178 }
|
Chris@16
|
179
|
Chris@16
|
180 /** \brief input stream operator for matrices
|
Chris@16
|
181 *
|
Chris@16
|
182 * This is used to feed in matrices with data stored as an ASCII representation
|
Chris@16
|
183 * from a standard input stream.
|
Chris@16
|
184 *
|
Chris@16
|
185 * From a file or any valid standard stream, the format is:
|
Chris@16
|
186 * \c[<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>))
|
Chris@16
|
187 *
|
Chris@16
|
188 * You can use it like this
|
Chris@16
|
189 * \code
|
Chris@16
|
190 * my_input_stream >> my_matrix;
|
Chris@16
|
191 * \endcode
|
Chris@16
|
192 *
|
Chris@16
|
193 * You can only put data into a valid \c matrix<> not a \c matrix_expression
|
Chris@16
|
194 *
|
Chris@16
|
195 * \param is is a standard basic input stream
|
Chris@16
|
196 * \param m is a matrix
|
Chris@16
|
197 * \return a reference to the resulting input stream
|
Chris@16
|
198 */
|
Chris@16
|
199 template<class E, class T, class MT, class MF, class MA>
|
Chris@16
|
200 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
|
Chris@16
|
201 std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
|
Chris@16
|
202 matrix<MT, MF, MA> &m) {
|
Chris@16
|
203 typedef typename matrix<MT, MF, MA>::size_type size_type;
|
Chris@16
|
204 E ch;
|
Chris@16
|
205 size_type size1, size2;
|
Chris@16
|
206 if (is >> ch && ch != '[') {
|
Chris@16
|
207 is.putback (ch);
|
Chris@16
|
208 is.setstate (std::ios_base::failbit);
|
Chris@16
|
209 } else if (is >> size1 >> ch && ch != ',') {
|
Chris@16
|
210 is.putback (ch);
|
Chris@16
|
211 is.setstate (std::ios_base::failbit);
|
Chris@16
|
212 } else if (is >> size2 >> ch && ch != ']') {
|
Chris@16
|
213 is.putback (ch);
|
Chris@16
|
214 is.setstate (std::ios_base::failbit);
|
Chris@16
|
215 } else if (! is.fail ()) {
|
Chris@16
|
216 matrix<MT, MF, MA> s (size1, size2);
|
Chris@16
|
217 if (is >> ch && ch != '(') {
|
Chris@16
|
218 is.putback (ch);
|
Chris@16
|
219 is.setstate (std::ios_base::failbit);
|
Chris@16
|
220 } else if (! is.fail ()) {
|
Chris@16
|
221 for (size_type i = 0; i < size1; i ++) {
|
Chris@16
|
222 if (is >> ch && ch != '(') {
|
Chris@16
|
223 is.putback (ch);
|
Chris@16
|
224 is.setstate (std::ios_base::failbit);
|
Chris@16
|
225 break;
|
Chris@16
|
226 }
|
Chris@16
|
227 for (size_type j = 0; j < size2; j ++) {
|
Chris@16
|
228 if (is >> s (i, j) >> ch && ch != ',') {
|
Chris@16
|
229 is.putback (ch);
|
Chris@16
|
230 if (j < size2 - 1) {
|
Chris@16
|
231 is.setstate (std::ios_base::failbit);
|
Chris@16
|
232 break;
|
Chris@16
|
233 }
|
Chris@16
|
234 }
|
Chris@16
|
235 }
|
Chris@16
|
236 if (is >> ch && ch != ')') {
|
Chris@16
|
237 is.putback (ch);
|
Chris@16
|
238 is.setstate (std::ios_base::failbit);
|
Chris@16
|
239 break;
|
Chris@16
|
240 }
|
Chris@16
|
241 if (is >> ch && ch != ',') {
|
Chris@16
|
242 is.putback (ch);
|
Chris@16
|
243 if (i < size1 - 1) {
|
Chris@16
|
244 is.setstate (std::ios_base::failbit);
|
Chris@16
|
245 break;
|
Chris@16
|
246 }
|
Chris@16
|
247 }
|
Chris@16
|
248 }
|
Chris@16
|
249 if (is >> ch && ch != ')') {
|
Chris@16
|
250 is.putback (ch);
|
Chris@16
|
251 is.setstate (std::ios_base::failbit);
|
Chris@16
|
252 }
|
Chris@16
|
253 }
|
Chris@16
|
254 if (! is.fail ())
|
Chris@16
|
255 m.swap (s);
|
Chris@16
|
256 }
|
Chris@16
|
257 return is;
|
Chris@16
|
258 }
|
Chris@16
|
259
|
Chris@16
|
260 /** \brief special input stream operator for symmetric matrices
|
Chris@16
|
261 *
|
Chris@16
|
262 * This is used to feed in symmetric matrices with data stored as an ASCII
|
Chris@16
|
263 * representation from a standard input stream.
|
Chris@16
|
264 *
|
Chris@16
|
265 * You can simply write your matrices in a file or any valid stream and read them again
|
Chris@16
|
266 * at a later time with this function. The format is the following:
|
Chris@16
|
267 * \code [<rows>,<columns>]((<m00>,<m01>,...,<m0N>),...,(<mM0>,<mM1>,...,<mMN>)) \endcode
|
Chris@16
|
268 *
|
Chris@16
|
269 * You can use it like this
|
Chris@16
|
270 * \code
|
Chris@16
|
271 * my_input_stream >> my_symmetric_matrix;
|
Chris@16
|
272 * \endcode
|
Chris@16
|
273 *
|
Chris@16
|
274 * You can only put data into a valid \c symmetric_matrix<>, not in a \c matrix_expression
|
Chris@16
|
275 * This function also checks that input data form a valid symmetric matrix
|
Chris@16
|
276 *
|
Chris@16
|
277 * \param is is a standard basic input stream
|
Chris@16
|
278 * \param m is a \c symmetric_matrix
|
Chris@16
|
279 * \return a reference to the resulting input stream
|
Chris@16
|
280 */
|
Chris@16
|
281 template<class E, class T, class MT, class MF1, class MF2, class MA>
|
Chris@16
|
282 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
|
Chris@16
|
283 std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is,
|
Chris@16
|
284 symmetric_matrix<MT, MF1, MF2, MA> &m) {
|
Chris@16
|
285 typedef typename symmetric_matrix<MT, MF1, MF2, MA>::size_type size_type;
|
Chris@16
|
286 E ch;
|
Chris@16
|
287 size_type size1, size2;
|
Chris@16
|
288 MT value;
|
Chris@16
|
289 if (is >> ch && ch != '[') {
|
Chris@16
|
290 is.putback (ch);
|
Chris@16
|
291 is.setstate (std::ios_base::failbit);
|
Chris@16
|
292 } else if (is >> size1 >> ch && ch != ',') {
|
Chris@16
|
293 is.putback (ch);
|
Chris@16
|
294 is.setstate (std::ios_base::failbit);
|
Chris@16
|
295 } else if (is >> size2 >> ch && (size2 != size1 || ch != ']')) { // symmetric matrix must be square
|
Chris@16
|
296 is.putback (ch);
|
Chris@16
|
297 is.setstate (std::ios_base::failbit);
|
Chris@16
|
298 } else if (! is.fail ()) {
|
Chris@16
|
299 symmetric_matrix<MT, MF1, MF2, MA> s (size1, size2);
|
Chris@16
|
300 if (is >> ch && ch != '(') {
|
Chris@16
|
301 is.putback (ch);
|
Chris@16
|
302 is.setstate (std::ios_base::failbit);
|
Chris@16
|
303 } else if (! is.fail ()) {
|
Chris@16
|
304 for (size_type i = 0; i < size1; i ++) {
|
Chris@16
|
305 if (is >> ch && ch != '(') {
|
Chris@16
|
306 is.putback (ch);
|
Chris@16
|
307 is.setstate (std::ios_base::failbit);
|
Chris@16
|
308 break;
|
Chris@16
|
309 }
|
Chris@16
|
310 for (size_type j = 0; j < size2; j ++) {
|
Chris@16
|
311 if (is >> value >> ch && ch != ',') {
|
Chris@16
|
312 is.putback (ch);
|
Chris@16
|
313 if (j < size2 - 1) {
|
Chris@16
|
314 is.setstate (std::ios_base::failbit);
|
Chris@16
|
315 break;
|
Chris@16
|
316 }
|
Chris@16
|
317 }
|
Chris@16
|
318 if (i <= j) {
|
Chris@16
|
319 // this is the first time we read this element - set the value
|
Chris@16
|
320 s(i,j) = value;
|
Chris@16
|
321 }
|
Chris@16
|
322 else if ( s(i,j) != value ) {
|
Chris@16
|
323 // matrix is not symmetric
|
Chris@16
|
324 is.setstate (std::ios_base::failbit);
|
Chris@16
|
325 break;
|
Chris@16
|
326 }
|
Chris@16
|
327 }
|
Chris@16
|
328 if (is >> ch && ch != ')') {
|
Chris@16
|
329 is.putback (ch);
|
Chris@16
|
330 is.setstate (std::ios_base::failbit);
|
Chris@16
|
331 break;
|
Chris@16
|
332 }
|
Chris@16
|
333 if (is >> ch && ch != ',') {
|
Chris@16
|
334 is.putback (ch);
|
Chris@16
|
335 if (i < size1 - 1) {
|
Chris@16
|
336 is.setstate (std::ios_base::failbit);
|
Chris@16
|
337 break;
|
Chris@16
|
338 }
|
Chris@16
|
339 }
|
Chris@16
|
340 }
|
Chris@16
|
341 if (is >> ch && ch != ')') {
|
Chris@16
|
342 is.putback (ch);
|
Chris@16
|
343 is.setstate (std::ios_base::failbit);
|
Chris@16
|
344 }
|
Chris@16
|
345 }
|
Chris@16
|
346 if (! is.fail ())
|
Chris@16
|
347 m.swap (s);
|
Chris@16
|
348 }
|
Chris@16
|
349 return is;
|
Chris@16
|
350 }
|
Chris@16
|
351
|
Chris@16
|
352
|
Chris@16
|
353 }}}
|
Chris@16
|
354
|
Chris@16
|
355 #endif
|