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 rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags) 59 { 60 int i = int(matSuffix.length())-1; 61 while (i>=0 && matSuffix[i]!='\n') 62 { 63 rowSpacer += ' '; 64 i--; 65 } 66 } 67 std::string matPrefix, matSuffix; 68 std::string rowPrefix, rowSuffix, rowSeparator, rowSpacer; 69 std::string coeffSeparator; 70 int precision; 71 int flags; 72 }; 73 74 /** \class WithFormat 75 * \ingroup Core_Module 76 * 77 * \brief Pseudo expression providing matrix output with given format 78 * 79 * \param ExpressionType the type of the object on which IO stream operations are performed 80 * 81 * This class represents an expression with stream operators controlled by a given IOFormat. 82 * It is the return type of DenseBase::format() 83 * and most of the time this is the only way it is used. 84 * 85 * See class IOFormat for some examples. 86 * 87 * \sa DenseBase::format(), class IOFormat 88 */ 89 template<typename ExpressionType> 90 class WithFormat 91 { 92 public: 93 94 WithFormat(const ExpressionType& matrix, const IOFormat& format) 95 : m_matrix(matrix), m_format(format) 96 {} 97 98 friend std::ostream & operator << (std::ostream & s, const WithFormat& wf) 99 { 100 return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format); 101 } 102 103 protected: 104 const typename ExpressionType::Nested m_matrix; 105 IOFormat m_format; 106 }; 107 108 /** \returns a WithFormat proxy object allowing to print a matrix the with given 109 * format \a fmt. 110 * 111 * See class IOFormat for some examples. 112 * 113 * \sa class IOFormat, class WithFormat 114 */ 115 template<typename Derived> 116 inline const WithFormat<Derived> 117 DenseBase<Derived>::format(const IOFormat& fmt) const 118 { 119 return WithFormat<Derived>(derived(), fmt); 120 } 121 122 namespace internal { 123 124 template<typename Scalar, bool IsInteger> 125 struct significant_decimals_default_impl 126 { 127 typedef typename NumTraits<Scalar>::Real RealScalar; 128 static inline int run() 129 { 130 using std::ceil; 131 using std::log; 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 std::streamsize old_precision = 0; 189 if(explicit_precision) old_precision = s.precision(explicit_precision); 190 191 bool align_cols = !(fmt.flags & DontAlignCols); 192 if(align_cols) 193 { 194 // compute the largest width 195 for(Index j = 0; j < m.cols(); ++j) 196 for(Index i = 0; i < m.rows(); ++i) 197 { 198 std::stringstream sstr; 199 sstr.copyfmt(s); 200 sstr << m.coeff(i,j); 201 width = std::max<Index>(width, Index(sstr.str().length())); 202 } 203 } 204 s << fmt.matPrefix; 205 for(Index i = 0; i < m.rows(); ++i) 206 { 207 if (i) 208 s << fmt.rowSpacer; 209 s << fmt.rowPrefix; 210 if(width) s.width(width); 211 s << m.coeff(i, 0); 212 for(Index j = 1; j < m.cols(); ++j) 213 { 214 s << fmt.coeffSeparator; 215 if (width) s.width(width); 216 s << m.coeff(i, j); 217 } 218 s << fmt.rowSuffix; 219 if( i < m.rows() - 1) 220 s << fmt.rowSeparator; 221 } 222 s << fmt.matSuffix; 223 if(explicit_precision) s.precision(old_precision); 224 return s; 225 } 226 227 } // end namespace internal 228 229 /** \relates DenseBase 230 * 231 * Outputs the matrix, to the given stream. 232 * 233 * If you wish to print the matrix with a format different than the default, use DenseBase::format(). 234 * 235 * It is also possible to change the default format by defining EIGEN_DEFAULT_IO_FORMAT before including Eigen headers. 236 * If not defined, this will automatically be defined to Eigen::IOFormat(), that is the Eigen::IOFormat with default parameters. 237 * 238 * \sa DenseBase::format() 239 */ 240 template<typename Derived> 241 std::ostream & operator << 242 (std::ostream & s, 243 const DenseBase<Derived> & m) 244 { 245 return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT); 246 } 247 248 } // end namespace Eigen 249 250 #endif // EIGEN_IO_H 251