IO.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. // 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. #ifndef EIGEN_IO_H
  11. #define EIGEN_IO_H
  12. namespace Eigen {
  13. enum { DontAlignCols = 1 };
  14. enum { StreamPrecision = -1,
  15. FullPrecision = -2 };
  16. namespace internal {
  17. template<typename Derived>
  18. std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt);
  19. }
  20. /** \class IOFormat
  21. * \ingroup Core_Module
  22. *
  23. * \brief Stores a set of parameters controlling the way matrices are printed
  24. *
  25. * List of available parameters:
  26. * - \b precision number of digits for floating point values, or one of the special constants \c StreamPrecision and \c FullPrecision.
  27. * The default is the special value \c StreamPrecision which means to use the
  28. * stream's own precision setting, as set for instance using \c cout.precision(3). The other special value
  29. * \c FullPrecision means that the number of digits will be computed to match the full precision of each floating-point
  30. * type.
  31. * - \b flags an OR-ed combination of flags, the default value is 0, the only currently available flag is \c DontAlignCols which
  32. * allows to disable the alignment of columns, resulting in faster code.
  33. * - \b coeffSeparator string printed between two coefficients of the same row
  34. * - \b rowSeparator string printed between two rows
  35. * - \b rowPrefix string printed at the beginning of each row
  36. * - \b rowSuffix string printed at the end of each row
  37. * - \b matPrefix string printed at the beginning of the matrix
  38. * - \b matSuffix string printed at the end of the matrix
  39. *
  40. * Example: \include IOFormat.cpp
  41. * Output: \verbinclude IOFormat.out
  42. *
  43. * \sa DenseBase::format(), class WithFormat
  44. */
  45. struct IOFormat
  46. {
  47. /** Default constructor, see class IOFormat for the meaning of the parameters */
  48. IOFormat(int _precision = StreamPrecision, int _flags = 0,
  49. const std::string& _coeffSeparator = " ",
  50. const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
  51. const std::string& _matPrefix="", const std::string& _matSuffix="")
  52. : matPrefix(_matPrefix), matSuffix(_matSuffix), rowPrefix(_rowPrefix), rowSuffix(_rowSuffix), rowSeparator(_rowSeparator),
  53. rowSpacer(""), coeffSeparator(_coeffSeparator), precision(_precision), flags(_flags)
  54. {
  55. // TODO check if rowPrefix, rowSuffix or rowSeparator contains a newline
  56. // don't add rowSpacer if columns are not to be aligned
  57. if((flags & DontAlignCols))
  58. return;
  59. int i = int(matSuffix.length())-1;
  60. while (i>=0 && matSuffix[i]!='\n')
  61. {
  62. rowSpacer += ' ';
  63. i--;
  64. }
  65. }
  66. std::string matPrefix, matSuffix;
  67. std::string rowPrefix, rowSuffix, rowSeparator, rowSpacer;
  68. std::string coeffSeparator;
  69. int precision;
  70. int flags;
  71. };
  72. /** \class WithFormat
  73. * \ingroup Core_Module
  74. *
  75. * \brief Pseudo expression providing matrix output with given format
  76. *
  77. * \tparam ExpressionType the type of the object on which IO stream operations are performed
  78. *
  79. * This class represents an expression with stream operators controlled by a given IOFormat.
  80. * It is the return type of DenseBase::format()
  81. * and most of the time this is the only way it is used.
  82. *
  83. * See class IOFormat for some examples.
  84. *
  85. * \sa DenseBase::format(), class IOFormat
  86. */
  87. template<typename ExpressionType>
  88. class WithFormat
  89. {
  90. public:
  91. WithFormat(const ExpressionType& matrix, const IOFormat& format)
  92. : m_matrix(matrix), m_format(format)
  93. {}
  94. friend std::ostream & operator << (std::ostream & s, const WithFormat& wf)
  95. {
  96. return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format);
  97. }
  98. protected:
  99. typename ExpressionType::Nested m_matrix;
  100. IOFormat m_format;
  101. };
  102. namespace internal {
  103. // NOTE: This helper is kept for backward compatibility with previous code specializing
  104. // this internal::significant_decimals_impl structure. In the future we should directly
  105. // call digits10() which has been introduced in July 2016 in 3.3.
  106. template<typename Scalar>
  107. struct significant_decimals_impl
  108. {
  109. static inline int run()
  110. {
  111. return NumTraits<Scalar>::digits10();
  112. }
  113. };
  114. /** \internal
  115. * print the matrix \a _m to the output stream \a s using the output format \a fmt */
  116. template<typename Derived>
  117. std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
  118. {
  119. if(_m.size() == 0)
  120. {
  121. s << fmt.matPrefix << fmt.matSuffix;
  122. return s;
  123. }
  124. typename Derived::Nested m = _m;
  125. typedef typename Derived::Scalar Scalar;
  126. Index width = 0;
  127. std::streamsize explicit_precision;
  128. if(fmt.precision == StreamPrecision)
  129. {
  130. explicit_precision = 0;
  131. }
  132. else if(fmt.precision == FullPrecision)
  133. {
  134. if (NumTraits<Scalar>::IsInteger)
  135. {
  136. explicit_precision = 0;
  137. }
  138. else
  139. {
  140. explicit_precision = significant_decimals_impl<Scalar>::run();
  141. }
  142. }
  143. else
  144. {
  145. explicit_precision = fmt.precision;
  146. }
  147. std::streamsize old_precision = 0;
  148. if(explicit_precision) old_precision = s.precision(explicit_precision);
  149. bool align_cols = !(fmt.flags & DontAlignCols);
  150. if(align_cols)
  151. {
  152. // compute the largest width
  153. for(Index j = 0; j < m.cols(); ++j)
  154. for(Index i = 0; i < m.rows(); ++i)
  155. {
  156. std::stringstream sstr;
  157. sstr.copyfmt(s);
  158. sstr << m.coeff(i,j);
  159. width = std::max<Index>(width, Index(sstr.str().length()));
  160. }
  161. }
  162. s << fmt.matPrefix;
  163. for(Index i = 0; i < m.rows(); ++i)
  164. {
  165. if (i)
  166. s << fmt.rowSpacer;
  167. s << fmt.rowPrefix;
  168. if(width) s.width(width);
  169. s << m.coeff(i, 0);
  170. for(Index j = 1; j < m.cols(); ++j)
  171. {
  172. s << fmt.coeffSeparator;
  173. if (width) s.width(width);
  174. s << m.coeff(i, j);
  175. }
  176. s << fmt.rowSuffix;
  177. if( i < m.rows() - 1)
  178. s << fmt.rowSeparator;
  179. }
  180. s << fmt.matSuffix;
  181. if(explicit_precision) s.precision(old_precision);
  182. return s;
  183. }
  184. } // end namespace internal
  185. /** \relates DenseBase
  186. *
  187. * Outputs the matrix, to the given stream.
  188. *
  189. * If you wish to print the matrix with a format different than the default, use DenseBase::format().
  190. *
  191. * It is also possible to change the default format by defining EIGEN_DEFAULT_IO_FORMAT before including Eigen headers.
  192. * If not defined, this will automatically be defined to Eigen::IOFormat(), that is the Eigen::IOFormat with default parameters.
  193. *
  194. * \sa DenseBase::format()
  195. */
  196. template<typename Derived>
  197. std::ostream & operator <<
  198. (std::ostream & s,
  199. const DenseBase<Derived> & m)
  200. {
  201. return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT);
  202. }
  203. } // end namespace Eigen
  204. #endif // EIGEN_IO_H