$darkmode
Eigen  5.0.1-dev
lapacke_helpers.h
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 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 #ifdef EIGEN_USE_MKL
17 #include "mkl_lapacke.h"
18 #else
19 #include "lapacke.h"
20 #endif
21 
22 namespace Eigen {
23 namespace internal {
28 namespace lapacke_helpers {
29 
30 // ---------------------------------------------------------------------------------------------------------------------
31 // Translation from Eigen to Lapacke for types and constants
32 // ---------------------------------------------------------------------------------------------------------------------
33 
34 // For complex numbers, the types in Eigen and Lapacke are different, but layout compatible.
35 template <typename Scalar>
36 struct translate_type_imp;
37 template <>
38 struct translate_type_imp<float> {
39  using type = float;
40 };
41 template <>
42 struct translate_type_imp<double> {
43  using type = double;
44 };
45 template <>
46 struct translate_type_imp<std::complex<double>> {
47  using type = lapack_complex_double;
48 };
49 template <>
50 struct translate_type_imp<std::complex<float>> {
51  using type = lapack_complex_float;
52 };
53 
55 template <typename Scalar>
56 using translated_type = typename translate_type_imp<Scalar>::type;
57 
60 template <typename Source, typename Target = translated_type<Source>>
61 EIGEN_ALWAYS_INLINE auto to_lapack(Source value) {
62  return static_cast<Target>(value);
63 }
64 
67 template <typename Source, typename Target = translated_type<Source>>
68 EIGEN_ALWAYS_INLINE auto to_lapack(Source *value) {
69  return reinterpret_cast<Target *>(value);
70 }
71 
74 EIGEN_ALWAYS_INLINE lapack_int to_lapack(Index index) { return convert_index<lapack_int>(index); }
75 
77 template <typename Derived>
78 EIGEN_ALWAYS_INLINE constexpr lapack_int lapack_storage_of(const EigenBase<Derived> &) {
79  return Derived::IsRowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR;
80 }
81 
82 // ---------------------------------------------------------------------------------------------------------------------
83 // Automatic generation of low-level wrappers
84 // ---------------------------------------------------------------------------------------------------------------------
85 
96 template <typename DoubleFn, typename SingleFn, typename DoubleCpxFn, typename SingleCpxFn>
97 struct WrappingHelper {
98  // The naming of double, single, double complex and single complex is purely for readability
99  // and doesn't actually affect the workings of this class. In principle, the arguments can
100  // be supplied in any permuted order.
101  DoubleFn double_;
102  SingleFn single_;
103  DoubleCpxFn double_cpx_;
104  SingleCpxFn single_cpx_;
105 
106  template <typename... Args>
107  auto call(Args &&...args) -> decltype(double_(std::forward<Args>(args)...)) {
108  return double_(std::forward<Args>(args)...);
109  }
110 
111  template <typename... Args>
112  auto call(Args &&...args) -> decltype(single_(std::forward<Args>(args)...)) {
113  return single_(std::forward<Args>(args)...);
114  }
115 
116  template <typename... Args>
117  auto call(Args &&...args) -> decltype(double_cpx_(std::forward<Args>(args)...)) {
118  return double_cpx_(std::forward<Args>(args)...);
119  }
120 
121  template <typename... Args>
122  auto call(Args &&...args) -> decltype(single_cpx_(std::forward<Args>(args)...)) {
123  return single_cpx_(std::forward<Args>(args)...);
124  }
125 };
126 
131 template <typename DoubleFn, typename SingleFn, typename DoubleCpxFn, typename SingleCpxFn, typename... Args>
132 EIGEN_ALWAYS_INLINE auto call_wrapper(DoubleFn df, SingleFn sf, DoubleCpxFn dcf, SingleCpxFn scf, Args &&...args) {
133  WrappingHelper<DoubleFn, SingleFn, DoubleCpxFn, SingleCpxFn> helper{df, sf, dcf, scf};
134  return helper.call(std::forward<Args>(args)...);
135 }
136 
142 #define EIGEN_MAKE_LAPACKE_WRAPPER(FUNCTION) \
143  template <typename... Args> \
144  EIGEN_ALWAYS_INLINE auto FUNCTION(Args &&...args) { \
145  return call_wrapper(LAPACKE_d##FUNCTION, LAPACKE_s##FUNCTION, LAPACKE_z##FUNCTION, LAPACKE_c##FUNCTION, \
146  std::forward<Args>(args)...); \
147  }
148 
149 // Now with this macro and the helper wrappers, we can generate the dispatch for all the lapacke functions that are
150 // used in Eigen.
151 // We define these here instead of in the files where they are used because this allows us to #undef the macro again
152 // right here
153 EIGEN_MAKE_LAPACKE_WRAPPER(potrf)
154 EIGEN_MAKE_LAPACKE_WRAPPER(getrf)
155 EIGEN_MAKE_LAPACKE_WRAPPER(geqrf)
156 EIGEN_MAKE_LAPACKE_WRAPPER(gesdd)
157 
158 #undef EIGEN_MAKE_LAPACKE_WRAPPER
159 } // namespace lapacke_helpers
160 } // namespace internal
161 } // namespace Eigen
162 
163 #endif // EIGEN_LAPACKE_HELPERS_H
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: BFloat16.h:231
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82