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