sytrd_sb2st_cta.hh
Go to the documentation of this file.
1#pragma once
2
4
5#include <src/math-helpers.hh>
6#include <src/queue.hh>
8
9#include <sycl/sycl.hpp>
10
11#include <complex>
12#include <cstdint>
13
14namespace batchlas {
15
16namespace internal {
17
18// Band-to-tridiagonal (xSBTRD/xHBTRD) Givens primitives shared by sytrd_sb2st.cc and sytrd_sb2st_cta.cc.
19template <typename T>
21 T* ptr = nullptr;
22 int inc = 1;
23 inline T& operator[](int i) const { return ptr[i * inc]; }
24};
25
26template <typename T>
28 const T* ptr = nullptr;
29 int inc = 1;
30 inline const T& operator[](int i) const { return ptr[i * inc]; }
31};
32
33template <typename T>
34inline StridedView<T> make_strided(T* ptr, int inc) {
35 return StridedView<T>{ptr, inc};
36}
37
38template <typename T>
39inline ConstStridedView<T> make_strided(const T* ptr, int inc) {
40 return ConstStridedView<T>{ptr, inc};
41}
42
43template <typename T>
44inline ConstStridedView<T> make_const_strided(T* ptr, int inc) {
45 return ConstStridedView<T>{ptr, inc};
46}
47
48template <typename Ops, typename T>
51 for (int t = 0; t < nrot; ++t) {
52 Ops::rot_pair(x[t], y[t], c[t], s[t]);
53 }
54}
55
56template <typename Ops, typename T>
58 for (int t = 0; t < nrot; ++t) {
59 const T f = x[t];
60 const T g = w[t];
61 typename Ops::Real ct = typename Ops::Real(0);
62 T st = T(0);
63 T rt = T(0);
64 Ops::lartg(f, g, ct, st, rt);
65 c[t] = ct;
66 w[t] = st;
67 x[t] = rt;
68 }
69}
70
71template <typename T>
72inline T real_as_T(const T& x) {
73 if constexpr (internal::is_complex<T>::value) {
74 return T(x.real(), typename T::value_type(0));
75 } else {
76 return x;
77 }
78}
79
80template <typename T, bool IsComplex = internal::is_complex<T>::value>
82
83// Real/symmetric variant (DSBTRD-style primitives).
84template <typename T>
85struct btrd_givens_ops<T, false> {
86 using Real = typename base_type<T>::type;
87
88 static inline void lartg(const T& f_in, const T& g_in, Real& c, T& s, T& r) {
89 auto [ct, st, rt] = internal::lartg(f_in, g_in);
90 c = ct;
91 s = T(st);
92 r = T(rt);
93 }
94
95 static inline void rot_pair(T& x, T& y, Real c, const T& s_in) {
96 const Real s = static_cast<Real>(s_in);
97 const Real xt = static_cast<Real>(x);
98 const Real yt = static_cast<Real>(y);
99 x = T(c * xt + s * yt);
100 y = T(c * yt - s * xt);
101 }
102
103 static inline void rot(int nrot, StridedView<T> x, StridedView<T> y, Real c, const T& s_in) {
104 for (int t = 0; t < nrot; ++t) {
105 rot_pair(x[t], y[t], c, s_in);
106 }
107 }
108
109 static inline void lartv(int nrot,
114 lartv_impl<btrd_givens_ops<T, false>, T>(nrot, x, y, c, s);
115 }
116
117 static inline void largv(int nrot, StridedView<T> x, StridedView<T> w, StridedView<Real> c) {
118 largv_impl<btrd_givens_ops<T, false>, T>(nrot, x, w, c);
119 }
120
121 static inline void lar2v_pair(T& x, T& y, T& z, Real ci, const T& si_in) {
122 const Real xi = static_cast<Real>(x);
123 const Real yi = static_cast<Real>(y);
124 const Real zi = static_cast<Real>(z);
125 const Real si = static_cast<Real>(si_in);
126
127 const Real t1 = si * zi;
128 const Real t2 = ci * zi;
129 const Real t3 = t2 - si * xi;
130 const Real t4 = t2 + si * yi;
131 const Real t5 = ci * xi + t1;
132 const Real t6 = ci * yi - t1;
133
134 x = T(ci * t5 + si * t4);
135 y = T(ci * t6 - si * t3);
136 z = T(ci * t4 - si * t5);
137 }
138
139 static inline void lar2v(int nrot,
145 for (int t = 0; t < nrot; ++t) {
146 lar2v_pair(x[t], y[t], z[t], c[t], s[t]);
147 }
148 }
149
150 static inline void prepare_work_for_right(int /*nrot*/, T* /*s*/, int /*stride*/) {}
151 static inline void ensure_band_diag_real(T* /*AB*/, int /*ldab*/, int /*n*/) {}
152
154 int n,
157 VectorView<T> TAU) {
158 auto diag = AB(int32_t(0), Slice{});
159 auto sub = AB(int32_t(1), Slice{});
160 for (int j = 0; j < n; ++j) {
161 D[j] = static_cast<Real>(diag[j]);
162 if (j < n - 1) {
163 E[j] = static_cast<Real>(sub[j]);
164 TAU[j] = T(0);
165 }
166 }
167 }
168};
169
170// Complex/Hermitian variant (ZHBTRD-style primitives).
171template <typename T>
172struct btrd_givens_ops<T, true> {
173 using Real = typename base_type<T>::type;
174
175 static inline void lartg(const T& f, const T& g, Real& c, T& s, T& r) {
176 auto [ct, st, rt] = internal::lartg(f, g);
177 c = ct;
178 s = st;
179 r = rt;
180 }
181
182 static inline void rot_pair(T& x, T& y, Real c, const T& s) {
183 const T xt = x;
184 const T yt = y;
185 x = T(c) * xt + s * yt;
186 y = T(c) * yt - batchlas::device::detail::conj(s) * xt;
187 }
188
189 static inline void rot(int nrot, StridedView<T> x, StridedView<T> y, Real c, const T& s) {
190 for (int t = 0; t < nrot; ++t) {
191 rot_pair(x[t], y[t], c, s);
192 }
193 }
194
195 static inline void lartv(int nrot,
200 lartv_impl<btrd_givens_ops<T, true>, T>(nrot, x, y, c, s);
201 }
202
203 static inline void largv(int nrot, StridedView<T> x, StridedView<T> w, StridedView<Real> c) {
204 largv_impl<btrd_givens_ops<T, true>, T>(nrot, x, w, c);
205 }
206
207 static inline void lar2v_pair(T& x, T& y, T& z, Real ci, const T& si) {
208 // Exact port of Netlib LAPACK CLAR2V logic.
209 const Real xi = static_cast<Real>(x.real());
210 const Real yi = static_cast<Real>(y.real());
211 const T zi = z;
212
213 const Real zir = static_cast<Real>(zi.real());
214 const Real zii = static_cast<Real>(zi.imag());
215
216 const Real sir = static_cast<Real>(si.real());
217 const Real sii = static_cast<Real>(si.imag());
218
219 const Real t1r = sir * zir - sii * zii;
220 const Real t1i = sir * zii + sii * zir;
221
222 const T t2 = T(ci * zir, ci * zii);
223 const T t3 = t2 - batchlas::device::detail::conj(si) * T(xi, Real(0));
224 const T t4 = batchlas::device::detail::conj(t2) + si * T(yi, Real(0));
225
226 const Real t5 = ci * xi + t1r;
227 const Real t6 = ci * yi - t1r;
228
229 const Real xnew = ci * t5 + (sir * static_cast<Real>(t4.real()) + sii * static_cast<Real>(t4.imag()));
230 const Real ynew = ci * t6 - (sir * static_cast<Real>(t3.real()) - sii * static_cast<Real>(t3.imag()));
231 const T znew = T(ci) * t3 + batchlas::device::detail::conj(si) * T(t6, t1i);
232
233 x = T(xnew, Real(0));
234 y = T(ynew, Real(0));
235 z = znew;
236 }
237
238 static inline void lar2v(int nrot,
244 for (int t = 0; t < nrot; ++t) {
245 lar2v_pair(x[t], y[t], z[t], c[t], s[t]);
246 }
247 }
248
249 static inline void prepare_work_for_right(int nrot, T* s, int stride) {
250 // ZHBTRD requirement: conjugate WORK(J1) vector before applying from the right.
251 for (int t = 0; t < nrot; ++t) {
252 s[t * stride] = batchlas::device::detail::conj(s[t * stride]);
253 }
254 }
255
256 static inline void ensure_band_diag_real(T* AB, int ldab, int n) {
257 // Ensure diagonal is real (ZHBTRD does this).
258 for (int j = 0; j < n; ++j) {
259 const int idx = 0 + j * ldab;
260 AB[idx] = real_as_T(AB[idx]);
261 }
262 }
263
265 int n,
268 VectorView<T> TAU) {
269 auto diag = AB(int32_t(0), Slice{});
270 auto sub = AB(int32_t(1), Slice{});
271
272 // Make diagonal real.
273 for (int j = 0; j < n; ++j) {
274 diag[j] = real_as_T(diag[j]);
275 }
276
277 // Make subdiagonal real (phase chaining) and extract D/E.
278 for (int j = 0; j < n - 1; ++j) {
279 const T t = sub[j];
280 const Real a = internal::abs(t);
281 E[j] = a;
282 T phase = T(1);
283 if (a != Real(0)) {
284 phase = t / T(a);
285 }
286 sub[j] = T(a, Real(0));
287 if (j < n - 2) {
288 sub[j + 1] *= phase;
289 }
290 TAU[j] = T(0);
291 }
292
293 for (int j = 0; j < n; ++j) {
294 D[j] = static_cast<Real>(real_part(diag[j]));
295 }
296 }
297};
298
299template <typename T>
302 int n,
303 int kd,
304 VectorView<typename base_type<T>::type> c,
305 VectorView<T> work,
306 VectorView<typename base_type<T>::type> d,
307 VectorView<typename base_type<T>::type> e,
308 VectorView<T> tau);
309
310// Explicit instantiations live in sytrd_sb2st_cta.cc.
311#define BTRD_LOWER_INPLACE_SUBGROUP_DISPATCH_EXTERN(fp, real_fp) \
312extern template Event btrd_lower_inplace_subgroup_dispatch<BATCHLAS_UNPAREN fp>(Queue&, \
313 KernelMatrixView<BATCHLAS_UNPAREN fp, MatrixFormat::Dense>, \
314 int, \
315 int, \
316 VectorView<BATCHLAS_UNPAREN real_fp>, \
317 VectorView<BATCHLAS_UNPAREN fp>, \
318 VectorView<BATCHLAS_UNPAREN real_fp>, \
319 VectorView<BATCHLAS_UNPAREN real_fp>, \
320 VectorView<BATCHLAS_UNPAREN fp>);
321
323
324#undef BTRD_LOWER_INPLACE_SUBGROUP_DISPATCH_EXTERN
325
326} // namespace internal
327
328} // namespace batchlas
Non-owning view of a batch of strided vectors: the vector argument type of the entry points.
Definition matrix.hh:1754
The batched containers: Matrix (owning), MatrixView (non-owning), KernelMatrixView (device-side),...
constexpr T conj(const T &value)
StridedView< T > make_strided(T *ptr, int inc)
void lartv_impl(int nrot, StridedView< T > x, StridedView< T > y, ConstStridedView< typename Ops::Real > c, ConstStridedView< T > s)
Event btrd_lower_inplace_subgroup_dispatch(Queue &q, KernelMatrixView< T, MatrixFormat::Dense > ab, int n, int kd, VectorView< typename base_type< T >::type > c, VectorView< T > work, VectorView< typename base_type< T >::type > d, VectorView< typename base_type< T >::type > e, VectorView< T > tau)
void largv_impl(int nrot, StridedView< T > x, StridedView< T > w, StridedView< typename Ops::Real > c)
T real_as_T(const T &x)
ConstStridedView< T > make_const_strided(T *ptr, int inc)
Completion handle of enqueued work, returned by every entry point.
Trivially copyable view of a MatrixView for use inside a SYCL kernel.
Definition matrix.hh:145
Where BatchLAS work runs: a device, a backend, an ordered SYCL queue and a workspace arena.
A half-open index range [start, end) along one dimension.
Definition matrix.hh:120
T type
The real type.
Definition enums.hh:30
static void largv(int nrot, StridedView< T > x, StridedView< T > w, StridedView< Real > c)
static void finalize_tridiag(const KernelMatrixView< T, MatrixFormat::Dense > &AB, int n, VectorView< Real > D, VectorView< Real > E, VectorView< T > TAU)
static void lartv(int nrot, StridedView< T > x, StridedView< T > y, ConstStridedView< Real > c, ConstStridedView< T > s)
static void lartg(const T &f_in, const T &g_in, Real &c, T &s, T &r)
static void rot_pair(T &x, T &y, Real c, const T &s_in)
static void rot(int nrot, StridedView< T > x, StridedView< T > y, Real c, const T &s_in)
static void lar2v_pair(T &x, T &y, T &z, Real ci, const T &si_in)
static void lar2v(int nrot, StridedView< T > x, StridedView< T > y, StridedView< T > z, ConstStridedView< Real > c, ConstStridedView< T > s)
static void lartv(int nrot, StridedView< T > x, StridedView< T > y, ConstStridedView< Real > c, ConstStridedView< T > s)
static void lartg(const T &f, const T &g, Real &c, T &s, T &r)
static void lar2v_pair(T &x, T &y, T &z, Real ci, const T &si)
static void prepare_work_for_right(int nrot, T *s, int stride)
static void rot_pair(T &x, T &y, Real c, const T &s)
static void lar2v(int nrot, StridedView< T > x, StridedView< T > y, StridedView< T > z, ConstStridedView< Real > c, ConstStridedView< T > s)
static void ensure_band_diag_real(T *AB, int ldab, int n)
static void rot(int nrot, StridedView< T > x, StridedView< T > y, Real c, const T &s)
static void finalize_tridiag(KernelMatrixView< T, MatrixFormat::Dense > AB, int n, VectorView< Real > D, VectorView< Real > E, VectorView< T > TAU)
static void largv(int nrot, StridedView< T > x, StridedView< T > w, StridedView< Real > c)
#define BTRD_LOWER_INPLACE_SUBGROUP_DISPATCH_EXTERN(fp, real_fp)
#define BATCHLAS_FOR_EACH_SYTRD_SB2ST_CTA_DISPATCH_TYPE(INVOKE)