Tomographer  v1.0a
Tomographer C++ Framework Documentation
util.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) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #ifndef QIT_UTIL_H
28 #define QIT_UTIL_H
29 
37 #include <complex>
38 #include <vector>
39 
40 #include <Eigen/Core>
41 #include <Eigen/Dense>
42 #include <Eigen/StdVector>
43 
44 
45 
46 // -----------------------------------------------------------------------------
47 // C++ Helper for Complex Type
48 // -----------------------------------------------------------------------------
49 
50 namespace Tomographer
51 {
52 namespace Tools
53 {
54 
60 template<typename Scalar>
61 struct is_complex {
62  // use Eigen's existing implementation
63  enum { value = Eigen::NumTraits<Scalar>::IsComplex };
64 };
65 
66 
75 template<typename Scalar>
77  typedef Scalar type;
78 };
79 
81 template<typename RealScalar>
82 struct complex_real_scalar<std::complex<RealScalar> >
83 {
84  typedef RealScalar type;
85 };
86 
87 
88 
89 
95 template<typename X>
96 inline typename std::enable_if<std::is_unsigned<X>::value, bool>::type is_positive(const X /* val */)
97 {
98  return true;
99 }
101 template<typename X>
102 inline typename std::enable_if<!std::is_unsigned<X>::value, bool>::type is_positive(const X val)
103 {
104  return val >= 0;
105 }
106 
107 
108 
109 } // namespace Tools
110 } // namespace Tomographer
111 
112 
113 
114 // -----------------------------------------------------------------------------
115 // Eigen and std::vector
116 // -----------------------------------------------------------------------------
117 
118 namespace Tomographer {
119 namespace Tools {
120 
135 template<typename EigenType>
137 {
139 };
140 
141 } // namespace Tools
142 } // namespace Tomographer
143 
144 // -----------------------------------------------------------------------------
145 // Random matrices in Eigen
146 // -----------------------------------------------------------------------------
147 
148 namespace Tomographer {
149 
150 namespace tomo_internal {
151 
152  template<typename Rng, typename RndDist, typename Scalar>
153  struct random_generator
154  {
155  typedef Scalar result_type;
156 
157  Rng & rng;
158  RndDist & rnddist;
159 
160  random_generator(Rng & rng_, RndDist & rnddist_)
161  : rng(rng_), rnddist(rnddist_)
162  {
163  }
164 
165  template<typename Index>
166  inline const result_type operator() (Index, Index = 0) const {
167  return rnddist(rng);
168  }
169  };
170 
171  template<typename Rng, typename RndDist, typename RealScalar>
172  struct random_generator<Rng, RndDist, std::complex<RealScalar> >
173  {
174  typedef std::complex<RealScalar> result_type;
175 
176  Rng & rng;
177  RndDist & rnddist;
178 
179  random_generator(Rng & rng_, RndDist & rnddist_)
180  : rng(rng_), rnddist(rnddist_)
181  {
182  }
183 
184  template<typename Index>
185  inline const result_type operator() (Index, Index = 0) const {
186  return result_type(rnddist(rng), rnddist(rng));
187  }
188  };
189 } // end namespace tomo_internal
190 
191 } // namespace Tomographer
192 
193 namespace Eigen {
194  namespace internal {
196  template<typename Rng, typename RndDist, typename Scalar>
197  struct functor_traits<Tomographer::tomo_internal::random_generator<Rng, RndDist, Scalar> >
198  { enum { Cost = 50 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; };
199  }
200 } // end namespace Eigen
201 
202 
203 namespace Tomographer {
204 
205 
214 template<typename Der, typename Rng, typename RndDist, typename... IndexTypes>
215 inline auto dense_random(Rng & rng, RndDist &rnddist, IndexTypes... sizes)
216  -> const Eigen::CwiseNullaryOp<
217  tomo_internal::random_generator<Rng, RndDist, typename Eigen::internal::traits<Der>::Scalar>,
218  Der
219  >
220 {
221  typedef typename Der::Scalar Scalar;
222 
224  sizes..., tomo_internal::random_generator<Rng, RndDist, Scalar>(rng, rnddist)
225  );
226 }
227 
228 
229 
230 // ---------------------------
231 
232 
233 
234 namespace tomo_internal {
236  template<typename Scalar, typename IndexType>
237  struct can_basis_vec_generator
238  {
239  typedef Scalar result_type;
240 
241  IndexType k;
242  IndexType j;
243 
244  can_basis_vec_generator(IndexType k_, IndexType j_ = 0)
245  : k(k_), j(j_)
246  {
247  }
248 
249  inline const result_type operator() (IndexType a, IndexType b = 0) const {
250  return (a == k) && (b == j) ? result_type(1) : result_type(0);
251  }
252  };
253 } // namespace tomo_internal
254 } // namespace Tomographer
255 namespace Eigen {
256  namespace internal {
258  template<typename Scalar, typename IndexType>
259  struct functor_traits<Tomographer::tomo_internal::can_basis_vec_generator<Scalar, IndexType> >
260  { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = true }; };
261  }
262 } // end namespace Eigen
263 
264 namespace Tomographer {
265 
266 
270 template<typename Der, typename IndexType>
271 inline auto can_basis_vec(IndexType k, IndexType size)
272  -> const Eigen::CwiseNullaryOp<
273  tomo_internal::can_basis_vec_generator<typename Eigen::internal::traits<Der>::Scalar, IndexType>,
274  Der
275  >
276 {
277  typedef typename Der::Scalar Scalar;
278 
280  size, tomo_internal::can_basis_vec_generator<Scalar, IndexType>(k)
281  );
282 }
283 
288 template<typename Der, typename IndexType>
289 inline auto can_basis_vec(IndexType k, IndexType j, IndexType rows, IndexType cols)
290  -> const Eigen::CwiseNullaryOp<
291  tomo_internal::can_basis_vec_generator<typename Eigen::internal::traits<Der>::Scalar, IndexType>,
292  Der
293  >
294 {
295  typedef typename Der::Scalar Scalar;
296 
298  rows, cols, tomo_internal::can_basis_vec_generator<Scalar, IndexType>(k, j)
299  );
300 }
301 
302 
303 
304 
305 // ---------------------------
306 
307 
308 
309 namespace tomo_internal {
311  template<typename Scalar>
312  struct powers_of_two_generator
313  {
314  typedef typename Eigen::NumTraits<Scalar>::Real result_type;
315 
316  powers_of_two_generator() { }
317 
318  template<typename IndexType>
319  inline const result_type operator() (IndexType a) const {
320  return std::ldexp(result_type(1), a);
321  }
322 
323  template<typename IndexType>
324  inline const result_type operator() (IndexType a, IndexType b) const {
325  eigen_assert(b == 0 && "powers_of_two_generator may only be used with 1-D objects!"); (void)b;
326  return std::ldexp(result_type(1), a);
327  }
328 
329  };
330 } // namespace tomo_internal
331 } // namespace Tomographer
332 namespace Eigen {
333  namespace internal {
335  template<typename Scalar>
336  struct functor_traits<Tomographer::tomo_internal::powers_of_two_generator<Scalar> >
337  { enum { Cost = 8 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = true }; };
338 
339  // template<typename Scalar>
340  // struct functor_has_linear_access<Tomographer::tomo_internal::powers_of_two_generator<Scalar> >
341  // { enum { ret = 0 }; };
342  }
343 } // end namespace Eigen
344 
345 namespace Tomographer {
346 
347 
356 template<typename Der, typename... IndexTypes>
357 inline auto powers_of_two(IndexTypes... sizes)
358  -> const Eigen::CwiseNullaryOp<
359  tomo_internal::powers_of_two_generator<typename Eigen::internal::traits<Der>::Scalar>,
360  Der
361  >
362 {
363  typedef typename Der::Scalar Scalar;
364 
366  sizes..., tomo_internal::powers_of_two_generator<Scalar>()
367  );
368 }
369 
370 
371 
372 
373 
374 // -----------------------------------------------------------------------------
375 
391 template<int RowFactorCTime, int ColFactorCTime, typename Derived,
392  typename std::enable_if<(RowFactorCTime == Eigen::Dynamic || ColFactorCTime == Eigen::Dynamic),
393  bool>::type dummy = true>
394 inline auto replicated(const Eigen::DenseBase<Derived> & x, int row_factor, int col_factor)
396 {
397  eigen_assert(RowFactorCTime == Eigen::Dynamic || row_factor == RowFactorCTime);
398  eigen_assert(ColFactorCTime == Eigen::Dynamic || col_factor == ColFactorCTime);
399  return x.replicate(row_factor, col_factor);
400 }
405 template<int RowFactorCTime, int ColFactorCTime, typename Derived,
406  typename std::enable_if<(RowFactorCTime != Eigen::Dynamic && ColFactorCTime != Eigen::Dynamic),
407  bool>::type dummy2 = true>
408 inline auto replicated(const Eigen::DenseBase<Derived> & x, int row_factor, int col_factor)
410 {
411  eigen_assert(row_factor == RowFactorCTime); (void)row_factor; // "unused argument" warning
412  eigen_assert(col_factor == ColFactorCTime); (void)col_factor; // "unused argument" warning
413  return x.template replicate<RowFactorCTime, ColFactorCTime>();
414 }
415 
416 
417 } // namespace Tomographer
418 
419 
420 
421 
422 #endif
static const CwiseNullaryOp< CustomNullaryOp, Derived > NullaryExpr(Index rows, Index cols, const CustomNullaryOp &func)
Base namespace for the Tomographer project.
Definition: dmmhrw.h:51
Use this if you need an std::vector of any Eigen type.
Definition: util.h:136
auto powers_of_two(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: util.h:357
T internal(T...args)
std::enable_if< std::is_unsigned< X >::value, bool >::type is_positive(const X)
Test whether the given value is positive or zero.
Definition: util.h:96
STL namespace.
STL class.
auto can_basis_vec(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: util.h:271
T ldexp(T...args)
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: util.h:394
auto dense_random(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++'s random framework
Definition: util.h:215
STL class.
The Real scalar type corresponding to a std::complex type.
Definition: util.h:76
statically determine whether a type is complex
Definition: util.h:61
const Replicate< Derived, RowFactor, ColFactor > replicate() const