Tomographer  v5.2
Tomographer C++ Framework Documentation
eigenutil.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHER_TOOLS_EIGENUTIL_H
29 #define TOMOGRAPHER_TOOLS_EIGENUTIL_H
30 
38 #include <complex>
39 #include <vector>
40 
41 #include <Eigen/Core>
42 #include <Eigen/Dense>
43 #include <Eigen/StdVector>
44 
45 
46 
47 
48 
49 // -----------------------------------------------------------------------------
50 // Eigen and std::vector
51 // -----------------------------------------------------------------------------
52 
53 namespace Tomographer {
54 namespace Tools {
55 
70 template<typename EigenType>
72 {
74 };
75 
76 } // namespace Tools
77 } // namespace Tomographer
78 
79 // -----------------------------------------------------------------------------
80 // Random matrices in Eigen
81 // -----------------------------------------------------------------------------
82 
83 namespace Tomographer {
84 namespace Tools {
85 
86 namespace tomo_internal {
87 
88  template<typename Rng, typename RndDist, typename Scalar>
89  struct random_generator
90  {
91  typedef Scalar result_type;
92 
93  Rng & rng;
94  RndDist & rnddist;
95 
96  random_generator(Rng & rng_, RndDist & rnddist_)
97  : rng(rng_), rnddist(rnddist_)
98  {
99  }
100 
101  template<typename Index>
102  inline const result_type operator() (Index, Index = 0) const {
103  return rnddist(rng);
104  }
105  };
106 
107  template<typename Rng, typename RndDist, typename RealScalar>
108  struct random_generator<Rng, RndDist, std::complex<RealScalar> >
109  {
110  typedef std::complex<RealScalar> result_type;
111 
112  Rng & rng;
113  RndDist & rnddist;
114 
115  random_generator(Rng & rng_, RndDist & rnddist_)
116  : rng(rng_), rnddist(rnddist_)
117  {
118  }
119 
120  template<typename Index>
121  inline const result_type operator() (Index, Index = 0) const {
122  return result_type(rnddist(rng), rnddist(rng));
123  }
124  };
125 } // end namespace tomo_internal
126 
127 } // namespace Tools
128 } // namespace Tomographer
129 
130 namespace Eigen {
131  namespace internal {
133  template<typename Rng, typename RndDist, typename Scalar>
134  struct functor_traits<Tomographer::Tools::tomo_internal::random_generator<Rng, RndDist, Scalar> >
135  { enum { Cost = 50 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; };
136  }
137 } // end namespace Eigen
138 
139 
140 namespace Tomographer {
141 namespace Tools {
142 
143 
152 template<typename Der, typename Rng, typename RndDist, typename... IndexTypes>
153 inline auto denseRandom(Rng & rng, RndDist &rnddist, IndexTypes... sizes)
154  -> const Eigen::CwiseNullaryOp<
155  tomo_internal::random_generator<Rng, RndDist, typename Eigen::internal::traits<Der>::Scalar>,
156  Der
157  >
158 {
159  typedef typename Der::Scalar Scalar;
160 
162  sizes..., tomo_internal::random_generator<Rng, RndDist, Scalar>(rng, rnddist)
163  );
164 }
165 
166 
167 
168 // ---------------------------
169 
170 
171 
172 namespace tomo_internal {
174  template<typename Scalar, typename IndexType>
175  struct can_basis_vec_generator
176  {
177  typedef Scalar result_type;
178 
179  const IndexType k;
180  const IndexType j;
181 
182  can_basis_vec_generator(IndexType k_, IndexType j_ = 0)
183  : k(k_), j(j_)
184  {
185  }
186 
187  inline const result_type operator() (IndexType a, IndexType b = 0) const {
188  return (a == k) && (b == j) ? result_type(1) : result_type(0);
189  }
190  };
191 } // namespace tomo_internal
192 } // namespace Tools
193 } // namespace Tomographer
194 namespace Eigen {
195  namespace internal {
197  template<typename Scalar, typename IndexType>
198  struct functor_traits<Tomographer::Tools::tomo_internal::can_basis_vec_generator<Scalar, IndexType> >
199  { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = true }; };
200  template<typename Scalar, typename IndexType>
201  struct functor_has_linear_access<Tomographer::Tools::tomo_internal::can_basis_vec_generator<Scalar, IndexType> >
202  { enum { ret = 0 }; };
203  }
204 } // end namespace Eigen
205 
206 namespace Tomographer {
207 namespace Tools {
208 
212 template<typename Der, typename IndexType>
213 inline auto canonicalBasisVec(IndexType k, IndexType size)
214  -> const Eigen::CwiseNullaryOp<
215  tomo_internal::can_basis_vec_generator<typename Eigen::internal::traits<Der>::Scalar, IndexType>,
216  Der
217  >
218 {
219  typedef typename Der::Scalar Scalar;
220 
222  size, tomo_internal::can_basis_vec_generator<Scalar, IndexType>(k)
223  );
224 }
225 
230 template<typename Der, typename IndexType>
231 inline auto canonicalBasisVec(IndexType k, IndexType j, IndexType rows, IndexType cols)
232  -> const Eigen::CwiseNullaryOp<
233  tomo_internal::can_basis_vec_generator<typename Eigen::internal::traits<Der>::Scalar, IndexType>,
234  Der
235  >
236 {
237  typedef typename Der::Scalar Scalar;
238 
240  rows, cols, tomo_internal::can_basis_vec_generator<Scalar, IndexType>(k, j)
241  );
242 }
243 
244 
245 
246 
247 // ---------------------------
248 
249 
250 
251 namespace tomo_internal {
253  template<typename Scalar>
254  struct powers_of_two_generator
255  {
256  typedef typename Eigen::NumTraits<Scalar>::Real result_type;
257 
258  powers_of_two_generator() { }
259 
260  template<typename IndexType>
261  inline const result_type operator() (IndexType a) const {
262  return std::ldexp(result_type(1), (int)a);
263  }
264 
265  // Don't expose an operator()(i,j) method, because otherwise Eigen might think that we
266  // don't have linear access
267  // https://eigen.tuxfamily.org/dox/NullaryFunctors_8h_source.html#l00147
268  //
269  // template<typename IndexType>
270  // inline const result_type operator() (IndexType a, IndexType b) const {
271  // eigen_assert(b == 0 && "powers_of_two_generator may only be used with 1-D objects or with linear access!");
272  // (void)b; // silence unused variable warning if eigen_assert is optimized out
273  // return std::ldexp(result_type(1), a);
274  // }
275 
276  };
277 } // namespace tomo_internal
278 } // namespace Tools
279 } // namespace Tomographer
280 namespace Eigen {
281  namespace internal {
283  template<typename Scalar>
284  struct functor_traits<Tomographer::Tools::tomo_internal::powers_of_two_generator<Scalar> >
285  { enum { Cost = 8 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = true }; };
286  }
287 } // end namespace Eigen
288 
289 namespace Tomographer {
290 namespace Tools {
291 
292 
305 template<typename Der, typename... IndexTypes>
306 inline auto powersOfTwo(IndexTypes... sizes)
307  -> const Eigen::CwiseNullaryOp<
308  tomo_internal::powers_of_two_generator<typename Eigen::internal::traits<Der>::Scalar>,
309  Der
310  >
311 {
312  typedef typename Der::Scalar Scalar;
313 
315  sizes..., tomo_internal::powers_of_two_generator<Scalar>()
316  );
317 }
318 
319 
320 
321 
322 
323 // -----------------------------------------------------------------------------
324 
340 template<int RowFactorCTime, int ColFactorCTime, typename Derived,
341  typename std::enable_if<(RowFactorCTime == Eigen::Dynamic || ColFactorCTime == Eigen::Dynamic),
342  bool>::type dummy = true>
343 inline auto replicated(const Eigen::DenseBase<Derived> & x, int row_factor, int col_factor)
345 {
346  eigen_assert(RowFactorCTime == Eigen::Dynamic || row_factor == RowFactorCTime);
347  eigen_assert(ColFactorCTime == Eigen::Dynamic || col_factor == ColFactorCTime);
348  return x.replicate(row_factor, col_factor);
349 }
354 template<int RowFactorCTime, int ColFactorCTime, typename Derived,
355  typename std::enable_if<(RowFactorCTime != Eigen::Dynamic && ColFactorCTime != Eigen::Dynamic),
356  bool>::type dummy2 = true>
357 inline auto replicated(const Eigen::DenseBase<Derived> & x, int row_factor, int col_factor)
359 {
360  eigen_assert(row_factor == RowFactorCTime); (void)row_factor; // "unused argument" warning
361  eigen_assert(col_factor == ColFactorCTime); (void)col_factor; // "unused argument" warning
362  return x.template replicate<RowFactorCTime, ColFactorCTime>();
363 }
364 
365 
366 
367 
368 } // namespace Tools
369 } // namespace Tomographer
370 
371 
372 
373 
374 #endif
auto canonicalBasisVec(IndexType k, IndexType size) -> const Eigen::CwiseNullaryOp< tomo_internal::can_basis_vec_generator< typename Eigen::internal::traits< Der >::Scalar, IndexType >, Der >
Expression for the k-th canonical basis vector of given dimension.
Definition: eigenutil.h:213
static const CwiseNullaryOp< CustomNullaryOp, Derived > NullaryExpr(Index rows, Index cols, const CustomNullaryOp &func)
Base namespace for the Tomographer project.
Definition: densellh.h:45
STL class.
Use this if you need an std::vector of any Eigen type.
Definition: eigenutil.h:71
T ldexp(T... args)
auto powersOfTwo(IndexTypes... sizes) -> const Eigen::CwiseNullaryOp< tomo_internal::powers_of_two_generator< typename Eigen::internal::traits< Der >::Scalar >, Der >
Expression for a 1-D expression of powers of two.
Definition: eigenutil.h:306
auto replicated(const Eigen::DenseBase< Derived > &x, int row_factor, int col_factor) -> const Eigen::Replicate< Derived, Eigen::Dynamic, Eigen::Dynamic >
Replicate a Eigen Dense object; same call for compile-time & run-time dimensions. ...
Definition: eigenutil.h:343
auto denseRandom(Rng &rng, RndDist &rnddist, IndexTypes... sizes) -> const Eigen::CwiseNullaryOp< tomo_internal::random_generator< Rng, RndDist, typename Eigen::internal::traits< Der >::Scalar >, Der >
a matrix populated with random entries using C++&#39;s random framework
Definition: eigenutil.h:153
STL class.
const Replicate< Derived, RowFactor, ColFactor > replicate() const