IO.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef EIGEN_IO_H
27 #define EIGEN_IO_H
28 
29 namespace Eigen {
30 
31 enum { DontAlignCols = 1 };
32 enum { StreamPrecision = -1,
33  FullPrecision = -2 };
34 
35 namespace internal {
36 template<typename Derived>
37 std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt);
38 }
39 
65 struct IOFormat
66 {
68  IOFormat(int _precision = StreamPrecision, int _flags = 0,
69  const std::string& _coeffSeparator = " ",
70  const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
71  const std::string& _matPrefix="", const std::string& _matSuffix="")
72  : matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
73  coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
74  {
75  rowSpacer = "";
76  int i = int(matSuffix.length())-1;
77  while (i>=0 && matSuffix[i]!='\n')
78  {
79  rowSpacer += ' ';
80  i--;
81  }
82  }
83  std::string matPrefix, matSuffix;
85  std::string coeffSeparator;
86  int precision;
87  int flags;
88 };
89 
105 template<typename ExpressionType>
107 {
108  public:
109 
110  WithFormat(const ExpressionType& matrix, const IOFormat& format)
111  : m_matrix(matrix), m_format(format)
112  {}
113 
114  friend std::ostream & operator << (std::ostream & s, const WithFormat& wf)
115  {
116  return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format);
117  }
118 
119  protected:
120  const typename ExpressionType::Nested m_matrix;
122 };
123 
131 template<typename Derived>
132 inline const WithFormat<Derived>
134 {
135  return WithFormat<Derived>(derived(), fmt);
136 }
137 
138 namespace internal {
139 
140 template<typename Scalar, bool IsInteger>
141 struct significant_decimals_default_impl
142 {
143  typedef typename NumTraits<Scalar>::Real RealScalar;
144  static inline int run()
145  {
146  using std::ceil;
147  return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
148  }
149 };
150 
151 template<typename Scalar>
152 struct significant_decimals_default_impl<Scalar, true>
153 {
154  static inline int run()
155  {
156  return 0;
157  }
158 };
159 
160 template<typename Scalar>
161 struct significant_decimals_impl
162  : significant_decimals_default_impl<Scalar, NumTraits<Scalar>::IsInteger>
163 {};
164 
167 template<typename Derived>
168 std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
169 {
170  if(_m.size() == 0)
171  {
172  s << fmt.matPrefix << fmt.matSuffix;
173  return s;
174  }
175 
176  typename Derived::Nested m = _m;
177  typedef typename Derived::Scalar Scalar;
178  typedef typename Derived::Index Index;
179 
180  Index width = 0;
181 
182  std::streamsize explicit_precision;
183  if(fmt.precision == StreamPrecision)
184  {
185  explicit_precision = 0;
186  }
187  else if(fmt.precision == FullPrecision)
188  {
190  {
191  explicit_precision = 0;
192  }
193  else
194  {
195  explicit_precision = significant_decimals_impl<Scalar>::run();
196  }
197  }
198  else
199  {
200  explicit_precision = fmt.precision;
201  }
202 
203  bool align_cols = !(fmt.flags & DontAlignCols);
204  if(align_cols)
205  {
206  // compute the largest width
207  for(Index j = 1; j < m.cols(); ++j)
208  for(Index i = 0; i < m.rows(); ++i)
209  {
210  std::stringstream sstr;
211  if(explicit_precision) sstr.precision(explicit_precision);
212  sstr << m.coeff(i,j);
213  width = std::max<Index>(width, Index(sstr.str().length()));
214  }
215  }
216  std::streamsize old_precision = 0;
217  if(explicit_precision) old_precision = s.precision(explicit_precision);
218  s << fmt.matPrefix;
219  for(Index i = 0; i < m.rows(); ++i)
220  {
221  if (i)
222  s << fmt.rowSpacer;
223  s << fmt.rowPrefix;
224  if(width) s.width(width);
225  s << m.coeff(i, 0);
226  for(Index j = 1; j < m.cols(); ++j)
227  {
228  s << fmt.coeffSeparator;
229  if (width) s.width(width);
230  s << m.coeff(i, j);
231  }
232  s << fmt.rowSuffix;
233  if( i < m.rows() - 1)
234  s << fmt.rowSeparator;
235  }
236  s << fmt.matSuffix;
237  if(explicit_precision) s.precision(old_precision);
238  return s;
239 }
240 
241 } // end namespace internal
242 
254 template<typename Derived>
255 std::ostream & operator <<
256 (std::ostream & s,
257  const DenseBase<Derived> & m)
258 {
259  return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT);
260 }
261 
262 } // end namespace Eigen
263 
264 #endif // EIGEN_IO_H