| // This file is part of Eigen, a lightweight C++ template library | |
| // for linear algebra. | |
| // | |
| // Copyright (C) 2026 Rasmus Munk Larsen <rmlarsen@gmail.com> | |
| // | |
| // This Source Code Form is subject to the terms of the Mozilla | |
| // Public License v. 2.0. If a copy of the MPL was not distributed | |
| // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
| // SPDX-License-Identifier: MPL-2.0 | |
| // cuSPARSE-specific support types. | |
| #ifndef EIGEN_GPU_CUSPARSE_SUPPORT_H | |
| #define EIGEN_GPU_CUSPARSE_SUPPORT_H | |
| // IWYU pragma: private | |
| #include "./InternalHeaderCheck.h" | |
| #include "./GpuSupport.h" | |
| #include "./Meta.h" | |
| #include <cusparse.h> | |
| /** \brief 1 when cuSPARSE runs SpMV and SpMM on BSR (block sparse row) | |
| * descriptors, 0 otherwise. | |
| * | |
| * The generic API gained BSR in SpMM with cuSPARSE 12.5 (CUDA 12.8) and in SpMV | |
| * with 12.6.3 (CUDA 13.0 Update 1); older toolkits declare cusparseCreateBsr but | |
| * return CUSPARSE_STATUS_NOT_SUPPORTED from the products. gpu::SparseContext | |
| * uploads a BlockSparseMatrix as BSR only when this is 1, and as CSC otherwise. */ | |
| #if defined(CUSPARSE_VERSION) && CUSPARSE_VERSION >= 12603 | |
| #define EIGEN_HAS_CUSPARSE_BSR 1 | |
| #else | |
| #define EIGEN_HAS_CUSPARSE_BSR 0 | |
| #endif | |
| namespace Eigen { | |
| namespace gpu { | |
| namespace internal { | |
| #define EIGEN_CUSPARSE_CHECK(x) \ | |
| do { \ | |
| const cusparseStatus_t _s = (x); \ | |
| if (_s != CUSPARSE_STATUS_SUCCESS) EIGEN_GPU_CHECK_FAILED(cusparseGetErrorName(_s), #x, __FILE__, __LINE__); \ | |
| } while (0) | |
| // cuSPARSE rejects CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE for real scalar | |
| // types; for real Scalar, ConjTrans is mathematically equivalent to Trans and | |
| // is silently demoted. Complex Scalar passes through unchanged. | |
| template <typename Scalar> | |
| constexpr cusparseOperation_t to_cusparse_op(GpuOp op) { | |
| const auto op_ = (op == GpuOp::ConjTrans && !NumTraits<Scalar>::IsComplex) ? GpuOp::Trans : op; | |
| switch (op_) { | |
| case GpuOp::Trans: | |
| return CUSPARSE_OPERATION_TRANSPOSE; | |
| case GpuOp::ConjTrans: | |
| return CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE; | |
| default: | |
| return CUSPARSE_OPERATION_NON_TRANSPOSE; | |
| } | |
| } | |
| // Bind without copying when the input already has the target sparse format | |
| // and is compressed; otherwise convert/compress into `storage` and return | |
| // that. Avoids a full host copy + format conversion on the common | |
| // already-matching path. The SFINAE split (rather than plain overloading on | |
| // `const SpMatType&`) is load-bearing: an exact-match overload would bind a | |
| // converted temporary for other input types and return a dangling reference. | |
| template <typename SpMatType, typename InputType, require_same_t<SpMatType, InputType> = 0> | |
| const SpMatType& bind_sparse(const InputType& A, SpMatType& storage) { | |
| if (A.isCompressed()) return A; | |
| storage = A; | |
| storage.makeCompressed(); | |
| return storage; | |
| } | |
| template <typename SpMatType, typename InputType, require_not_same_t<SpMatType, InputType> = 0> | |
| const SpMatType& bind_sparse(const InputType& A, SpMatType& storage) { | |
| storage = A; | |
| storage.makeCompressed(); | |
| return storage; | |
| } | |
| // Shared guard for the 32-bit index limits of the CUDA sparse libraries | |
| // (cuSPARSE, cuDSS): matrix dimensions and nonzero count must fit StorageIndex. | |
| template <typename StorageIndex> | |
| inline void check_storage_index_bounds(Index rows, Index cols, Index nnz) { | |
| const Index max_storage_index = static_cast<Index>((std::numeric_limits<StorageIndex>::max)()); | |
| eigen_assert(rows <= max_storage_index && cols <= max_storage_index && nnz <= max_storage_index && | |
| "matrix dimensions or nonzeros exceed the index range supported by the CUDA sparse libraries"); | |
| EIGEN_UNUSED_VARIABLE(rows); | |
| EIGEN_UNUSED_VARIABLE(cols); | |
| EIGEN_UNUSED_VARIABLE(nnz); | |
| EIGEN_UNUSED_VARIABLE(max_storage_index); | |
| } | |
| } // namespace internal | |
| } // namespace gpu | |
| } // namespace Eigen | |
| #endif // EIGEN_GPU_CUSPARSE_SUPPORT_H |