lapacke_helpers.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2021 Erik Schultheis <erik.schultheis@aalto.fi>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_LAPACKE_HELPERS_H
11 #define EIGEN_LAPACKE_HELPERS_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 #ifdef EIGEN_USE_MKL
16 #include "mkl_lapacke.h"
17 #else
18 #include "lapacke.h"
19 #endif
20 
21 namespace Eigen {
22 namespace internal {
27 namespace lapacke_helpers {
28 
29 // ---------------------------------------------------------------------------------------------------------------------
30 // Translation from Eigen to Lapacke for types and constants
31 // ---------------------------------------------------------------------------------------------------------------------
32 
33 // For complex numbers, the types in Eigen and Lapacke are different, but layout compatible.
34 template<typename Scalar>
35 struct translate_type_imp;
36 template<>
37 struct translate_type_imp<float> {
38  using type = float;
39 };
40 template<>
41 struct translate_type_imp<double> {
42  using type = double;
43 };
44 template<>
45 struct translate_type_imp<std::complex<double>> {
46  using type = lapack_complex_double;
47 };
48 template<>
49 struct translate_type_imp<std::complex<float>> {
50  using type = lapack_complex_float;
51 };
52 
54 template<typename Scalar>
55 using translated_type = typename translate_type_imp<Scalar>::type;
56 
59 template<typename Source, typename Target=translated_type<Source>>
60 EIGEN_ALWAYS_INLINE auto to_lapack(Source value) { return static_cast<Target>(value); }
61 
64 template<typename Source, typename Target=translated_type<Source>>
65 EIGEN_ALWAYS_INLINE auto to_lapack(Source *value) { return reinterpret_cast<Target*>(value); }
66 
69 EIGEN_ALWAYS_INLINE lapack_int to_lapack(Index index) {
70  return convert_index<lapack_int>(index);
71 }
72 
74 template<typename Derived>
75 EIGEN_ALWAYS_INLINE EIGEN_CONSTEXPR lapack_int lapack_storage_of(const EigenBase<Derived> &) {
76  return Derived::IsRowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR;
77 }
78 
79 // ---------------------------------------------------------------------------------------------------------------------
80 // Automatic generation of low-level wrappers
81 // ---------------------------------------------------------------------------------------------------------------------
82 
93 template<typename DoubleFn, typename SingleFn, typename DoubleCpxFn, typename SingleCpxFn>
94 struct WrappingHelper {
95  // The naming of double, single, double complex and single complex is purely for readability
96  // and doesn't actually affect the workings of this class. In principle, the arguments can
97  // be supplied in any permuted order.
98  DoubleFn double_; SingleFn single_; DoubleCpxFn double_cpx_; SingleCpxFn single_cpx_;
99 
100  template<typename... Args>
101  auto call(Args&&... args) -> decltype(double_(std::forward<Args>(args)...)) {
102  return double_(std::forward<Args>(args)...);
103  }
104 
105  template<typename... Args>
106  auto call(Args&&... args) -> decltype(single_(std::forward<Args>(args)...)){
107  return single_(std::forward<Args>(args)...);
108  }
109 
110  template<typename... Args>
111  auto call(Args&&... args) -> decltype(double_cpx_(std::forward<Args>(args)...)){
112  return double_cpx_(std::forward<Args>(args)...);
113  }
114 
115  template<typename... Args>
116  auto call(Args&&... args) -> decltype(single_cpx_(std::forward<Args>(args)...)){
117  return single_cpx_(std::forward<Args>(args)...);
118  }
119 };
120 
125 template<typename DoubleFn, typename SingleFn, typename DoubleCpxFn, typename SingleCpxFn, typename... Args>
126 EIGEN_ALWAYS_INLINE auto call_wrapper(DoubleFn df, SingleFn sf, DoubleCpxFn dcf, SingleCpxFn scf, Args&&... args) {
127  WrappingHelper<DoubleFn, SingleFn, DoubleCpxFn, SingleCpxFn> helper{df, sf, dcf, scf};
128  return helper.call(std::forward<Args>(args)...);
129 }
130 
136 #define EIGEN_MAKE_LAPACKE_WRAPPER(FUNCTION) \
137 template<typename... Args> \
138 EIGEN_ALWAYS_INLINE auto FUNCTION(Args&&... args) { return call_wrapper(LAPACKE_d##FUNCTION, LAPACKE_s##FUNCTION, LAPACKE_z##FUNCTION, LAPACKE_c##FUNCTION, std::forward<Args>(args)...); }
139 
140 // Now with this macro and the helper wrappers, we can generate the dispatch for all the lapacke functions that are
141 // used in Eigen.
142 // We define these here instead of in the files where they are used because this allows us to #undef the macro again
143 // right here
148 
149 #undef EIGEN_MAKE_LAPACKE_WRAPPER
150 }
151 }
152 }
153 
154 #endif // EIGEN_LAPACKE_HELPERS_H
#define EIGEN_ALWAYS_INLINE
Definition: Macros.h:836
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define LAPACK_COL_MAJOR
Definition: lapacke.h:125
#define lapack_int
Definition: lapacke.h:52
#define LAPACK_ROW_MAJOR
Definition: lapacke.h:124
#define lapack_complex_double
Definition: lapacke.h:94
#define lapack_complex_float
Definition: lapacke.h:79
#define EIGEN_MAKE_LAPACKE_WRAPPER(FUNCTION)
: InteropHeaders
Definition: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Definition: BFloat16.h:222