<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
legacyArray.hpp
Go to the documentation of this file.
1
3//
4// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
5//
6// This file is part of <T>LAPACK.
7// <T>LAPACK is free software: you can redistribute it and/or modify it under
8// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
9
10#ifndef TLAPACK_LEGACYARRAY_HH
11#define TLAPACK_LEGACYARRAY_HH
12
13#include <cassert>
14
20
21namespace tlapack {
22
23// -----------------------------------------------------------------------------
24// Helpers
25
26namespace traits {
27 namespace internal {
28 template <typename T, class idx_t, Layout L>
29 std::true_type is_legacy_type_f(const LegacyMatrix<T, idx_t, L>*);
30
31 template <typename T, class idx_t, class int_t, Direction D>
32 std::true_type is_legacy_type_f(
34
35 std::false_type is_legacy_type_f(const void*);
36 } // namespace internal
37
40 template <class T>
41 constexpr bool is_legacy_type =
42 decltype(internal::is_legacy_type_f(std::declval<T*>()))::value;
43} // namespace traits
44
45// -----------------------------------------------------------------------------
46// Data traits
47
48namespace traits {
50 template <typename T, class idx_t, Layout L>
51 struct layout_trait<LegacyMatrix<T, idx_t, L>, int> {
52 static constexpr Layout value = L;
53 };
54
56 template <typename T, class idx_t, typename int_t, Direction D>
57 struct layout_trait<LegacyVector<T, idx_t, int_t, D>, int> {
58 static constexpr Layout value = Layout::Strided;
59 };
60
61 template <class T, class idx_t, typename int_t, Direction D>
62 struct real_type_traits<LegacyVector<T, idx_t, int_t, D>, int> {
63 using type = LegacyVector<real_type<T>, idx_t, int_t, D>;
64 };
65
66 template <typename T, class idx_t, Layout layout>
68 using type = LegacyMatrix<real_type<T>, idx_t, layout>;
69 };
70
71 template <class T, class idx_t, typename int_t, Direction D>
72 struct complex_type_traits<LegacyVector<T, idx_t, int_t, D>, int> {
73 using type = LegacyVector<complex_type<T>, idx_t, int_t, D>;
74 };
75
76 template <typename T, class idx_t, Layout layout>
78 using type = LegacyMatrix<complex_type<T>, idx_t, layout>;
79 };
80
82 template <class U, class idx_t, Layout layout>
84 template <class T>
85 constexpr auto operator()(std::vector<T>& v, idx_t m, idx_t n) const
86 {
87 assert(m >= 0 && n >= 0);
88 v.resize(m * n); // Allocates space in memory
89 return LegacyMatrix<T, idx_t, layout>(m, n, v.data());
90 }
91 };
92
94 template <class U, class idx_t, Layout layout, int m, int n>
95 struct CreateStaticFunctor<LegacyMatrix<U, idx_t, layout>, m, n, int> {
96 static_assert(m >= 0 && n >= 0);
97
98 template <typename T>
99 constexpr auto operator()(T* v) const
100 {
101 return LegacyMatrix<T, idx_t, layout>(m, n, v);
102 }
103 };
104
106 template <class U, class idx_t, typename int_t, Direction D>
107 struct CreateFunctor<LegacyVector<U, idx_t, int_t, D>, int> {
108 template <class T>
109 constexpr auto operator()(std::vector<T>& v, idx_t n) const
110 {
111 assert(n >= 0);
112 v.resize(n); // Allocates space in memory
113 return LegacyVector<T, idx_t, int_t, D>(n, v.data());
114 }
115 };
116
118 template <class U, class idx_t, typename int_t, Direction D, int n>
119 struct CreateStaticFunctor<LegacyVector<U, idx_t, int_t, D>, n, -1, int> {
120 static_assert(n >= 0);
121
122 template <typename T>
123 constexpr auto operator()(T* v) const
124 {
125 return LegacyVector<T, idx_t>(n, v);
126 }
127 };
128} // namespace traits
129
130// -----------------------------------------------------------------------------
131// Data descriptors
132
133// Number of rows of LegacyMatrix
134template <typename T, class idx_t, Layout layout>
135constexpr auto nrows(const LegacyMatrix<T, idx_t, layout>& A) noexcept
136{
137 return A.m;
138}
139
140// Number of columns of LegacyMatrix
141template <typename T, class idx_t, Layout layout>
142constexpr auto ncols(const LegacyMatrix<T, idx_t, layout>& A) noexcept
143{
144 return A.n;
145}
146
147// Size of LegacyMatrix
148template <typename T, class idx_t, Layout layout>
149constexpr auto size(const LegacyMatrix<T, idx_t, layout>& A) noexcept
150{
151 return A.m * A.n;
152}
153
154// Size of LegacyVector
155template <typename T, class idx_t, typename int_t, Direction direction>
156constexpr auto size(const LegacyVector<T, idx_t, int_t, direction>& x) noexcept
157{
158 return x.n;
159}
160
161// Number of rows of LegacyBandedMatrix
162template <typename T, class idx_t>
163constexpr auto nrows(const LegacyBandedMatrix<T, idx_t>& A) noexcept
164{
165 return A.m;
166}
167
168// Number of columns of LegacyBandedMatrix
169template <typename T, class idx_t>
170constexpr auto ncols(const LegacyBandedMatrix<T, idx_t>& A) noexcept
171{
172 return A.n;
173}
174
175// Size of LegacyBandedMatrix
176template <typename T, class idx_t>
177constexpr auto size(const LegacyBandedMatrix<T, idx_t>& A) noexcept
178{
179 return A.m * A.n;
180}
181
182// Lowerband of LegacyBandedMatrix
183template <typename T, class idx_t>
184constexpr auto lowerband(const LegacyBandedMatrix<T, idx_t>& A) noexcept
185{
186 return A.kl;
187}
188
189// Upperband of LegacyBandedMatrix
190template <typename T, class idx_t>
191constexpr auto upperband(const LegacyBandedMatrix<T, idx_t>& A) noexcept
192{
193 return A.ku;
194}
195
196// -----------------------------------------------------------------------------
197// Block operations for const LegacyMatrix
198
199#define isSlice(SliceSpec) !std::is_convertible<SliceSpec, idx_t>::value
200
201// Slice LegacyMatrix
202template <
203 typename T,
204 class idx_t,
206 class SliceSpecRow,
207 class SliceSpecCol,
208 typename std::enable_if<isSlice(SliceSpecRow) && isSlice(SliceSpecCol),
209 int>::type = 0>
210constexpr auto slice(const LegacyMatrix<T, idx_t, layout>& A,
211 SliceSpecRow&& rows,
212 SliceSpecCol&& cols) noexcept
213{
214 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
215 rows.first == rows.second);
216 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
217 assert(rows.first <= rows.second);
218 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
219 cols.first == cols.second);
220 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
221 assert(cols.first <= cols.second);
223 rows.second - rows.first, cols.second - cols.first,
224 (layout == Layout::ColMajor) ? &A.ptr[rows.first + cols.first * A.ldim]
225 : &A.ptr[rows.first * A.ldim + cols.first],
226 A.ldim);
227}
228
229#undef isSlice
230
231// Slice LegacyMatrix over a single row
232template <typename T, class idx_t, Layout layout, class SliceSpecCol>
233constexpr auto slice(const LegacyMatrix<T, idx_t, layout>& A,
234 size_type<LegacyMatrix<T, idx_t, layout>> rowIdx,
235 SliceSpecCol&& cols) noexcept
236{
237 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
238 cols.first == cols.second);
239 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
240 assert(cols.first <= cols.second);
241 assert(rowIdx >= 0 and rowIdx < nrows(A));
243 cols.second - cols.first,
244 (layout == Layout::ColMajor) ? &A.ptr[rowIdx + cols.first * A.ldim]
245 : &A.ptr[rowIdx * A.ldim + cols.first],
246 layout == Layout::ColMajor ? A.ldim : 1);
247}
248
249// Slice LegacyMatrix over a single column
250template <typename T, class idx_t, Layout layout, class SliceSpecRow>
251constexpr auto slice(const LegacyMatrix<T, idx_t, layout>& A,
252 SliceSpecRow&& rows,
253 size_type<LegacyMatrix<T, idx_t, layout>> colIdx) noexcept
254{
255 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
256 rows.first == rows.second);
257 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
258 assert(rows.first <= rows.second);
259 assert(colIdx >= 0 and colIdx < ncols(A));
261 rows.second - rows.first,
262 (layout == Layout::ColMajor) ? &A.ptr[rows.first + colIdx * A.ldim]
263 : &A.ptr[rows.first * A.ldim + colIdx],
264 layout == Layout::RowMajor ? A.ldim : 1);
265}
266
267// Get rows of LegacyMatrix
268template <typename T, class idx_t, Layout layout, class SliceSpec>
269constexpr auto rows(const LegacyMatrix<T, idx_t, layout>& A,
270 SliceSpec&& rows) noexcept
271{
272 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
273 rows.first == rows.second);
274 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
275 assert(rows.first <= rows.second);
277 rows.second - rows.first, A.n,
278 (layout == Layout::ColMajor) ? &A.ptr[rows.first]
279 : &A.ptr[rows.first * A.ldim],
280 A.ldim);
281}
282
283// Get a row of a column-major LegacyMatrix
284template <typename T, class idx_t>
285constexpr auto row(const LegacyMatrix<T, idx_t>& A,
286 size_type<LegacyMatrix<T, idx_t>> rowIdx) noexcept
287{
288 assert(rowIdx >= 0 and rowIdx < nrows(A));
289 return LegacyVector<const T, idx_t, idx_t>(A.n, &A.ptr[rowIdx], A.ldim);
290}
291
292// Get a row of a row-major LegacyMatrix
293template <typename T, class idx_t>
294constexpr auto row(
296 size_type<LegacyMatrix<T, idx_t, Layout::RowMajor>> rowIdx) noexcept
297{
298 assert(rowIdx >= 0 and rowIdx < nrows(A));
299 return LegacyVector<const T, idx_t>(A.n, &A.ptr[rowIdx * A.ldim]);
300}
301
302// Get columns of LegacyMatrix
303template <typename T, class idx_t, Layout layout, class SliceSpec>
304constexpr auto cols(const LegacyMatrix<T, idx_t, layout>& A,
305 SliceSpec&& cols) noexcept
306{
307 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
308 cols.first == cols.second);
309 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
310 assert(cols.first <= cols.second);
312 A.m, cols.second - cols.first,
313 (layout == Layout::ColMajor) ? &A.ptr[cols.first * A.ldim]
314 : &A.ptr[cols.first],
315 A.ldim);
316}
317
318// Get a column of a column-major LegacyMatrix
319template <typename T, class idx_t>
320constexpr auto col(const LegacyMatrix<T, idx_t>& A,
321 size_type<LegacyMatrix<T, idx_t>> colIdx) noexcept
322{
323 assert(colIdx >= 0 and colIdx < ncols(A));
324 return LegacyVector<const T, idx_t>(A.m, &A.ptr[colIdx * A.ldim]);
325}
326
327// Get a column of a row-major LegacyMatrix
328template <typename T, class idx_t>
329constexpr auto col(
331 size_type<LegacyMatrix<T, idx_t, Layout::RowMajor>> colIdx) noexcept
332{
333 assert(colIdx >= 0 and colIdx < ncols(A));
334 return LegacyVector<const T, idx_t, idx_t>(A.m, &A.ptr[colIdx], A.ldim);
335}
336
337// Diagonal of a LegacyMatrix
338template <typename T, class idx_t, Layout layout>
339constexpr auto diag(const LegacyMatrix<T, idx_t, layout>& A,
340 int diagIdx = 0) noexcept
341{
342 assert(diagIdx >= 0 || (idx_t)(-diagIdx) < nrows(A));
343 assert(diagIdx <= 0 || (idx_t)diagIdx < ncols(A));
344 T* ptr =
345 (layout == Layout::ColMajor)
346 ? ((diagIdx >= 0) ? &A.ptr[diagIdx * A.ldim] : &A.ptr[-diagIdx])
347 : ((diagIdx >= 0) ? &A.ptr[diagIdx] : &A.ptr[-diagIdx * A.ldim]);
348 idx_t n = (diagIdx >= 0) ? std::min(A.m + diagIdx, A.n) - (idx_t)diagIdx
349 : std::min(A.m, A.n - diagIdx) + (idx_t)diagIdx;
350
351 return LegacyVector<const T, idx_t, idx_t>(n, ptr, A.ldim + 1);
352}
353
354// Transpose view of a LegacyMatrix
355template <typename T, class idx_t>
356constexpr auto transpose_view(
358{
360 A.ldim);
361}
362template <typename T, class idx_t>
363constexpr auto transpose_view(
365{
367 A.ldim);
368}
369
370// slice LegacyVector
371template <typename T,
372 class idx_t,
373 typename int_t,
374 Direction direction,
375 class SliceSpec>
376constexpr auto slice(const LegacyVector<T, idx_t, int_t, direction>& v,
377 SliceSpec&& rows) noexcept
378{
379 assert((rows.first >= 0 and (idx_t) rows.first < size(v)) ||
380 rows.first == rows.second);
381 assert(rows.second >= 0 and (idx_t) rows.second <= size(v));
382 assert(rows.first <= rows.second);
384 rows.second - rows.first, &v.ptr[rows.first * v.inc], v.inc);
385}
386
387// -----------------------------------------------------------------------------
388// Block operations for non-const LegacyMatrix
389
390#define isSlice(SliceSpec) !std::is_convertible<SliceSpec, idx_t>::value
391
392// Slice LegacyMatrix
393template <
394 typename T,
395 class idx_t,
397 class SliceSpecRow,
398 class SliceSpecCol,
399 typename std::enable_if<isSlice(SliceSpecRow) && isSlice(SliceSpecCol),
400 int>::type = 0>
401constexpr auto slice(LegacyMatrix<T, idx_t, layout>& A,
402 SliceSpecRow&& rows,
403 SliceSpecCol&& cols) noexcept
404{
405 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
406 rows.first == rows.second);
407 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
408 assert(rows.first <= rows.second);
409 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
410 cols.first == cols.second);
411 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
412 assert(cols.first <= cols.second);
414 rows.second - rows.first, cols.second - cols.first,
415 (layout == Layout::ColMajor) ? &A.ptr[rows.first + cols.first * A.ldim]
416 : &A.ptr[rows.first * A.ldim + cols.first],
417 A.ldim);
418}
419
420#undef isSlice
421
422// Slice LegacyMatrix over a single row
423template <typename T, class idx_t, Layout layout, class SliceSpecCol>
424constexpr auto slice(LegacyMatrix<T, idx_t, layout>& A,
425 size_type<LegacyMatrix<T, idx_t, layout>> rowIdx,
426 SliceSpecCol&& cols) noexcept
427{
428 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
429 cols.first == cols.second);
430 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
431 assert(cols.first <= cols.second);
432 assert(rowIdx >= 0 and rowIdx < nrows(A));
434 cols.second - cols.first,
435 (layout == Layout::ColMajor) ? &A.ptr[rowIdx + cols.first * A.ldim]
436 : &A.ptr[rowIdx * A.ldim + cols.first],
437 layout == Layout::ColMajor ? A.ldim : 1);
438}
439
440// Slice LegacyMatrix over a single column
441template <typename T, class idx_t, Layout layout, class SliceSpecRow>
442constexpr auto slice(LegacyMatrix<T, idx_t, layout>& A,
443 SliceSpecRow&& rows,
444 size_type<LegacyMatrix<T, idx_t, layout>> colIdx) noexcept
445{
446 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
447 rows.first == rows.second);
448 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
449 assert(rows.first <= rows.second);
450 assert(colIdx >= 0 and colIdx < ncols(A));
452 rows.second - rows.first,
453 (layout == Layout::ColMajor) ? &A.ptr[rows.first + colIdx * A.ldim]
454 : &A.ptr[rows.first * A.ldim + colIdx],
455 layout == Layout::RowMajor ? A.ldim : 1);
456}
457
458// Get rows of LegacyMatrix
459template <typename T, class idx_t, Layout layout, class SliceSpec>
460constexpr auto rows(LegacyMatrix<T, idx_t, layout>& A,
461 SliceSpec&& rows) noexcept
462{
463 assert((rows.first >= 0 and (idx_t) rows.first < nrows(A)) ||
464 rows.first == rows.second);
465 assert(rows.second >= 0 and (idx_t) rows.second <= nrows(A));
466 assert(rows.first <= rows.second);
467 return LegacyMatrix<T, idx_t, layout>(rows.second - rows.first, A.n,
468 (layout == Layout::ColMajor)
469 ? &A.ptr[rows.first]
470 : &A.ptr[rows.first * A.ldim],
471 A.ldim);
472}
473
474// Get a row of a column-major LegacyMatrix
475template <typename T, class idx_t>
476constexpr auto row(LegacyMatrix<T, idx_t>& A,
477 size_type<LegacyMatrix<T, idx_t>> rowIdx) noexcept
478{
479 assert(rowIdx >= 0 and rowIdx < nrows(A));
480 return LegacyVector<T, idx_t, idx_t>(A.n, &A.ptr[rowIdx], A.ldim);
481}
482
483// Get a row of a row-major LegacyMatrix
484template <typename T, class idx_t>
485constexpr auto row(
487 size_type<LegacyMatrix<T, idx_t, Layout::RowMajor>> rowIdx) noexcept
488{
489 assert(rowIdx >= 0 and rowIdx < nrows(A));
490 return LegacyVector<T, idx_t>(A.n, &A.ptr[rowIdx * A.ldim]);
491}
492
493// Get columns of LegacyMatrix
494template <typename T, class idx_t, Layout layout, class SliceSpec>
495constexpr auto cols(LegacyMatrix<T, idx_t, layout>& A,
496 SliceSpec&& cols) noexcept
497{
498 assert((cols.first >= 0 and (idx_t) cols.first < ncols(A)) ||
499 cols.first == cols.second);
500 assert(cols.second >= 0 and (idx_t) cols.second <= ncols(A));
501 assert(cols.first <= cols.second);
502 return LegacyMatrix<T, idx_t, layout>(A.m, cols.second - cols.first,
503 (layout == Layout::ColMajor)
504 ? &A.ptr[cols.first * A.ldim]
505 : &A.ptr[cols.first],
506 A.ldim);
507}
508
509// Get a column of a column-major LegacyMatrix
510template <typename T, class idx_t>
511constexpr auto col(LegacyMatrix<T, idx_t>& A,
512 size_type<LegacyMatrix<T, idx_t>> colIdx) noexcept
513{
514 assert(colIdx >= 0 and colIdx < ncols(A));
515 return LegacyVector<T, idx_t>(A.m, &A.ptr[colIdx * A.ldim]);
516}
517
518// Get a column of a row-major LegacyMatrix
519template <typename T, class idx_t>
520constexpr auto col(
522 size_type<LegacyMatrix<T, idx_t, Layout::RowMajor>> colIdx) noexcept
523{
524 assert(colIdx >= 0 and colIdx < ncols(A));
525 return LegacyVector<T, idx_t, idx_t>(A.m, &A.ptr[colIdx], A.ldim);
526}
527
528// Diagonal of a LegacyMatrix
529template <typename T, class idx_t, Layout layout>
530constexpr auto diag(LegacyMatrix<T, idx_t, layout>& A, int diagIdx = 0) noexcept
531{
532 assert(diagIdx >= 0 || (idx_t)(-diagIdx) < nrows(A));
533 assert(diagIdx <= 0 || (idx_t)diagIdx < ncols(A));
534 T* ptr =
535 (layout == Layout::ColMajor)
536 ? ((diagIdx >= 0) ? &A.ptr[diagIdx * A.ldim] : &A.ptr[-diagIdx])
537 : ((diagIdx >= 0) ? &A.ptr[diagIdx] : &A.ptr[-diagIdx * A.ldim]);
538 idx_t n = (diagIdx >= 0) ? std::min(A.m + diagIdx, A.n) - (idx_t)diagIdx
539 : std::min(A.m, A.n - diagIdx) + (idx_t)diagIdx;
540
541 return LegacyVector<T, idx_t, idx_t>(n, ptr, A.ldim + 1);
542}
543
544// Transpose view of a LegacyMatrix
545template <typename T, class idx_t>
546constexpr auto transpose_view(
548{
549 return LegacyMatrix<T, idx_t, Layout::RowMajor>(A.n, A.m, A.ptr, A.ldim);
550}
551template <typename T, class idx_t>
552constexpr auto transpose_view(
554{
555 return LegacyMatrix<T, idx_t, Layout::ColMajor>(A.n, A.m, A.ptr, A.ldim);
556}
557
558// slice LegacyVector
559template <typename T,
560 class idx_t,
561 typename int_t,
562 Direction direction,
563 class SliceSpec>
564constexpr auto slice(LegacyVector<T, idx_t, int_t, direction>& v,
565 SliceSpec&& rows) noexcept
566{
567 assert((rows.first >= 0 and (idx_t) rows.first < size(v)) ||
568 rows.first == rows.second);
569 assert(rows.second >= 0 and (idx_t) rows.second <= size(v));
570 assert(rows.first <= rows.second);
572 rows.second - rows.first, &v.ptr[rows.first * v.inc], v.inc);
573}
574
575// Reshape LegacyMatrix
576template <typename T, class idx_t, Layout layout>
577auto reshape(LegacyMatrix<T, idx_t, layout>& A,
578 size_type<LegacyMatrix<T, idx_t>> m,
579 size_type<LegacyMatrix<T, idx_t>> n)
580{
581 using matrix_t = LegacyMatrix<T, idx_t, layout>;
582
583 // constants
584 const idx_t size = A.m * A.n;
585 const idx_t new_size = m * n;
586 const bool is_contiguous =
587 (size <= 1) ||
588 (layout == Layout::ColMajor && (A.ldim == A.m || A.n <= 1)) ||
589 (layout == Layout::RowMajor && (A.ldim == A.n || A.m <= 1));
590
591 // Check arguments
592 if (new_size > size)
593 throw std::domain_error("New size is larger than current size");
594
595 if (is_contiguous) {
596 return std::make_pair(
597 matrix_t(m, n, &A.ptr[0]),
598 (layout == Layout::ColMajor)
599 ? matrix_t(size - new_size, 1, &A.ptr[0] + new_size)
600 : matrix_t(1, size - new_size, &A.ptr[0] + new_size));
601 }
602 else {
603 if (m == A.m || n == 0)
604 return std::make_pair(cols(A, std::pair{(idx_t)0, n}),
605 cols(A, std::pair{n, A.n}));
606 else if (n == A.n || m == 0)
607 return std::make_pair(rows(A, std::pair{(idx_t)0, m}),
608 rows(A, std::pair{m, A.m}));
609 else
610 throw std::domain_error(
611 "Cannot reshape to non-contiguous matrix into a matrix if both "
612 "the number of rows and columns are different from the new "
613 "ones.");
614 }
615}
616template <typename T, class idx_t, Layout layout>
617auto reshape(LegacyMatrix<T, idx_t, layout>& A,
618 size_type<LegacyMatrix<T, idx_t>> n)
619{
620 using vector_t = LegacyVector<T, idx_t, idx_t>;
621 using matrix_t = LegacyMatrix<T, idx_t, layout>;
622
623 // constants
624 const idx_t size = A.m * A.n;
625 const bool is_contiguous =
626 (size <= 1) ||
627 (layout == Layout::ColMajor && (A.ldim == A.m || A.n <= 1)) ||
628 (layout == Layout::RowMajor && (A.ldim == A.n || A.m <= 1));
629
630 // Check arguments
631 if (n > size)
632 throw std::domain_error("New size is larger than current size");
633
634 if (is_contiguous) {
635 return std::make_pair(vector_t(n, &A.ptr[0]),
636 (layout == Layout::ColMajor)
637 ? matrix_t(size - n, 1, &A.ptr[0] + n)
638 : matrix_t(1, size - n, &A.ptr[0] + n));
639 }
640 else {
641 if (n == 0) {
642 return std::make_pair(vector_t(0, &A.ptr[0]), A);
643 }
644 else if (n == A.m) {
645 if constexpr (layout == Layout::ColMajor)
646 return std::make_pair(
647 vector_t(n, &A.ptr[0], 1),
648 matrix_t(A.m, A.n - 1, &A.ptr[0] + A.ldim, A.ldim));
649 else
650 return std::make_pair(
651 vector_t(n, &A.ptr[0], A.ldim),
652 matrix_t(A.m, A.n - 1, &A.ptr[0] + 1, A.ldim));
653 }
654 else if (n == A.n) {
655 if constexpr (layout == Layout::ColMajor)
656 return std::make_pair(
657 vector_t(n, &A.ptr[0], A.ldim),
658 matrix_t(A.m - 1, A.n, &A.ptr[0] + 1, A.ldim));
659 else
660 return std::make_pair(
661 vector_t(n, &A.ptr[0], 1),
662 matrix_t(A.m - 1, A.n, &A.ptr[0] + A.ldim, A.ldim));
663 }
664 else {
665 throw std::domain_error(
666 "Cannot reshape to non-contiguous matrix into a vector if the "
667 "new size is different from the number of rows and columns.");
668 }
669 }
670}
671
672// Reshape LegacyVector
673template <typename T, class idx_t, typename int_t, Direction direction>
675 size_type<LegacyMatrix<T, idx_t>> m,
676 size_type<LegacyMatrix<T, idx_t>> n)
677{
680
681 // constants
682 const idx_t new_size = m * n;
683 const idx_t s = v.n - new_size;
684 const bool is_contiguous = (v.inc == 1) || (v.n <= 1);
685
686 // Check arguments
687 if (new_size > v.n)
688 throw std::domain_error("New size is larger than current size");
689 if (!is_contiguous && m > 1)
690 throw std::domain_error(
691 "New sizes are not compatible with the current vector.");
692
693 if (is_contiguous) {
694 return std::make_pair(matrix_t(m, n, &v.ptr[0]),
695 vector_t(s, &v.ptr[0] + new_size));
696 }
697 else {
698 return std::make_pair(matrix_t(m, n, &v.ptr[0], v.inc),
699 vector_t(s, &v.ptr[0] + new_size * v.inc, v.inc));
700 }
701}
702template <typename T, class idx_t, typename int_t, Direction direction>
704 size_type<LegacyMatrix<T, idx_t>> n)
705{
706 // Check arguments
707 if (n > v.n)
708 throw std::domain_error("New size is larger than current size");
709
710 return std::make_pair(slice(v, std::pair{(idx_t)0, n}),
711 slice(v, std::pair{n, v.n}));
712}
713
714// -----------------------------------------------------------------------------
715// Deduce matrix and vector type from two provided ones
716
717namespace traits {
718
719 template <typename T>
720 constexpr bool cast_to_legacy_type =
721 is_legacy_type<T> || is_stdvector_type<T>
722#ifdef TLAPACK_EIGEN_HH
723 || is_eigen_type<T>
724#endif
725#ifdef TLAPACK_MDSPAN_HH
726 || is_mdspan_type<T>
727#endif
728 ;
729
730 // for two types
731 // should be especialized for every new matrix class
732 template <class matrixA_t, typename matrixB_t>
734 matrixA_t,
735 matrixB_t,
736 typename std::enable_if<
737 ((is_legacy_type<matrixA_t> ||
738 is_legacy_type<matrixB_t>)&&cast_to_legacy_type<matrixA_t> &&
739 cast_to_legacy_type<matrixB_t>),
740 int>::type> {
742 using idx_t = size_type<matrixA_t>;
743
744 static constexpr Layout LA = layout<matrixA_t>;
745 static constexpr Layout LB = layout<matrixB_t>;
746 static constexpr Layout L =
747 ((LA == Layout::RowMajor) && (LB == Layout::RowMajor))
748 ? Layout::RowMajor
749 : Layout::ColMajor;
750
751 using type = LegacyMatrix<T, idx_t, L>;
752 };
753
754 // for two types
755 // should be especialized for every new vector class
756 template <typename vecA_t, typename vecB_t>
758 vecA_t,
759 vecB_t,
760 typename std::enable_if<
761 ((is_legacy_type<vecA_t> ||
762 is_legacy_type<vecB_t>)&&cast_to_legacy_type<vecA_t> &&
763 cast_to_legacy_type<vecB_t>),
764 int>::type> {
766 using idx_t = size_type<vecA_t>;
767
769 };
770
771#if !defined(TLAPACK_EIGEN_HH) && !defined(TLAPACK_MDSPAN_HH)
772 template <class vecA_t, class vecB_t>
773 struct matrix_type_traits<
774 vecA_t,
775 vecB_t,
776 std::enable_if_t<traits::is_stdvector_type<vecA_t> &&
777 traits::is_stdvector_type<vecB_t>,
778 int>> {
780 using type = LegacyMatrix<T>;
781 };
782
783 template <class vecA_t, class vecB_t>
784 struct vector_type_traits<
785 vecA_t,
786 vecB_t,
787 std::enable_if_t<traits::is_stdvector_type<vecA_t> &&
788 traits::is_stdvector_type<vecB_t>,
789 int>> {
791 using type = LegacyVector<T>;
792 };
793#endif
794
795} // namespace traits
796
797// -----------------------------------------------------------------------------
798// Cast to Legacy arrays
799
800template <typename T, class idx_t, Layout layout>
801constexpr auto legacy_matrix(const LegacyMatrix<T, idx_t, layout>& A) noexcept
802{
803 return legacy::Matrix<T, idx_t>{layout, A.m, A.n, A.ptr, A.ldim};
804}
805
806template <class T, class idx_t, class int_t, Direction direction>
807constexpr auto legacy_matrix(
809{
810 return legacy::Matrix<T, idx_t>{Layout::ColMajor, 1, v.n, v.ptr,
811 (idx_t)v.inc};
812}
813
814template <typename T, class idx_t, typename int_t, Direction direction>
815constexpr auto legacy_vector(
817{
818 assert(direction == Direction::Forward || std::is_signed<idx_t>::value ||
819 v.inc == 0);
820
821 return legacy::Vector<T, idx_t>{
822 v.n, v.ptr,
823 (direction == Direction::Forward) ? idx_t(v.inc) : idx_t(-v.inc)};
824}
825
826} // namespace tlapack
827
828#endif // TLAPACK_LEGACYARRAY_HH
constexpr Layout layout
Layout of a matrix or vector.
Definition arrayTraits.hpp:232
Layout
Definition types.hpp:24
@ ColMajor
Column-major layout.
@ RowMajor
Row-major layout.
constexpr auto diag(T &A, int diagIdx=0) noexcept
Get the Diagonal of an Eigen Matrix.
Definition eigen.hpp:576
Concept for types that represent tlapack::Direction.
Concept for matrices that can be converted to a legacy matrix.
Concept for vectors that can be converted to a legacy vector.
constexpr bool is_legacy_type
True if T is a legacy array.
Definition legacyArray.hpp:41
typename traits::real_type_traits< Types..., int >::type real_type
The common real type of the list of types.
Definition scalar_type_traits.hpp:113
Legacy matrix.
Definition LegacyMatrix.hpp:34
Legacy vector.
Definition LegacyVector.hpp:42
Functor for data creation.
Definition arrayTraits.hpp:89
constexpr auto operator()(std::vector< T > &v, idx_t m, idx_t n=1) const
Creates a m-by-n matrix with entries of type T.
Definition arrayTraits.hpp:105
Functor for data creation with static size.
Definition arrayTraits.hpp:141
constexpr auto operator()(T *v) const
Creates a m-by-n matrix or, if n == -1, a vector of size m.
Definition arrayTraits.hpp:157
Complex type traits for the list of types Types.
Definition scalar_type_traits.hpp:145
Trait to determine the layout of a given data structure.
Definition arrayTraits.hpp:75
Matrix type deduction.
Definition arrayTraits.hpp:176
Real type traits for the list of types Types.
Definition scalar_type_traits.hpp:71
Vector type deduction.
Definition arrayTraits.hpp:203