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 (at) gmail.com> 5 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_IO_H 12 #define EIGEN_IO_H 13 14 namespace Eigen { 15 16 enum { DontAlignCols = 1 }; 17 enum { StreamPrecision = -1, 18 FullPrecision = -2 }; 19 20 namespace internal { 21 template<typename Derived> 22 std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt); 23 } 24 25 /** \class IOFormat 26 * \ingroup Core_Module 27 * 28 * \brief Stores a set of parameters controlling the way matrices are printed 29 * 30 * List of available parameters: 31 * - \b precision number of digits for floating point values, or one of the special constants \c StreamPrecision and \c FullPrecision. 32 * The default is the special value \c StreamPrecision which means to use the 33 * stream's own precision setting, as set for instance using \c cout.precision(3). The other special value 34 * \c FullPrecision means that the number of digits will be computed to match the full precision of each floating-point 35 * type. 36 * - \b flags an OR-ed combination of flags, the default value is 0, the only currently available flag is \c DontAlignCols which 37 * allows to disable the alignment of columns, resulting in faster code. 38 * - \b coeffSeparator string printed between two coefficients of the same row 39 * - \b rowSeparator string printed between two rows 40 * - \b rowPrefix string printed at the beginning of each row 41 * - \b rowSuffix string printed at the end of each row 42 * - \b matPrefix string printed at the beginning of the matrix 43 * - \b matSuffix string printed at the end of the matrix 44 * 45 * Example: \include IOFormat.cpp 46 * Output: \verbinclude IOFormat.out 47 * 48 * \sa DenseBase::format(), class WithFormat 49 */ 50 struct IOFormat 51 { 52 /** Default contructor, see class IOFormat for the meaning of the parameters */ 53 IOFormat(int _precision = StreamPrecision, int _flags = 0, 54 const std::string& _coeffSeparator = " ", 55 const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="", 56 const std::string& _matPrefix="", const std::string& _matSuffix="") 57 : matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator), 58 coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags) 59 { 60 rowSpacer = ""; 61 int i = int(matSuffix.length())-1; 62 while (i>=0 && matSuffix[i]!='\n') 63 { 64 rowSpacer += ' '; 65 i--; 66 } 67 } 68 std::string matPrefix, matSuffix; 69 std::string rowPrefix, rowSuffix, rowSeparator, rowSpacer; 70 std::string coeffSeparator; 71 int precision; 72 int flags; 73 }; 74 75 /** \class WithFormat 76 * \ingroup Core_Module 77 * 78 * \brief Pseudo expression providing matrix output with given format 79 * 80 * \param ExpressionType the type of the object on which IO stream operations are performed 81 * 82 * This class represents an expression with stream operators controlled by a given IOFormat. 83 * It is the return type of DenseBase::format() 84 * and most of the time this is the only way it is used. 85 * 86 * See class IOFormat for some examples. 87 * 88 * \sa DenseBase::format(), class IOFormat 89 */ 90 template<typename ExpressionType> 91 class WithFormat 92 { 93 public: 94 95 WithFormat(const ExpressionType& matrix, const IOFormat& format) 96 : m_matrix(matrix), m_format(format) 97 {} 98 99 friend std::ostream & operator << (std::ostream & s, const WithFormat& wf) 100 { 101 return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format); 102 } 103 104 protected: 105 const typename ExpressionType::Nested m_matrix; 106 IOFormat m_format; 107 }; 108 109 /** \returns a WithFormat proxy object allowing to print a matrix the with given 110 * format \a fmt. 111 * 112 * See class IOFormat for some examples. 113 * 114 * \sa class IOFormat, class WithFormat 115 */ 116 template<typename Derived> 117 inline const WithFormat<Derived> 118 DenseBase<Derived>::format(const IOFormat& fmt) const 119 { 120 return WithFormat<Derived>(derived(), fmt); 121 } 122 123 namespace internal { 124 125 template<typename Scalar, bool IsInteger> 126 struct significant_decimals_default_impl 127 { 128 typedef typename NumTraits<Scalar>::Real RealScalar; 129 static inline int run() 130 { 131 using std::ceil; 132 return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10)))); 133 } 134 }; 135 136 template<typename Scalar> 137 struct significant_decimals_default_impl<Scalar, true> 138 { 139 static inline int run() 140 { 141 return 0; 142 } 143 }; 144 145 template<typename Scalar> 146 struct significant_decimals_impl 147 : significant_decimals_default_impl<Scalar, NumTraits<Scalar>::IsInteger> 148 {}; 149 150 /** \internal 151 * print the matrix \a _m to the output stream \a s using the output format \a fmt */ 152 template<typename Derived> 153 std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt) 154 { 155 if(_m.size() == 0) 156 { 157 s << fmt.matPrefix << fmt.matSuffix; 158 return s; 159 } 160 161 typename Derived::Nested m = _m; 162 typedef typename Derived::Scalar Scalar; 163 typedef typename Derived::Index Index; 164 165 Index width = 0; 166 167 std::streamsize explicit_precision; 168 if(fmt.precision == StreamPrecision) 169 { 170 explicit_precision = 0; 171 } 172 else if(fmt.precision == FullPrecision) 173 { 174 if (NumTraits<Scalar>::IsInteger) 175 { 176 explicit_precision = 0; 177 } 178 else 179 { 180 explicit_precision = significant_decimals_impl<Scalar>::run(); 181 } 182 } 183 else 184 { 185 explicit_precision = fmt.precision; 186 } 187 188 bool align_cols = !(fmt.flags & DontAlignCols); 189 if(align_cols) 190 { 191 // compute the largest width 192 for(Index j = 1; j < m.cols(); ++j) 193 for(Index i = 0; i < m.rows(); ++i) 194 { 195 std::stringstream sstr; 196 if(explicit_precision) sstr.precision(explicit_precision); 197 sstr << m.coeff(i,j); 198 width = std::max<Index>(width, Index(sstr.str().length())); 199 } 200 } 201 std::streamsize old_precision = 0; 202 if(explicit_precision) old_precision = s.precision(explicit_precision); 203 s << fmt.matPrefix; 204 for(Index i = 0; i < m.rows(); ++i) 205 { 206 if (i) 207 s << fmt.rowSpacer; 208 s << fmt.rowPrefix; 209 if(width) s.width(width); 210 s << m.coeff(i, 0); 211 for(Index j = 1; j < m.cols(); ++j) 212 { 213 s << fmt.coeffSeparator; 214 if (width) s.width(width); 215 s << m.coeff(i, j); 216 } 217 s << fmt.rowSuffix; 218 if( i < m.rows() - 1) 219 s << fmt.rowSeparator; 220 } 221 s << fmt.matSuffix; 222 if(explicit_precision) s.precision(old_precision); 223 return s; 224 } 225 226 } // end namespace internal 227 228 /** \relates DenseBase 229 * 230 * Outputs the matrix, to the given stream. 231 * 232 * If you wish to print the matrix with a format different than the default, use DenseBase::format(). 233 * 234 * It is also possible to change the default format by defining EIGEN_DEFAULT_IO_FORMAT before including Eigen headers. 235 * If not defined, this will automatically be defined to Eigen::IOFormat(), that is the Eigen::IOFormat with default parameters. 236 * 237 * \sa DenseBase::format() 238 */ 239 template<typename Derived> 240 std::ostream & operator << 241 (std::ostream & s, 242 const DenseBase<Derived> & m) 243 { 244 return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT); 245 } 246 247 } // end namespace Eigen 248 249 #endif // EIGEN_IO_H 250