Quantum++  v0.7
C++11 quantum computing library
iomanip.h
Go to the documentation of this file.
1 /*
2  * Quantum++
3  *
4  * Copyright (c) 2013 - 2015 Vlad Gheorghiu (vgheorgh@gmail.com)
5  *
6  * This file is part of Quantum++.
7  *
8  * Quantum++ is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Quantum++ is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Quantum++. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
27 #ifndef INTERNAL_CLASSES_IOMANIP_H_
28 #define INTERNAL_CLASSES_IOMANIP_H_
29 
30 // ostream manipulators for nice formatting of
31 // Eigen matrices and STL/C-style containers/vectors
32 
33 namespace qpp
34 {
35 namespace internal
36 {
37 
38 template<typename InputIterator>
40 {
41  InputIterator _first, _last;
42  std::string _separator, _start, _end;
43 public:
44  explicit IOManipRange(InputIterator first, InputIterator last,
45  const std::string& separator,
46  const std::string& start = "[",
47  const std::string& end = "]") :
48  _first{first},
49  _last{last},
50  _separator{separator},
51  _start{start},
52  _end{end}
53  {
54  }
55 
56  template<typename charT, typename traits>
57  friend std::basic_ostream<charT, traits>&
58  operator<<(std::basic_ostream<charT, traits>& os, const IOManipRange& rhs)
59  {
60  os << rhs._start;
61 
62  bool first = true;
63  for (auto it = rhs._first; it != rhs._last; ++it)
64  {
65  if (!first)
66  os << rhs._separator;
67  first = false;
68  os << *it;
69  }
70  os << rhs._end;
71 
72  return os;
73  }
74 }; // class IOManipRange
75 
76 template<typename PointerType>
78 {
79  const PointerType* _p;
80  idx _n;
81  std::string _separator, _start, _end;
82 public:
83  explicit IOManipPointer(const PointerType* p, const idx n,
84  const std::string& separator,
85  const std::string& start = "[",
86  const std::string& end = "]") :
87  _p{p},
88  _n{n},
89  _separator{separator},
90  _start{start},
91  _end{end}
92  {
93  }
94 
95  // to silence -Weffc++ warnings
96  IOManipPointer(const IOManipPointer&) = default;
97 
98  IOManipPointer& operator=(const IOManipPointer&) = default;
99 
100  template<typename charT, typename traits>
101  friend std::basic_ostream<charT, traits>&
102  operator<<(std::basic_ostream<charT, traits>& os,
103  const IOManipPointer& rhs)
104  {
105  os << rhs._start;
106 
107  for (idx i = 0; i < rhs._n - 1; ++i)
108  os << rhs._p[i] << rhs._separator;
109  if (rhs._n > 0)
110  os << rhs._p[rhs._n - 1];
111 
112  os << rhs._end;
113 
114  return os;
115  }
116 }; // class IOManipPointer
117 
119 {
120  cmat _A;
121  double _chop;
122 public:
123  // Eigen matrices
124  template<typename Derived>
125  explicit IOManipEigen(const Eigen::MatrixBase<Derived>& A, double chop =
126  qpp::chop) :
127  _A{A.template cast<cplx>()}, _chop{chop}
128  {
129  }
130 
131  // Complex numbers
132  explicit IOManipEigen(const cplx z, double chop = qpp::chop) :
133  _A{cmat::Zero(1, 1)}, _chop{chop}
134  {
135  // put the complex number inside an Eigen matrix
136  _A(0, 0) = z;
137  }
138 
139  template<typename charT, typename traits>
140  friend std::basic_ostream<charT, traits>&
141  operator<<(std::basic_ostream<charT, traits>& os, const IOManipEigen& rhs)
142  {
143  if (!internal::_check_nonzero_size(rhs._A))
144  {
145  os << "Empty [" << rhs._A.rows() << " x "
146  << rhs._A.cols() << "] matrix";
147 
148  return os;
149  };
150 
151  std::ostringstream ostr;
152  ostr.copyfmt(os); // copy os' state
153 
154  std::vector<std::string> vstr;
155  std::string strA;
156 
157  for (idx i = 0; i < static_cast<idx>(rhs._A.rows());
158  ++i)
159  {
160  for (idx j = 0;
161  j < static_cast<idx>(rhs._A.cols()); ++j)
162  {
163  strA.clear(); // clear the temporary string
164  ostr.clear();
165  ostr.str(std::string {}); // clear the ostringstream
166 
167  // convert to complex
168  double re = static_cast<cplx>(rhs._A(i, j)).real();
169  double im = static_cast<cplx>(rhs._A(i, j)).imag();
170 
171  if (std::abs(re) < rhs._chop && std::abs(im) < rhs._chop)
172  {
173  ostr << "0 "; // otherwise segfault on destruction
174  // if using only vstr.push_back("0 ");
175  // bug in MATLAB libmx
176  vstr.push_back(ostr.str());
177  }
178  else if (std::abs(re) < rhs._chop)
179  {
180  ostr << im;
181  vstr.push_back(ostr.str() + "i");
182  }
183  else if (std::abs(im) < rhs._chop)
184  {
185  ostr << re;
186  vstr.push_back(ostr.str() + " ");
187  }
188  else
189  {
190  ostr << re;
191  strA = ostr.str();
192 
193  strA += (im > 0 ? " + " : " - ");
194  ostr.clear();
195  ostr.str(std::string()); // clear
196  ostr << std::abs(im);
197  strA += ostr.str();
198  strA += "i";
199  vstr.push_back(strA);
200  }
201  }
202  }
203 
204  // determine the maximum lenght of the entries in each column
205  std::vector<idx> maxlengthcols(rhs._A.cols(), 0);
206 
207  for (idx i = 0; i < static_cast<idx>(rhs._A.rows());
208  ++i)
209  for (idx j = 0;
210  j < static_cast<idx>(rhs._A.cols()); ++j)
211  if (vstr[i * rhs._A.cols() + j].size() > maxlengthcols[j])
212  maxlengthcols[j] = vstr[i * rhs._A.cols() + j].size();
213 
214  // finally display it!
215  for (idx i = 0; i < static_cast<idx>(rhs._A.rows());
216  ++i)
217  {
218  os << std::setw(static_cast<int>(maxlengthcols[0])) << std::right
219  << vstr[i * rhs._A.cols()]; // display first column
220  // then the rest
221  for (idx j = 1;
222  j < static_cast<idx>(rhs._A.cols()); ++j)
223  os << std::setw(static_cast<int>(maxlengthcols[j] + 2))
224  << std::right << vstr[i * rhs._A.cols() + j];
225 
226  if (i < static_cast<idx>(rhs._A.rows()) - 1)
227  os << std::endl;
228  }
229 
230  return os;
231  }
232 }; // class IOManipEigen
233 
234 } /* namespace internal */
235 } /* namespace qpp */
236 
237 #endif /* INTERNAL_CLASSES_IOMANIP_H_ */
constexpr double chop
Used in qpp::disp() for setting to zero numbers that have their absolute value smaller than qpp::chop...
Definition: constants.h:67
IOManipEigen(const Eigen::MatrixBase< Derived > &A, double chop=qpp::chop)
Definition: iomanip.h:125
Definition: iomanip.h:39
IOManipPointer & operator=(const IOManipPointer &)=default
Quantum++ main namespace.
Definition: codes.h:30
Definition: iomanip.h:118
std::complex< double > cplx
Complex number in double precision.
Definition: types.h:41
IOManipRange(InputIterator first, InputIterator last, const std::string &separator, const std::string &start="[", const std::string &end="]")
Definition: iomanip.h:44
IOManipPointer(const PointerType *p, const idx n, const std::string &separator, const std::string &start="[", const std::string &end="]")
Definition: iomanip.h:83
bool _check_nonzero_size(const T &x) noexcept
Definition: util.h:119
IOManipEigen(const cplx z, double chop=qpp::chop)
Definition: iomanip.h:132
Definition: iomanip.h:77
Eigen::MatrixXcd cmat
Complex (double precision) dynamic Eigen matrix.
Definition: types.h:56
std::size_t idx
Non-negative integer index.
Definition: types.h:36