485 class BATCHLAS_API MatrixView {
501 template <typename U = T, MatrixFormat M = MType>
502 requires DenseMatrixFormat<M>
503 MatrixView(T* data, int rows, int cols, int ld = 0,
504 int stride = 0, int batch_size = 1, T** data_ptrs = nullptr);
508 template <typename U = T, MatrixFormat M = MType>
509 requires CsrMatrixFormat<M>
510 MatrixView(T* data, int* row_offsets, int* col_indices,
511 int rows, int cols, NonZeros nnz, int matrix_stride = 0,
512 int offset_stride = 0, int batch_size = 1, T** data_ptrs = nullptr);
515 template <typename U = T, MatrixFormat M = MType>
516 requires CsrMatrixFormat<M>
517 MatrixView(T* data, int* row_offsets, int* col_indices,
518 int nnz, int rows, int cols, int matrix_stride = 0,
519 int offset_stride = 0, int batch_size = 1, T** data_ptrs = nullptr) = delete;
523 template <typename U = T, MatrixFormat M = MType>
524 requires DenseMatrixFormat<M>
525 MatrixView(const VectorView<T>& vector_view, VectorOrientation orientation = VectorOrientation::Column);
530 template <typename U = T, MatrixFormat M = MType>
531 requires DenseMatrixFormat<M>
532 MatrixView(const MatrixView<T, MType>& matrix_view,
533 int rows = -1, int cols = -1, int ld = -1, int stride = -1, int batch_size = -1);
536 MatrixView() = default;
542 static Event copy(Queue& ctx, const MatrixView<T, MType>& dest, const MatrixView<T, MType>& src);
547 MatrixView(const MatrixView&) = default;
548 MatrixView& operator=(const MatrixView&) = default;
549 MatrixView(MatrixView&&) noexcept = default;
550 MatrixView& operator=(MatrixView&&) noexcept = default;
554 ~MatrixView() = default;
560 BackendMatrixHandle<T, MType>* operator->() const;
562 BackendMatrixHandle<T, MType>& operator*() const;
565 MatrixView<T, MType> operator[](int i) const;
573 int rows_ = 0, cols_ = 0, batch_size_ = 0;
577 Span<T> data() const { return data_; }
582 Event set_access_device(const Queue& ctx) const {
583 if constexpr (MType == MatrixFormat::CSR) {
584 (void)row_offsets_.set_access_device(ctx);
585 (void)col_indices_.set_access_device(ctx);
587 return data_.set_access_device(ctx);
591 Event prefetch(const Queue& ctx) const {
592 if constexpr (MType == MatrixFormat::CSR) {
593 (void)row_offsets_.prefetch(ctx);
594 (void)col_indices_.prefetch(ctx);
596 return data_.prefetch(ctx);
600 T* data_ptr() const { return data_.data(); }
603 int batch_size() const { return batch_size_; }
605 int rows() const { return rows_; }
607 int rows(int batch_index) const {
608 return detail::dense_active_rows(rows_, active_rows_, batch_index);
611 int cols() const { return cols_; }
613 int cols(int batch_index) const {
614 return detail::dense_active_cols(cols_, active_cols_, batch_index);
617 int rows_capacity() const { return rows_; }
619 int cols_capacity() const { return cols_; }
621 bool is_heterogeneous() const { return !active_rows_.empty() || !active_cols_.empty(); }
624 template <MatrixFormat M = MType>
625 requires DenseMatrixFormat<M>
626 Span<int> active_rows() const { return active_rows_; }
629 template <MatrixFormat M = MType>
630 requires DenseMatrixFormat<M>
631 Span<int> active_cols() const { return active_cols_; }
634 template <typename U>
635 Matrix<U, MType> astype() const;
649 using promoted_type = std::conditional_t<is_std_complex_v<T>, std::complex<double>, double>;
652 template <typename U = T>
653 requires(std::is_floating_point_v<U> || is_std_complex_v<U>)
654 static promoted_type up(U x) { return promoted_type(x); }
657 template <typename U = T>
658 requires(std::is_floating_point_v<U> || is_std_complex_v<U>)
659 static U make(double re, double im = 0.0) {
660 if constexpr (is_std_complex_v<U>) return U(float_t<U>(re), float_t<U>(im));
661 else { (void)im; return U(re); }
665 template <typename U = T>
666 requires(std::is_floating_point_v<U> || is_std_complex_v<U>)
668 if constexpr (is_std_complex_v<U>) return std::conj(x);
673 template <typename U = T>
674 requires(std::is_floating_point_v<U> || is_std_complex_v<U>)
675 static double cabs1(U x) {
676 if constexpr (is_std_complex_v<U>) return std::fabs(double(x.real())) + std::fabs(double(x.imag()));
677 else return std::fabs(double(x));
681 template <typename U = T>
682 requires(std::is_floating_point_v<U> || is_std_complex_v<U>)
683 static bool finite(U x) {
684 if constexpr (is_std_complex_v<U>) return std::isfinite(double(x.real())) && std::isfinite(double(x.imag()));
685 else return std::isfinite(double(x));
689 std::vector<int> all_items() const;
692 std::vector<int> default_items() const;
697 template <typename U>
698 Matrix<U, MType> astype(std::span<const int> items) const;
703 static Event product(const Queue& ctx, const MatrixView& A, Transpose ta, const MatrixView& B, Transpose tb,
704 const MatrixView& C);
708 static double potrf_residual(Queue& ctx, const MatrixView& A0, const MatrixView& F, Uplo uplo,
709 std::span<const int> items = {});
713 static double getrf_residual(Queue& ctx, const MatrixView& A0, const MatrixView& F,
714 const VectorView<std::int32_t>& piv, std::span<const int> items = {});
717 static double qr_residual(Queue& ctx, const MatrixView& A0, const MatrixView& F, const VectorView<T>& tau,
718 std::span<const int> items = {});
722 static Matrix<promoted_type, MType> form_q(Queue& ctx, const MatrixView& F, const VectorView<T>& tau, int item,
727 static Matrix<promoted_type, MType> form_q(Queue& ctx, const MatrixView& F, const VectorView<T>& tau,
728 std::span<const int> items, int cols);
732 static double qr_reconstruction(Queue& ctx, const MatrixView& A0, const MatrixView& Q, const MatrixView& R,
733 std::span<const int> items = {});
736 static double similarity_residual(Queue& ctx, const MatrixView& A0, const MatrixView& Q, const MatrixView& B,
737 std::span<const int> items = {});
742 static double svd_residual(Queue& ctx, const MatrixView& A0, const MatrixView& U, const VectorView<float_t<T>>& s,
743 const MatrixView& Vh, std::span<const int> items = {});
747 static double solve_residual(Queue& ctx, const MatrixView& A0, Transpose ta, const MatrixView& X,
748 const MatrixView& B0, std::span<const int> items = {},
749 double full_limit = double(1 << 28));
752 static double solve_residual(Queue& ctx, const MatrixView& A0, const MatrixView& X, const MatrixView& B0,
753 std::span<const int> items = {});
757 static double lu_solve_residual(Queue& ctx, const MatrixView& F, const VectorView<std::int32_t>& piv,
758 Transpose ta, const MatrixView& X, const MatrixView& B0,
759 std::span<const int> items = {}, double full_limit = double(1 << 28));
763 static double gemm_backward_error(Queue& ctx, const MatrixView& A, Transpose ta, const MatrixView& B, Transpose tb,
764 const MatrixView& C0, const MatrixView& C, promoted_type alpha,
765 promoted_type beta, std::span<const int> items = {},
766 std::optional<Uplo> c_triangle = std::nullopt);
770 static double gemm_max_denominator(Queue& ctx, const MatrixView& A, Transpose ta, const MatrixView& B,
771 Transpose tb, const MatrixView& C0, promoted_type alpha, promoted_type beta,
772 std::span<const int> items = {});
775 static double gemv_backward_error(Queue& ctx, const MatrixView& A, Transpose ta, const VectorView<T>& x,
776 const VectorView<T>& y0, const VectorView<T>& y, promoted_type alpha,
777 promoted_type beta, std::span<const int> items = {});
781 static double trsm_residual(Queue& ctx, const MatrixView& A, Side side, Uplo uplo, Transpose ta, Diag diag,
782 const MatrixView& X, const MatrixView& B0, promoted_type alpha,
783 std::span<const int> items = {});
786 static double spmm_backward_error(Queue& ctx, const MatrixView<T, MatrixFormat::CSR>& A, Transpose ta,
787 const MatrixView& B, Transpose tb, const MatrixView& C0, const MatrixView& C,
788 promoted_type alpha, promoted_type beta, std::span<const int> items = {});
792 static double rank2k_backward_error(Queue& ctx, const MatrixView& A, const MatrixView& B, Transpose trans,
793 const MatrixView& C0, const MatrixView& C, Uplo uplo, promoted_type alpha,
794 promoted_type beta, bool hermitian, std::span<const int> items = {});
797 static double orthogonality(Queue& ctx, const MatrixView& Q, std::span<const int> items = {});
800 static double eigen_residual(Queue& ctx, const MatrixView& A, const MatrixView& V, const VectorView<float_t<T>>& w,
801 std::span<const int> items = {});
804 static double values_error(const VectorView<float_t<T>>& w, const std::vector<std::vector<double>>& ref,
805 double scale, std::span<const int> items = {});
809 static double pivot_ratio(const MatrixView& F, std::span<const int> items = {});
812 static bool pivots_valid(const VectorView<std::int32_t>& piv, int n);
816 template <MatrixFormat M = MType>
817 requires DenseMatrixFormat<M>
818 int ld() const { return ld_; }
821 template <MatrixFormat M = MType>
822 requires DenseMatrixFormat<M>
823 int stride() const { return stride_; }
826 template <MatrixFormat M = MType>
827 requires DenseMatrixFormat<M>
828 int inc() const { return 1; }
831 template <MatrixFormat M = MType>
832 requires CsrMatrixFormat<M>
833 Span<int> row_offsets() const { return row_offsets_; }
836 template <MatrixFormat M = MType>
837 requires CsrMatrixFormat<M>
838 Span<int> col_indices() const { return col_indices_; }
841 template <MatrixFormat M = MType>
842 requires CsrMatrixFormat<M>
843 int nnz() const { return nnz_; }
846 template <MatrixFormat M = MType>
847 requires CsrMatrixFormat<M>
848 int nnz_capacity() const { return matrix_stride_; }
853 template <MatrixFormat M = MType>
854 requires CsrMatrixFormat<M>
855 int nnz(int batch_index) const {
856 const std::size_t base = static_cast<std::size_t>(batch_index) *
857 static_cast<std::size_t>(offset_stride_);
858 return row_offsets_[base + static_cast<std::size_t>(rows_)] - row_offsets_[base];
862 template <MatrixFormat M = MType>
863 requires CsrMatrixFormat<M>
864 int matrix_stride() const { return matrix_stride_; }
867 template <MatrixFormat M = MType>
868 requires CsrMatrixFormat<M>
869 int offset_stride() const { return offset_stride_; }
876 Span<T*> data_ptrs(Queue& ctx) const {
877 init_data_ptr_array(ctx);
883 template <MatrixFormat M = MType>
884 requires DenseMatrixFormat<M>
885 T& at(int row, int col, int batch = 0);
889 template <MatrixFormat M = MType>
890 requires DenseMatrixFormat<M>
891 const T& at(int row, int col, int batch = 0) const;
894 template <MatrixFormat M = MType>
895 requires DenseMatrixFormat<M>
896 T& operator()(int row, int col, int batch = 0) {
897 return at(row, col, batch);
901 template <MatrixFormat M = MType>
902 requires DenseMatrixFormat<M>
903 const T& operator()(int row, int col, int batch = 0) const {
904 return at(row, col, batch);
909 template <MatrixFormat M = MType>
910 requires DenseMatrixFormat<M>
911 MatrixView<T, MType> operator()(Slice rows, Slice cols) const {
912 auto [r_start, r_len] = detail::checked_slice_component(rows, rows_);
913 auto [c_start, c_len] = detail::checked_slice_component(cols, cols_);
914 if (r_len <= 0 || c_len <= 0) {
915 throw batchlas::invalid_argument("Invalid slice dimensions: " + std::to_string(r_len) + "x" + std::to_string(c_len));
917 auto offset = c_start * ld_ + r_start;
921 return MatrixView<T, MType>(data_ptr() + offset, static_cast<int>(r_len), static_cast<int>(c_len), ld_, stride_, batch_size_, data_ptrs_.data());
925 template <MatrixFormat M = MType>
926 requires DenseMatrixFormat<M>
927 MatrixView<T, MType> operator()(Slice rows) const {
928 return (*this)(rows, {});
933 template <MatrixFormat M = MType>
934 requires DenseMatrixFormat<M>
935 VectorView<T> operator()(int32_t row, Slice cols) const {
936 auto [c_start, c_len] = detail::checked_slice_component(cols, cols_);
938 throw batchlas::invalid_argument("Invalid slice dimensions for row vector: " + std::to_string(c_len));
940 auto offset = c_start * ld_ + row;
941 return VectorView<T>(data_ptr() + offset, static_cast<int>(c_len), batch_size_, ld_, stride_);
946 template <MatrixFormat M = MType>
947 requires DenseMatrixFormat<M>
948 VectorView<T> operator()(Slice rows, int32_t col) const {
949 auto [r_start, r_len] = detail::checked_slice_component(rows, rows_);
951 throw batchlas::invalid_argument("Invalid slice dimensions for column vector: " + std::to_string(r_len));
953 auto offset = col * ld_ + r_start;
954 return VectorView<T>(data_ptr() + offset, static_cast<int>(r_len), batch_size_, 1, stride_);
965 template <MatrixFormat M = MType>
966 requires DenseMatrixFormat<M>
967 Event symmetrize(const Queue& ctx, Uplo uplo) const;
970 template <MatrixFormat M = MType>
971 requires DenseMatrixFormat<M>
972 Event symmetrize(Uplo uplo) const {
973 return symmetrize(Queue(Device::default_device_for<T>()), uplo);
978 template <MatrixFormat M = MType>
979 requires DenseMatrixFormat<M>
980 Event hermitize(const Queue& ctx, Uplo uplo) const;
983 template <MatrixFormat M = MType>
984 requires DenseMatrixFormat<M>
985 Event hermitize(Uplo uplo) const {
986 return hermitize(Queue(Device::default_device_for<T>()), uplo);
991 template <MatrixFormat M = MType>
992 requires DenseMatrixFormat<M>
993 Event transpose(const Queue& ctx, bool conjugate = false) const;
996 template <MatrixFormat M = MType>
997 requires DenseMatrixFormat<M>
998 Event transpose(bool conjugate = false) const {
999 return transpose(Queue(Device::default_device_for<T>()), conjugate);
1006 template <MatrixFormat M = MType>
1007 requires DenseMatrixFormat<M>
1008 Event triangularize(const Queue& ctx, Uplo uplo, Diag diag) const;
1011 template <MatrixFormat M = MType>
1012 requires DenseMatrixFormat<M>
1013 Event triangularize(Uplo uplo, Diag diag) const {
1014 return triangularize(Queue(Device::default_device_for<T>()), uplo, diag);
1020 template <MatrixFormat M = MType>
1021 requires DenseMatrixFormat<M>
1022 Event fill_random(const Queue& ctx, bool hermitian = false, unsigned int seed = 42) const;
1025 template <MatrixFormat M = MType>
1026 requires DenseMatrixFormat<M>
1027 Event fill_random(bool hermitian = false, unsigned int seed = 42) const {
1028 return fill_random(Queue(Device::default_device_for<T>()), hermitian, seed);
1037 template <MatrixFormat M = MType>
1038 requires CsrMatrixFormat<M>
1039 Event fill_random_sparse_hermitian(const Queue& ctx,
1041 unsigned int seed = 42,
1042 typename base_type<T>::type diagonal_boost = typename base_type<T>::type(1),
1043 bool shared_pattern = true) const;
1046 template <MatrixFormat M = MType>
1047 requires CsrMatrixFormat<M>
1048 Event fill_random_sparse_hermitian(float density,
1049 unsigned int seed = 42,
1050 typename base_type<T>::type diagonal_boost = typename base_type<T>::type(1),
1051 bool shared_pattern = true) const {
1052 return fill_random_sparse_hermitian(Queue(Device::default_device_for<T>()), density, seed, diagonal_boost, shared_pattern);
1056 Event fill(const Queue& ctx, T value) const;
1059 Event fill(T value) const {
1060 return fill(Queue(Device::default_device_for<T>()), value);
1064 Event fill_zeros(const Queue& ctx) const {
1065 return fill(ctx, detail::convert_to_fill_value<T>(0));
1069 template <MatrixFormat M = MType>
1070 requires DenseMatrixFormat<M>
1071 Event fill_identity(const Queue& ctx, T value = T(1)) const;
1078 template <MatrixFormat M = MType>
1079 requires DenseMatrixFormat<M>
1080 Event fill_diagonal(const Queue& ctx, const Span<T>& diag_values, int64_t k = 0) const;
1085 template <MatrixFormat M = MType>
1086 requires DenseMatrixFormat<M>
1087 Event fill_diagonal(const Queue& ctx, const VectorView<T>& diag_values, int64_t k = 0) const;
1090 template <MatrixFormat M = MType>
1091 requires DenseMatrixFormat<M>
1092 Event fill_diagonal(const Span<T>& diag_values, int64_t k = 0) const {
1093 return fill_diagonal(Queue(Device::default_device_for<T>()), diag_values, k);
1097 template <MatrixFormat M = MType>
1098 requires DenseMatrixFormat<M>
1099 Event fill_diagonal(const Queue& ctx, const T& value) const;
1102 template <MatrixFormat M = MType>
1103 requires DenseMatrixFormat<M>
1104 Event fill_diagonal(const T& value) const {
1105 return fill_diagonal(Queue(Device::default_device_for<T>()), value);
1110 template <MatrixFormat M = MType>
1111 requires DenseMatrixFormat<M>
1112 Event fill_triangular(const Queue& ctx, Uplo uplo, T diagonal_value = T(1),
1113 T non_diagonal_value = T(0.5)) const;
1116 template <MatrixFormat M = MType>
1117 requires DenseMatrixFormat<M>
1118 Event fill_triangular(Uplo uplo, T diagonal_value = T(1),
1119 T non_diagonal_value = T(0.5)) const {
1120 return fill_triangular(Queue(Device::default_device_for<T>()), uplo, diagonal_value, non_diagonal_value);
1124 template <MatrixFormat M = MType>
1125 requires DenseMatrixFormat<M>
1126 Event fill_tridiag(const Queue& ctx, VectorView<T> sub_diag,
1127 VectorView<T> diag, VectorView<T> super_diag) const {
1130 (void)fill_diagonal(ctx, diag);
1131 (void)fill_diagonal(ctx, sub_diag, -1);
1132 return fill_diagonal(ctx, super_diag, 1);
1137 template <MatrixFormat M = MType>
1138 requires DenseMatrixFormat<M>
1139 Event fill_tridiag_toeplitz(const Queue& ctx, T diag = T(1),
1140 T sub_diag = T(-0.5), T super_diag = T(0.5)) const;
1143 template <MatrixFormat M = MType>
1144 requires DenseMatrixFormat<M>
1145 Event fill_tridiag_toeplitz(T diag = T(1),
1146 T sub_diag = T(-0.5), T super_diag = T(0.5)) const {
1147 return fill_tridiag_toeplitz(Queue(Device::default_device_for<T>()), diag, sub_diag, super_diag);
1154 template <MatrixFormat M = MType>
1155 requires DenseMatrixFormat<M>
1156 Event fill_triangular_random(const Queue& ctx, Uplo uplo,
1157 Diag diag = Diag::Unit,
1158 unsigned int seed = 42) const;
1161 template <MatrixFormat M = MType>
1162 requires DenseMatrixFormat<M>
1163 Event fill_triangular_random(Uplo uplo,
1164 Diag diag = Diag::Unit,
1165 unsigned int seed = 42) const {
1166 return fill_triangular_random(Queue(Device::default_device_for<T>()), uplo, diag, seed);
1176 template <MatrixFormat M = MType>
1177 requires DenseMatrixFormat<M>
1178 Event fill_random_spd(const Queue& ctx, unsigned int seed = 42) const;
1181 template <MatrixFormat M = MType>
1182 requires DenseMatrixFormat<M>
1183 Event fill_random_spd(unsigned int seed = 42) const {
1184 return fill_random_spd(Queue(Device::default_device_for<T>()), seed);
1194 template <MatrixFormat M = MType>
1195 requires DenseMatrixFormat<M>
1196 Event fill_random_pivoted(const Queue& ctx, unsigned int seed = 42) const;
1199 template <MatrixFormat M = MType>
1200 requires DenseMatrixFormat<M>
1201 Event fill_random_pivoted(unsigned int seed = 42) const {
1202 return fill_random_pivoted(Queue(Device::default_device_for<T>()), seed);
1213 template <MatrixFormat M = MType>
1214 requires DenseMatrixFormat<M>
1215 Event fill_graded_hermitian(const Queue& ctx, double log10_cond, unsigned int seed = 42) const;
1218 template <MatrixFormat M = MType>
1219 requires DenseMatrixFormat<M>
1220 Event fill_graded_hermitian(double log10_cond, unsigned int seed = 42) const {
1221 return fill_graded_hermitian(Queue(Device::default_device_for<T>()), log10_cond, seed);
1232 template <MatrixFormat M = MType>
1233 requires DenseMatrixFormat<M>
1234 Event fill_near_degenerate_hermitian(const Queue& ctx, double noise, unsigned int seed = 42) const;
1242 MatrixView<T, MType> batch_item(int batch_index) const;
1246 template <MatrixFormat M = MType>
1247 requires DenseMatrixFormat<M>
1248 MatrixView<T, MType> with_active_dims(Span<int> active_rows, Span<int> active_cols) const {
1249 detail::validate_dense_active_dims(rows_, cols_, batch_size_, active_rows, active_cols);
1250 MatrixView<T, MType> out = *this;
1251 out.active_rows_ = active_rows;
1252 out.active_cols_ = active_cols;
1263 static bool all_close(Queue& ctx, const MatrixView<T, MType>& a, const MatrixView<T, MType>& b, float_t<T> tol = std::numeric_limits<float_t<T>>::epsilon());
1267 std::ostream& stream_formatted_to(std::ostream& os, int max_rows_to_print = 10, int max_cols_to_print = 10, int max_elements_to_print_csr = 20) const {
1268 std::ios_base::fmtflags original_flags = os.flags();
1269 os << std::scientific << std::setprecision(4);
1271 for (int b_idx = 0; b_idx < batch_size_; ++b_idx) {
1272 if (batch_size_ > 1) {
1273 os << "Batch " << b_idx << ":\n";
1275 MatrixView<T, MType> current_item_view = this->batch_item(b_idx);
1277 if constexpr (MType == MatrixFormat::Dense) {
1278 for (int r = 0; r < std::min(current_item_view.rows_, max_rows_to_print); ++r) {
1280 for (int c = 0; c < std::min(current_item_view.cols_, max_cols_to_print); ++c) {
1281 detail::print_with_width(os, current_item_view.at(r, c, 0), 13);
1283 if (current_item_view.cols_ > max_cols_to_print) {
1288 if (current_item_view.rows_ > max_rows_to_print) {
1291 } else if constexpr (MType == MatrixFormat::CSR) {
1292 os << "CSR Matrix (rows: " << current_item_view.rows_
1293 << ", cols: " << current_item_view.cols_
1294 << ", nnz: " << current_item_view.nnz_ << ")\n";
1297 for (int i = 0; i < std::min(current_item_view.nnz_, max_elements_to_print_csr); ++i) {
1298 os << std::setw(13) << current_item_view.data()[i] << (i == std::min(current_item_view.nnz_, max_elements_to_print_csr) - 1 ? "" : ", ");
1300 if (current_item_view.nnz_ > max_elements_to_print_csr) os << " ...";
1303 os << " Row Offsets: [";
1305 int num_row_offsets = current_item_view.rows_ + 1;
1306 for (int i = 0; i < std::min(num_row_offsets, max_elements_to_print_csr); ++i) {
1307 os << std::setw(6) << current_item_view.row_offsets()[i] << (i == std::min(num_row_offsets, max_elements_to_print_csr) - 1 ? "" : ", ");
1309 if (num_row_offsets > max_elements_to_print_csr) os << " ...";
1312 os << " Col Indices: [";
1313 for (int i = 0; i < std::min(current_item_view.nnz_, max_elements_to_print_csr); ++i) {
1314 os << std::setw(6) << current_item_view.col_indices()[i] << (i == std::min(current_item_view.nnz_, max_elements_to_print_csr) - 1 ? "" : ", ");
1316 if (current_item_view.nnz_ > max_elements_to_print_csr) os << " ...";
1319 if (b_idx < batch_size_ - 1) {
1323 os.flags(original_flags);
1328 void print(std::ostream& os = std::cout, int max_rows_to_print = 10, int max_cols_to_print = 10, int max_elements_to_print_csr = 20) const {
1329 stream_formatted_to(os, max_rows_to_print, max_cols_to_print, max_elements_to_print_csr);
1333 KernelMatrixView<T, MType> kernel_view() const noexcept {
1334 KernelMatrixView<T, MType> kv;
1335 kv.data_ = const_cast<T*>(data_.data());
1339 kv.stride_ = stride_;
1340 kv.active_rows_ = active_rows_.empty() ? nullptr : active_rows_.data();
1341 kv.active_cols_ = active_cols_.empty() ? nullptr : active_cols_.data();
1342 kv.batch_size_ = batch_size_;
1343 if constexpr (MType == MatrixFormat::CSR) {
1344 kv.row_offsets_ = const_cast<int*>(row_offsets_.data());
1345 kv.col_indices_ = const_cast<int*>(col_indices_.data());
1347 kv.matrix_stride_ = matrix_stride_;
1348 kv.offset_stride_ = offset_stride_;
1354 void init_data_ptr_array(Queue& ctx, Span<T*> target = {}) const;
1360 Span<int> active_rows_;
1361 Span<int> active_cols_;
1363 Span<T*> data_ptrs_;
1365 Span<int> row_offsets_;
1366 Span<int> col_indices_;
1368 int matrix_stride_ = 0;
1369 int offset_stride_ = 0;
1372 mutable std::shared_ptr<BackendMatrixHandle<T, MType>> backend_handle_;
1399 class BATCHLAS_API Matrix : public MatrixView<T, MType> {
1400 using Base = MatrixView<T, MType>;
1401 using Base::ld_, Base::stride_, Base::nnz_, Base::matrix_stride_, Base::offset_stride_;
1404 using Base::rows_, Base::cols_, Base::batch_size_;
1416 template <typename U = T, MatrixFormat M = MType>
1417 requires DenseMatrixFormat<M>
1418 Matrix(int rows, int cols, int batch_size = 1, int ld = 0, int stride = 0);
1425 template <typename U = T, MatrixFormat M = MType>
1426 requires CsrMatrixFormat<M>
1427 Matrix(int rows, int cols, NonZeros nnz, int batch_size = 1);
1430 template <typename U = T, MatrixFormat M = MType>
1431 requires CsrMatrixFormat<M>
1432 Matrix(int rows, int cols, int nnz, int batch_size = 1) = delete;
1448 template <typename U = T, MatrixFormat M = MType>
1449 requires DenseMatrixFormat<M>
1450 Matrix(const T* data, int rows, int cols, int ld, int stride = 0, int batch_size = 1);
1454 template <typename U = T, MatrixFormat M = MType>
1455 requires DenseMatrixFormat<M>
1456 Matrix(Span<const T> data, int rows, int cols, int ld, int stride = 0, int batch_size = 1);
1459 template <typename U = T, MatrixFormat M = MType>
1460 requires DenseMatrixFormat<M>
1461 Matrix(Span<T> data, int rows, int cols, int ld, int stride = 0, int batch_size = 1)
1462 : Matrix(Span<const T>(data.data(), data.size()), rows, cols, ld, stride, batch_size) {}
1474 template <typename U = T, MatrixFormat M = MType>
1475 requires CsrMatrixFormat<M>
1476 Matrix(const T* values, const int* row_offsets, const int* col_indices,
1477 int rows, int cols, NonZeros nnz, int matrix_stride = 0,
1478 int offset_stride = 0, int batch_size = 1);
1481 template <typename U = T, MatrixFormat M = MType>
1482 requires CsrMatrixFormat<M>
1483 Matrix(const T* values, const int* row_offsets, const int* col_indices,
1484 int nnz, int rows, int cols, int matrix_stride = 0,
1485 int offset_stride = 0, int batch_size = 1) = delete;
1494 template <typename U = T, MatrixFormat M = MType>
1495 requires DenseMatrixFormat<M>
1496 static Matrix<T, MType> Identity(int n, int batch_size = 1);
1504 template <typename U = T, MatrixFormat M = MType>
1505 requires DenseMatrixFormat<M>
1506 static Matrix<T, MType> Random(int rows, int cols, bool hermitian = false, int batch_size = 1, unsigned int seed = 42);
1509 template <typename U = T, MatrixFormat M = MType>
1510 requires CsrMatrixFormat<M>
1511 static Matrix<T, MType> RandomSparseHermitian(int n,
1514 unsigned int seed = 42,
1515 typename base_type<T>::type diagonal_boost = typename base_type<T>::type(1),
1516 bool shared_pattern = true);
1519 template <typename U = T, MatrixFormat M = MType>
1520 requires DenseMatrixFormat<M>
1521 static Matrix<T, MType> RandomTriangular(int n, Uplo uplo, Diag diag = Diag::NonUnit, int batch_size = 1, unsigned int seed = 42) {
1522 auto result = Matrix<T, MType>(n, n, batch_size);
1523 result.fill_triangular_random(uplo, diag, seed).wait();
1528 template <typename U = T, MatrixFormat M = MType>
1529 requires DenseMatrixFormat<M>
1530 static Matrix<T, MType> Zeros(int rows, int cols, int batch_size = 1);
1533 template <typename U = T, MatrixFormat M = MType>
1534 requires DenseMatrixFormat<M>
1535 static Matrix<T, MType> Ones(int rows, int cols, int batch_size = 1);
1538 template <typename U = T, MatrixFormat M = MType>
1539 requires DenseMatrixFormat<M>
1540 static Matrix<T, MType> Diagonal(const Span<T>& diag_values, int batch_size = 1);
1544 template <typename U = T, MatrixFormat M = MType>
1545 requires DenseMatrixFormat<M>
1546 static Matrix<T, MType> Triangular(int n, Uplo uplo, T diagonal_value = T(1),
1547 T non_diagonal_value = T(0.5), int batch_size = 1);
1550 template <typename U = T, MatrixFormat M = MType>
1551 requires DenseMatrixFormat<M>
1552 static Matrix<T, MType> TriDiagToeplitz(int n, T diag = T(1),
1553 T sub_diag = T(-0.5), T super_diag = T(0.5), int batch_size = 1);
1568 template <typename U = T, MatrixFormat M = MType>
1569 requires DenseMatrixFormat<M>
1570 Matrix<T, MType> to_column_major(const Queue& ctx, int row_pitch = 0) const;
1573 template <typename U = T, MatrixFormat M = MType>
1574 requires DenseMatrixFormat<M>
1575 Matrix<T, MType> to_column_major(int row_pitch = 0) const;
1586 template <MatrixFormat NewMType>
1587 Matrix<T, NewMType> convert_to(const float_t<T>& zero_threshold = 1e-7) const;
1593 template <typename U = T, MatrixFormat M = MType>
1594 requires DenseMatrixFormat<M>
1595 Matrix<T, MType> to_row_major(const Queue& ctx) const;
1598 template <typename U = T, MatrixFormat M = MType>
1599 requires DenseMatrixFormat<M>
1600 Matrix<T, MType> to_row_major() const;
1606 Matrix(const Matrix& other)
1607 : Base(other), values_(other.values_), ptrs_(other.ptrs_), active_rows_store_(other.active_rows_store_),
1608 active_cols_store_(other.active_cols_store_), row_offsets_store_(other.row_offsets_store_),
1609 col_indices_store_(other.col_indices_store_) {
1610 this->backend_handle_.reset();
1611 for (std::size_t b = 0; b < ptrs_.size(); ++b) ptrs_[b] = values_.data() + static_cast<std::ptrdiff_t>(b) * stride_;
1614 Matrix(Matrix&& other) noexcept : Base() { *this = std::move(other); }
1615 Matrix& operator=(const Matrix& other) { return *this = Matrix(other); }
1616 Matrix& operator=(Matrix&& other) noexcept {
1617 Base::operator=(std::move(other));
1618 values_ = std::move(other.values_);
1619 ptrs_ = std::move(other.ptrs_);
1620 active_rows_store_ = std::move(other.active_rows_store_);
1621 active_cols_store_ = std::move(other.active_cols_store_);
1622 row_offsets_store_ = std::move(other.row_offsets_store_);
1623 col_indices_store_ = std::move(other.col_indices_store_);
1631 Matrix<T, MType> clone() const {
1632 Matrix<T, MType> result = [&]() -> Matrix<T, MType> {
1633 if constexpr (MType == MatrixFormat::CSR) {
1636 return Matrix<T, MType>(rows_, cols_, NonZeros{matrix_stride_}, batch_size_);
1641 return Matrix<T, MType>(rows_, cols_, batch_size_, ld_, stride_);
1645 std::copy(values_.begin(), values_.end(), result.values_.begin());
1646 if constexpr (MType == MatrixFormat::CSR) {
1647 std::copy(row_offsets_store_.begin(), row_offsets_store_.end(), result.row_offsets_store_.begin());
1648 std::copy(col_indices_store_.begin(), col_indices_store_.end(), result.col_indices_store_.begin());
1650 result.matrix_stride_ = matrix_stride_;
1651 result.offset_stride_ = offset_stride_;
1652 } else if (this->is_heterogeneous()) {
1653 result.set_active_dims(this->active_rows(), this->active_cols());
1659 MatrixView<T, MType> view() const { return *this; }
1664 MatrixView<T, MType> view(int rows, int cols, int ld = -1, int stride = -1) const;
1667 template <typename U>
1668 Matrix<U, MType> astype() const;
1672 void fill(T value) { Base::fill(value).wait(); }
1680 template <MatrixFormat M = MType>
1681 requires DenseMatrixFormat<M>
1682 T& operator()(int row, int col, int batch) {
1684 return values_.at(static_cast<int64_t>(batch) * stride_ + col * ld_ + row);
1688 template <MatrixFormat M = MType>
1689 requires DenseMatrixFormat<M>
1690 const T& operator()(int row, int col, int batch) const {
1691 return values_.at(static_cast<int64_t>(batch) * stride_ + col * ld_ + row);
1693 using Base::operator();
1698 void copy_from(const MatrixView<T, MType>& src);
1707 template <MatrixFormat M = MType>
1708 requires DenseMatrixFormat<M>
1709 Matrix<T, MType>& set_active_dims(Span<int> active_rows, Span<int> active_cols) {
1710 detail::validate_dense_active_dims(rows_, cols_, batch_size_, active_rows, active_cols);
1711 active_rows_store_.resize(active_rows.size());
1712 active_cols_store_.resize(active_cols.size());
1713 std::copy(active_rows.begin(), active_rows.end(), active_rows_store_.begin());
1714 std::copy(active_cols.begin(), active_cols.end(), active_cols_store_.begin());
1722 this->data_ = values_.to_span();
1723 this->data_ptrs_ = ptrs_.to_span();
1724 this->active_rows_ = active_rows_store_.to_span();
1725 this->active_cols_ = active_cols_store_.to_span();
1726 this->row_offsets_ = row_offsets_store_.to_span();
1727 this->col_indices_ = col_indices_store_.to_span();
1730 UnifiedVector<T> values_;
1731 UnifiedVector<T*> ptrs_;
1732 UnifiedVector<int> active_rows_store_;
1733 UnifiedVector<int> active_cols_store_;
1734 UnifiedVector<int> row_offsets_store_;
1735 UnifiedVector<int> col_indices_store_;