Repository: ROCm/hipSPARSE
Pull request #619: hipsparseSpMV using rocsparse_v2_spmv
Author: login: YvanMokwinski
Created: 2025-05-27T22:03:50Z | Merged: 2025-05-28T18:35:29Z

Re-implement the ROCm-adapter of hipsparseSpMV to use rocsparse_v2_spmv instead of the deprecated rocsparse_spmv.


Diff:
diff --git a/clients/benchmarks/hipsparse_bench_app.cpp b/clients/benchmarks/hipsparse_bench_app.cpp
index f961da8f..798717a3 100644
--- a/clients/benchmarks/hipsparse_bench_app.cpp
+++ b/clients/benchmarks/hipsparse_bench_app.cpp
@@ -260,7 +260,7 @@ hipsparseStatus_t hipsparse_bench_app::export_file()
         exit(1);
     }
 
-    for(int isample = 0; isample < nsamples; ++isample)
+    for(size_t isample = 0; isample < nsamples; ++isample)
     {
         this->m_bench_cmdlines.get(isample, sample_argc, sample_argv);
 
@@ -339,7 +339,7 @@ hipsparseStatus_t hipsparse_bench_app::define_results_json(std::ostream& out)
     }
     out << "\"," << std::endl;
 
-    size_t option_index_x = this->m_bench_cmdlines.get_option_index_x();
+    const size_t option_index_x = this->m_bench_cmdlines.get_option_index_x();
     out << std::endl << "\"xargs\": \[";
     for(int j = 0; j < this->m_bench_cmdlines.get_option_nargs(option_index_x); ++j)
     {
@@ -358,7 +358,7 @@ hipsparseStatus_t hipsparse_bench_app::define_results_json(std::ostream& out)
     std::vector<int> y_options_index;
     for(int k = 0; k < this->m_bench_cmdlines.get_noptions(); ++k)
     {
-        if(k != option_index_x)
+        if(static_cast<size_t>(k) != option_index_x)
         {
             if(this->m_bench_cmdlines.get_option_nargs(k) > 1)
             {
diff --git a/clients/include/testing_spmm_bell.hpp b/clients/include/testing_spmm_bell.hpp
index 47f55b5d..49aabc4a 100644
--- a/clients/include/testing_spmm_bell.hpp
+++ b/clients/include/testing_spmm_bell.hpp
@@ -277,8 +277,7 @@ hipsparseStatus_t testing_spmm_bell()
                               make_DataType<T>(45.0),
                               make_DataType<T>(58.0)};
 
-    std::vector<T> hC_2(m * n);
-    hC_2 = hC_1;
+    std::vector<T> hC_2(hC_1);
 
     // allocate memory on device
     auto drow_ptr_managed = hipsparse_unique_ptr{device_malloc(sizeof(I) * (m + 1)), device_free};
diff --git a/clients/tests/hipsparse_gtest_main.cpp b/clients/tests/hipsparse_gtest_main.cpp
index 22c123a5..13bbf781 100644
--- a/clients/tests/hipsparse_gtest_main.cpp
+++ b/clients/tests/hipsparse_gtest_main.cpp
@@ -262,7 +262,7 @@ int main(int argc, char** argv)
     int ret = RUN_ALL_TESTS();
 
     // Reset HIP device
-    hipDeviceReset();
+    (void)hipDeviceReset();
 
     return ret;
 }
diff --git a/library/include/hipsparse-generic-types.h b/library/include/hipsparse-generic-types.h
index 448c42b2..ccb52852 100644
--- a/library/include/hipsparse-generic-types.h
+++ b/library/include/hipsparse-generic-types.h
@@ -63,7 +63,7 @@ typedef void* hipsparseDnVecDescr_t;
  *  It should be destroyed at the end using hipsparseDestroySpMat().
  */
 #if(!defined(CUDART_VERSION) || CUDART_VERSION >= 10010)
-typedef void* hipsparseSpMatDescr_t;
+typedef struct hipsparseSpMatDescr_st* hipsparseSpMatDescr_t;
 #endif
 
 /*! \ingroup types_module
@@ -115,7 +115,7 @@ typedef void const* hipsparseConstDnVecDescr_t;
  *  hipsparseDestroySpMat().
  */
 #if(!defined(CUDART_VERSION) || CUDART_VERSION >= 12000)
-typedef void const* hipsparseConstSpMatDescr_t;
+typedef struct hipsparseSpMatDescr_st const* hipsparseConstSpMatDescr_t;
 #endif
 
 /*! \ingroup types_module
diff --git a/library/src/amd_detail/generic/hipsparse_dense2sparse.cpp b/library/src/amd_detail/generic/hipsparse_dense2sparse.cpp
index 28cf6017..eda4179f 100644
--- a/library/src/amd_detail/generic/hipsparse_dense2sparse.cpp
+++ b/library/src/amd_detail/generic/hipsparse_dense2sparse.cpp
@@ -39,7 +39,7 @@ hipsparseStatus_t hipsparseDenseToSparse_bufferSize(hipsparseHandle_t
     return hipsparse::rocSPARSEStatusToHIPStatus(
         rocsparse_dense_to_sparse((rocsparse_handle)handle,
                                   (rocsparse_const_dnmat_descr)matA,
-                                  (rocsparse_spmat_descr)matB,
+                                  to_rocsparse_spmat_descr(matB),
                                   hipsparse::hipDnToSpAlgToHCCDnToSpAlg(alg),
                                   pBufferSizeInBytes,
                                   nullptr));
@@ -54,7 +54,7 @@ hipsparseStatus_t hipsparseDenseToSparse_analysis(hipsparseHandle_t           ha
     return hipsparse::rocSPARSEStatusToHIPStatus(
         rocsparse_dense_to_sparse((rocsparse_handle)handle,
                                   (rocsparse_const_dnmat_descr)matA,
-                                  (rocsparse_spmat_descr)matB,
+                                  to_rocsparse_spmat_descr(matB),
                                   hipsparse::hipDnToSpAlgToHCCDnToSpAlg(alg),
                                   nullptr,
                                   externalBuffer));
@@ -70,7 +70,7 @@ hipsparseStatus_t hipsparseDenseToSparse_convert(hipsparseHandle_t           han
     return hipsparse::rocSPARSEStatusToHIPStatus(
         rocsparse_dense_to_sparse((rocsparse_handle)handle,
                                   (rocsparse_const_dnmat_descr)matA,
-                                  (rocsparse_spmat_descr)matB,
+                                  to_rocsparse_spmat_descr(matB),
                                   hipsparse::hipDnToSpAlgToHCCDnToSpAlg(alg),
                                   externalBuffer != nullptr ? &bufferSize : nullptr,
                                   externalBuffer));
diff --git a/library/src/amd_detail/generic/hipsparse_sddmm.cpp b/library/src/amd_detail/generic/hipsparse_sddmm.cpp
index ac13c081..8f150900 100644
--- a/library/src/amd_detail/generic/hipsparse_sddmm.cpp
+++ b/library/src/amd_detail/generic/hipsparse_sddmm.cpp
@@ -50,7 +50,7 @@ hipsparseStatus_t hipsparseSDDMM(hipsparseHandle_t          handle,
                         (rocsparse_const_dnmat_descr)matA,
                         (rocsparse_const_dnmat_descr)matB,
                         beta,
-                        (const rocsparse_spmat_descr)matC,
+                        to_rocsparse_spmat_descr(matC),
                         hipsparse::hipDataTypeToHCCDataType(computeType),
                         hipsparse::hipSDDMMAlgToHCCSDDMMAlg(alg),
                         tempBuffer));
@@ -76,7 +76,7 @@ hipsparseStatus_t hipsparseSDDMM_bufferSize(hipsparseHandle_t          handle,
                                     (rocsparse_const_dnmat_descr)matA,
                                     (rocsparse_const_dnmat_descr)matB,
                                     beta,
-                                    (const rocsparse_spmat_descr)matC,
+                                    to_rocsparse_spmat_descr(matC),
                                     hipsparse::hipDataTypeToHCCDataType(computeType),
                                     hipsparse::hipSDDMMAlgToHCCSDDMMAlg(alg),
                                     pBufferSizeInBytes));
@@ -102,7 +102,7 @@ hipsparseStatus_t hipsparseSDDMM_preprocess(hipsparseHandle_t          handle,
                                    (rocsparse_const_dnmat_descr)matA,
                                    (rocsparse_const_dnmat_descr)matB,
                                    beta,
-                                   (const rocsparse_spmat_descr)matC,
+                                   to_rocsparse_spmat_descr(matC),
                                    hipsparse::hipDataTypeToHCCDataType(computeType),
                                    hipsparse::hipSDDMMAlgToHCCSDDMMAlg(alg),
                                    tempBuffer));
diff --git a/library/src/amd_detail/generic/hipsparse_sparse2dense.cpp b/library/src/amd_detail/generic/hipsparse_sparse2dense.cpp
index b1b6fc8a..e8ed2838 100644
--- a/library/src/amd_detail/generic/hipsparse_sparse2dense.cpp
+++ b/library/src/amd_detail/generic/hipsparse_sparse2dense.cpp
@@ -38,7 +38,7 @@ hipsparseStatus_t hipsparseSparseToDense_bufferSize(hipsparseHandle_t
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
         rocsparse_sparse_to_dense((rocsparse_handle)handle,
-                                  (rocsparse_const_spmat_descr)matA,
+                                  to_rocsparse_const_spmat_descr(matA),
                                   (rocsparse_dnmat_descr)matB,
                                   hipsparse::hipSpToDnAlgToHCCSpToDnAlg(alg),
                                   pBufferSizeInBytes,
@@ -53,7 +53,7 @@ hipsparseStatus_t hipsparseSparseToDense(hipsparseHandle_t           handle,
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
         rocsparse_sparse_to_dense((rocsparse_handle)handle,
-                                  (rocsparse_const_spmat_descr)matA,
+                                  to_rocsparse_const_spmat_descr(matA),
                                   (rocsparse_dnmat_descr)matB,
                                   hipsparse::hipSpToDnAlgToHCCSpToDnAlg(alg),
                                   nullptr,
diff --git a/library/src/amd_detail/generic/hipsparse_spgemm.cpp b/library/src/amd_detail/generic/hipsparse_spgemm.cpp
index 1bad28a6..df12219e 100644
--- a/library/src/amd_detail/generic/hipsparse_spgemm.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spgemm.cpp
@@ -183,11 +183,11 @@ hipsparseStatus_t hipsparseSpGEMM_workEstimation(hipsparseHandle_t          hand
                                                    hipsparse::hipOperationToHCCOperation(opA),
                                                    hipsparse::hipOperationToHCCOperation(opB),
                                                    alpha,
-                                                   (rocsparse_const_spmat_descr)matA,
-                                                   (rocsparse_const_spmat_descr)matB,
+                                                   to_rocsparse_const_spmat_descr(matA),
+                                                   to_rocsparse_const_spmat_descr(matB),
                                                    nullptr,
-                                                   (rocsparse_const_spmat_descr)matC,
-                                                   (rocsparse_spmat_descr)matC,
+                                                   to_rocsparse_const_spmat_descr(matC),
+                                                   to_rocsparse_spmat_descr(matC),
                                                    hipsparse::hipDataTypeToHCCDataType(computeType),
                                                    hipsparse::hipSpGEMMAlgToHCCSpGEMMAlg(alg),
                                                    rocsparse_spgemm_stage_buffer_size,
@@ -217,11 +217,11 @@ hipsparseStatus_t hipsparseSpGEMM_workEstimation(hipsparseHandle_t          hand
                              hipsparse::hipOperationToHCCOperation(opA),
                              hipsparse::hipOperationToHCCOperation(opB),
                              alpha,
-                             (rocsparse_const_spmat_descr)matA,
-                             (rocsparse_const_spmat_descr)matB,
+                             to_rocsparse_const_spmat_descr(matA),
+                             to_rocsparse_const_spmat_descr(matB),
                              nullptr,
-                             (rocsparse_const_spmat_descr)matC,
-                             (rocsparse_spmat_descr)matC,
+                             to_rocsparse_const_spmat_descr(matC),
+                             to_rocsparse_spmat_descr(matC),
                              hipsparse::hipDataTypeToHCCDataType(computeType),
                              hipsparse::hipSpGEMMAlgToHCCSpGEMMAlg(alg),
                              rocsparse_spgemm_stage_nnz,
@@ -327,11 +327,11 @@ hipsparseStatus_t hipsparseSpGEMM_compute(hipsparseHandle_t          handle,
                              hipsparse::hipOperationToHCCOperation(opA),
                              hipsparse::hipOperationToHCCOperation(opB),
                              alpha,
-                             (rocsparse_const_spmat_descr)matA,
-                             (rocsparse_const_spmat_descr)matB,
+                             to_rocsparse_const_spmat_descr(matA),
+                             to_rocsparse_const_spmat_descr(matB),
                              nullptr,
-                             (rocsparse_const_spmat_descr)matC,
-                             (rocsparse_spmat_descr)matC,
+                             to_rocsparse_const_spmat_descr(matC),
+                             to_rocsparse_spmat_descr(matC),
                              hipsparse::hipDataTypeToHCCDataType(computeType),
                              hipsparse::hipSpGEMMAlgToHCCSpGEMMAlg(alg),
                              rocsparse_spgemm_stage_compute,
diff --git a/library/src/amd_detail/generic/hipsparse_spgemm_reuse.cpp b/library/src/amd_detail/generic/hipsparse_spgemm_reuse.cpp
index d609dd31..4e872e53 100644
--- a/library/src/amd_detail/generic/hipsparse_spgemm_reuse.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spgemm_reuse.cpp
@@ -273,11 +273,11 @@ hipsparseStatus_t hipsparseSpGEMMreuse_nnz(hipsparseHandle_t          handle,
                              hipsparse::hipOperationToHCCOperation(opA),
                              hipsparse::hipOperationToHCCOperation(opB),
                              alpha,
-                             (rocsparse_const_spmat_descr)matA,
-                             (rocsparse_const_spmat_descr)matB,
+                             to_rocsparse_const_spmat_descr(matA),
+                             to_rocsparse_const_spmat_descr(matB),
                              nullptr,
-                             (rocsparse_const_spmat_descr)matC,
-                             (rocsparse_spmat_descr)matC,
+                             to_rocsparse_const_spmat_descr(matC),
+                             to_rocsparse_spmat_descr(matC),
                              hipsparse::hipDataTypeToHCCDataType(computeType),
                              hipsparse::hipSpGEMMAlgToHCCSpGEMMAlg(alg),
                              rocsparse_spgemm_stage_symbolic,
@@ -442,11 +442,11 @@ hipsparseStatus_t hipsparseSpGEMMreuse_compute(hipsparseHandle_t          handle
                          hipsparse::hipOperationToHCCOperation(opA),
                          hipsparse::hipOperationToHCCOperation(opB),
                          alpha,
-                         (rocsparse_const_spmat_descr)matA,
-                         (rocsparse_const_spmat_descr)matB,
+                         to_rocsparse_const_spmat_descr(matA),
+                         to_rocsparse_const_spmat_descr(matB),
                          nullptr,
-                         (rocsparse_const_spmat_descr)matC,
-                         (rocsparse_spmat_descr)matC,
+                         to_rocsparse_const_spmat_descr(matC),
+                         to_rocsparse_spmat_descr(matC),
                          hipsparse::hipDataTypeToHCCDataType(computeType),
                          hipsparse::hipSpGEMMAlgToHCCSpGEMMAlg(alg),
                          rocsparse_spgemm_stage_numeric,
diff --git a/library/src/amd_detail/generic/hipsparse_spmm.cpp b/library/src/amd_detail/generic/hipsparse_spmm.cpp
index b496f5f4..8641fb57 100644
--- a/library/src/amd_detail/generic/hipsparse_spmm.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spmm.cpp
@@ -47,7 +47,7 @@ hipsparseStatus_t hipsparseSpMM_bufferSize(hipsparseHandle_t           handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        hipsparse::hipOperationToHCCOperation(opB),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnmat_descr)matB,
                        beta,
                        (const rocsparse_dnmat_descr)matC,
@@ -76,7 +76,7 @@ hipsparseStatus_t hipsparseSpMM_preprocess(hipsparseHandle_t           handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        hipsparse::hipOperationToHCCOperation(opB),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnmat_descr)matB,
                        beta,
                        (const rocsparse_dnmat_descr)matC,
@@ -105,7 +105,7 @@ hipsparseStatus_t hipsparseSpMM(hipsparseHandle_t           handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        hipsparse::hipOperationToHCCOperation(opB),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnmat_descr)matB,
                        beta,
                        (const rocsparse_dnmat_descr)matC,
diff --git a/library/src/amd_detail/generic/hipsparse_spmv.cpp b/library/src/amd_detail/generic/hipsparse_spmv.cpp
index 33943e41..30826eeb 100644
--- a/library/src/amd_detail/generic/hipsparse_spmv.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spmv.cpp
@@ -41,19 +41,134 @@ hipsparseStatus_t hipsparseSpMV_bufferSize(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            size_t*                     pBufferSizeInBytes)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_buffer_size,
-                       pBufferSizeInBytes,
-                       nullptr));
+
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(pBufferSizeInBytes == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    const rocsparse_datatype  datatype  = hipsparse::hipDataTypeToHCCDataType(computeType);
+    const rocsparse_operation operation = hipsparse::hipOperationToHCCOperation(opA);
+    rocsparse_spmv_alg        spmv_alg  = hipsparse::hipSpMVAlgToHCCSpMVAlg(alg);
+
+    //
+    // Fallback algorithm?
+    //
+    if(spmv_alg == rocsparse_spmv_alg_csr_lrb)
+    {
+        rocsparse_matrix_type matrix_type;
+        RETURN_IF_ROCSPARSE_ERROR(
+            rocsparse_spmat_get_attribute(to_rocsparse_const_spmat_descr(matA),
+                                          rocsparse_spmat_matrix_type,
+                                          &matrix_type,
+                                          sizeof(matrix_type)));
+
+        if((matrix_type == rocsparse_matrix_type_symmetric)
+           || (operation != rocsparse_operation_none))
+        {
+            spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+        }
+    }
+    else if((spmv_alg == rocsparse_spmv_alg_csr_adaptive)
+            && (operation != rocsparse_operation_none))
+    {
+        spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+    }
+
+    hipsparseSpMVDescr_st* hip_spmv_descr = matA->get_hip_spmv_descr();
+
+    //
+    // If spmv_descr alreay exists, then destroy it.
+    //
+    rocsparse_spmv_descr spmv_descr = hip_spmv_descr->get_spmv_descr();
+    if(spmv_descr != nullptr)
+    {
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_destroy_spmv_descr(spmv_descr));
+        hip_spmv_descr->set_spmv_descr(nullptr);
+    }
+
+    //
+    // Create spmv_descr.
+    //
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_create_spmv_descr(&spmv_descr));
+
+    hip_spmv_descr->set_spmv_descr(spmv_descr);
+
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                       spmv_descr,
+                                                       rocsparse_spmv_input_alg,
+                                                       &spmv_alg,
+                                                       sizeof(spmv_alg)));
+
+    //
+    // Set operation.
+    //
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                       spmv_descr,
+                                                       rocsparse_spmv_input_operation,
+                                                       &operation,
+                                                       sizeof(operation)));
+
+    //
+    // Set datatypes.
+    //
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                       spmv_descr,
+                                                       rocsparse_spmv_input_scalar_datatype,
+                                                       &datatype,
+                                                       sizeof(datatype)));
+
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                       spmv_descr,
+                                                       rocsparse_spmv_input_compute_datatype,
+                                                       &datatype,
+                                                       sizeof(datatype)));
+
+    //
+    // Buffer size for the analysis phase.
+    //
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_v2_spmv_buffer_size((rocsparse_handle)handle,
+                                                            spmv_descr,
+                                                            to_rocsparse_const_spmat_descr(matA),
+                                                            (rocsparse_const_dnvec_descr)vecX,
+                                                            (rocsparse_dnvec_descr)vecY,
+                                                            rocsparse_v2_spmv_stage_analysis,
+                                                            pBufferSizeInBytes));
+
+    hip_spmv_descr->set_buffer_size_stage_analysis(pBufferSizeInBytes[0]);
+    hip_spmv_descr->buffer_size_called();
+
+    return HIPSPARSE_STATUS_SUCCESS;
 }
 
 hipsparseStatus_t hipsparseSpMV_preprocess(hipsparseHandle_t           handle,
@@ -67,20 +182,118 @@ hipsparseStatus_t hipsparseSpMV_preprocess(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_preprocess,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    const rocsparse_datatype  datatype  = hipsparse::hipDataTypeToHCCDataType(computeType);
+    const rocsparse_operation operation = hipsparse::hipOperationToHCCOperation(opA);
+    rocsparse_spmv_alg        spmv_alg  = hipsparse::hipSpMVAlgToHCCSpMVAlg(alg);
+
+    //
+    // Fallback algorithm?
+    //
+    if(spmv_alg == rocsparse_spmv_alg_csr_lrb)
+    {
+        rocsparse_matrix_type matrix_type;
+        RETURN_IF_ROCSPARSE_ERROR(
+            rocsparse_spmat_get_attribute(to_rocsparse_const_spmat_descr(matA),
+                                          rocsparse_spmat_matrix_type,
+                                          &matrix_type,
+                                          sizeof(matrix_type)));
+
+        if((matrix_type == rocsparse_matrix_type_symmetric)
+           || (operation != rocsparse_operation_none))
+        {
+            spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+        }
+    }
+    else if((spmv_alg == rocsparse_spmv_alg_csr_adaptive)
+            && (operation != rocsparse_operation_none))
+    {
+        spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+    }
+
+    hipsparseSpMVDescr_st* hip_spmv_descr = matA->get_hip_spmv_descr();
+    rocsparse_spmv_descr   spmv_descr     = hip_spmv_descr->get_spmv_descr();
+
+    if(spmv_descr == nullptr)
+    {
+        //
+        // Create spmv_descr.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_create_spmv_descr(&spmv_descr));
+
+        hip_spmv_descr->set_spmv_descr(spmv_descr);
+
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_alg,
+                                                           &spmv_alg,
+                                                           sizeof(spmv_alg)));
+        //
+        // Set operation.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_operation,
+                                                           &operation,
+                                                           sizeof(operation)));
+
+        //
+        // Set datatypes.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_scalar_datatype,
+                                                           &datatype,
+                                                           sizeof(datatype)));
+
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_compute_datatype,
+                                                           &datatype,
+                                                           sizeof(datatype)));
+    }
+
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_v2_spmv((rocsparse_handle)handle,
+                                                spmv_descr,
+                                                alpha,
+                                                to_rocsparse_const_spmat_descr(matA),
+                                                (rocsparse_const_dnvec_descr)vecX,
+                                                beta,
+                                                (rocsparse_dnvec_descr)vecY,
+                                                rocsparse_v2_spmv_stage_analysis,
+                                                hip_spmv_descr->get_buffer_size_stage_analysis(),
+                                                externalBuffer));
+    hip_spmv_descr->stage_analysis_called();
+    return HIPSPARSE_STATUS_SUCCESS;
 }
 
 hipsparseStatus_t hipsparseSpMV(hipsparseHandle_t           handle,
@@ -94,18 +307,214 @@ hipsparseStatus_t hipsparseSpMV(hipsparseHandle_t           handle,
                                 hipsparseSpMVAlg_t          alg,
                                 void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_compute,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    const rocsparse_datatype  datatype  = hipsparse::hipDataTypeToHCCDataType(computeType);
+    const rocsparse_operation operation = hipsparse::hipOperationToHCCOperation(opA);
+    rocsparse_spmv_alg        spmv_alg  = hipsparse::hipSpMVAlgToHCCSpMVAlg(alg);
+
+    hipsparseSpMVDescr_st* hip_spmv_descr = matA->get_hip_spmv_descr();
+    rocsparse_spmv_descr   spmv_descr     = hip_spmv_descr->get_spmv_descr();
+
+    if(spmv_descr == nullptr)
+    {
+        //
+        // Create spmv_descr.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_create_spmv_descr(&spmv_descr));
+
+        hip_spmv_descr->set_spmv_descr(spmv_descr);
+
+        if(spmv_alg == rocsparse_spmv_alg_csr_lrb)
+        {
+            rocsparse_matrix_type matrix_type;
+            RETURN_IF_ROCSPARSE_ERROR(
+                rocsparse_spmat_get_attribute(to_rocsparse_const_spmat_descr(matA),
+                                              rocsparse_spmat_matrix_type,
+                                              &matrix_type,
+                                              sizeof(matrix_type)));
+            if((matrix_type == rocsparse_matrix_type_symmetric)
+               || (operation != rocsparse_operation_none))
+            {
+                spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+            }
+        }
+        else if((spmv_alg == rocsparse_spmv_alg_csr_adaptive)
+                && (operation != rocsparse_operation_none))
+        {
+            spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+        }
+        else if(((spmv_alg == rocsparse_spmv_alg_csr_adaptive)
+                 || (spmv_alg == rocsparse_spmv_alg_csr_lrb))
+                && (hip_spmv_descr->is_stage_analysis_called() == false))
+        {
+            spmv_alg = rocsparse_spmv_alg_csr_rowsplit;
+        }
+
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_alg,
+                                                           &spmv_alg,
+                                                           sizeof(spmv_alg)));
+
+        //
+        // Set operation.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_operation,
+                                                           &operation,
+                                                           sizeof(operation)));
+
+        //
+        // Set datatypes.
+        //
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_scalar_datatype,
+                                                           &datatype,
+                                                           sizeof(datatype)));
+
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmv_set_input((rocsparse_handle)handle,
+                                                           spmv_descr,
+                                                           rocsparse_spmv_input_compute_datatype,
+                                                           &datatype,
+                                                           sizeof(datatype)));
+    }
+
+    if(hip_spmv_descr->is_stage_analysis_called() == false)
+    {
+        //
+        // No analysis has been performed, we have to call the analysis since this is a requirement for v2_spmv.
+        //
+        if(hip_spmv_descr->is_implicit_stage_analysis_called() == false)
+        {
+
+            if(hip_spmv_descr->is_buffer_size_called() == false)
+            {
+                size_t buffer_size_in_bytes;
+                RETURN_IF_ROCSPARSE_ERROR(
+                    rocsparse_v2_spmv_buffer_size((rocsparse_handle)handle,
+                                                  spmv_descr,
+                                                  to_rocsparse_const_spmat_descr(matA),
+                                                  (rocsparse_const_dnvec_descr)vecX,
+                                                  (rocsparse_dnvec_descr)vecY,
+                                                  rocsparse_v2_spmv_stage_analysis,
+                                                  &buffer_size_in_bytes));
+
+                hipStream_t stream{};
+                RETURN_IF_ROCSPARSE_ERROR(rocsparse_get_stream((rocsparse_handle)handle, &stream));
+
+                RETURN_IF_HIP_ERROR(hipMallocAsync(
+                    hip_spmv_descr->get_buffer_reference(), buffer_size_in_bytes, stream));
+
+                RETURN_IF_ROCSPARSE_ERROR(rocsparse_v2_spmv((rocsparse_handle)handle,
+                                                            spmv_descr,
+                                                            alpha,
+                                                            to_rocsparse_const_spmat_descr(matA),
+                                                            (rocsparse_const_dnvec_descr)vecX,
+                                                            beta,
+                                                            (const rocsparse_dnvec_descr)vecY,
+                                                            rocsparse_v2_spmv_stage_analysis,
+                                                            buffer_size_in_bytes,
+                                                            hip_spmv_descr->get_buffer()));
+
+                RETURN_IF_HIP_ERROR(hipFreeAsync(hip_spmv_descr->get_buffer(), stream));
+                hip_spmv_descr->set_buffer(nullptr);
+            }
+            else
+            {
+                //
+                // We can use the externalBuffer since the user is allocating a buffer for the analysis phase only, but the user
+                // does not know it.
+                //
+                RETURN_IF_ROCSPARSE_ERROR(
+                    rocsparse_v2_spmv((rocsparse_handle)handle,
+                                      spmv_descr,
+                                      alpha,
+                                      to_rocsparse_const_spmat_descr(matA),
+                                      (rocsparse_const_dnvec_descr)vecX,
+                                      beta,
+                                      (const rocsparse_dnvec_descr)vecY,
+                                      rocsparse_v2_spmv_stage_analysis,
+                                      hip_spmv_descr->get_buffer_size_stage_analysis(),
+                                      externalBuffer));
+            }
+
+            hip_spmv_descr->implicit_stage_analysis_called();
+        }
+
+        //
+        // We keep hip_spmv_descr->spmv_analysis_called = false;
+        // because it hasn't been explicitly called.
+        //
+    }
+
+    if(hip_spmv_descr->is_stage_compute_subsequent() == false)
+    {
+        //
+        // Get the buffer size for the compute phase, the buffer size returned in hipsparseSpMV_bufferSize is the buffer size for the analysis phase.
+        //
+        size_t buffer_size_in_bytes;
+        RETURN_IF_ROCSPARSE_ERROR(
+            rocsparse_v2_spmv_buffer_size((rocsparse_handle)handle,
+                                          spmv_descr,
+                                          to_rocsparse_const_spmat_descr(matA),
+                                          (rocsparse_const_dnvec_descr)vecX,
+                                          (rocsparse_dnvec_descr)vecY,
+                                          rocsparse_v2_spmv_stage_compute,
+                                          &buffer_size_in_bytes));
+
+        hip_spmv_descr->set_buffer_size_stage_compute(buffer_size_in_bytes);
+
+        hipStream_t stream{};
+        RETURN_IF_ROCSPARSE_ERROR(rocsparse_get_stream((rocsparse_handle)handle, &stream));
+
+        RETURN_IF_HIP_ERROR(hipMallocAsync(hip_spmv_descr->get_buffer_reference(),
+                                           hip_spmv_descr->get_buffer_size_stage_compute(),
+                                           stream));
+
+        hip_spmv_descr->stage_compute_subsequent();
+    }
+
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_v2_spmv((rocsparse_handle)handle,
+                                                spmv_descr,
+                                                alpha,
+                                                to_rocsparse_const_spmat_descr(matA),
+                                                (rocsparse_const_dnvec_descr)vecX,
+                                                beta,
+                                                (rocsparse_dnvec_descr)vecY,
+                                                rocsparse_v2_spmv_stage_compute,
+                                                hip_spmv_descr->get_buffer_size_stage_compute(),
+                                                hip_spmv_descr->get_buffer()));
+
+    return HIPSPARSE_STATUS_SUCCESS;
 }
diff --git a/library/src/amd_detail/generic/hipsparse_spsm.cpp b/library/src/amd_detail/generic/hipsparse_spsm.cpp
index 54b341fa..53783b91 100644
--- a/library/src/amd_detail/generic/hipsparse_spsm.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spsm.cpp
@@ -73,7 +73,7 @@ hipsparseStatus_t hipsparseSpSM_bufferSize(hipsparseHandle_t           handle,
                                              hipsparse::hipOperationToHCCOperation(opA),
                                              hipsparse::hipOperationToHCCOperation(opB),
                                              alpha,
-                                             (rocsparse_const_spmat_descr)matA,
+                                             to_rocsparse_const_spmat_descr(matA),
                                              (rocsparse_const_dnmat_descr)matB,
                                              (const rocsparse_dnmat_descr)matC,
                                              hipsparse::hipDataTypeToHCCDataType(computeType),
@@ -108,7 +108,7 @@ hipsparseStatus_t hipsparseSpSM_analysis(hipsparseHandle_t           handle,
                                              hipsparse::hipOperationToHCCOperation(opA),
                                              hipsparse::hipOperationToHCCOperation(opB),
                                              alpha,
-                                             (rocsparse_const_spmat_descr)matA,
+                                             to_rocsparse_const_spmat_descr(matA),
                                              (rocsparse_const_dnmat_descr)matB,
                                              (const rocsparse_dnmat_descr)matC,
                                              hipsparse::hipDataTypeToHCCDataType(computeType),
@@ -144,7 +144,7 @@ hipsparseStatus_t hipsparseSpSM_solve(hipsparseHandle_t           handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        hipsparse::hipOperationToHCCOperation(opB),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnmat_descr)matB,
                        (const rocsparse_dnmat_descr)matC,
                        hipsparse::hipDataTypeToHCCDataType(computeType),
diff --git a/library/src/amd_detail/generic/hipsparse_spsv.cpp b/library/src/amd_detail/generic/hipsparse_spsv.cpp
index f5a917e6..99c05082 100644
--- a/library/src/amd_detail/generic/hipsparse_spsv.cpp
+++ b/library/src/amd_detail/generic/hipsparse_spsv.cpp
@@ -67,7 +67,7 @@ hipsparseStatus_t hipsparseSpSV_bufferSize(hipsparseHandle_t           handle,
         rocsparse_spsv((rocsparse_handle)handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnvec_descr)x,
                        (const rocsparse_dnvec_descr)y,
                        hipsparse::hipDataTypeToHCCDataType(computeType),
@@ -96,7 +96,7 @@ hipsparseStatus_t hipsparseSpSV_analysis(hipsparseHandle_t           handle,
     RETURN_IF_ROCSPARSE_ERROR(rocsparse_spsv((rocsparse_handle)handle,
                                              hipsparse::hipOperationToHCCOperation(opA),
                                              alpha,
-                                             (rocsparse_const_spmat_descr)matA,
+                                             to_rocsparse_const_spmat_descr(matA),
                                              (rocsparse_const_dnvec_descr)x,
                                              (const rocsparse_dnvec_descr)y,
                                              hipsparse::hipDataTypeToHCCDataType(computeType),
@@ -126,7 +126,7 @@ hipsparseStatus_t hipsparseSpSV_solve(hipsparseHandle_t           handle,
         rocsparse_spsv((rocsparse_handle)handle,
                        hipsparse::hipOperationToHCCOperation(opA),
                        alpha,
-                       (rocsparse_const_spmat_descr)matA,
+                       to_rocsparse_const_spmat_descr(matA),
                        (rocsparse_const_dnvec_descr)x,
                        (const rocsparse_dnvec_descr)y,
                        hipsparse::hipDataTypeToHCCDataType(computeType),
diff --git a/library/src/amd_detail/hipsparse_generic_auxiliary.cpp b/library/src/amd_detail/hipsparse_generic_auxiliary.cpp
index 2e30eb8e..502a092f 100644
--- a/library/src/amd_detail/hipsparse_generic_auxiliary.cpp
+++ b/library/src/amd_detail/hipsparse_generic_auxiliary.cpp
@@ -30,6 +30,150 @@
 
 #include "utility.h"
 
+//
+// hipsparseSpMVDescr_st
+//
+rocsparse_spmv_descr hipsparseSpMVDescr_st::get_spmv_descr()
+{
+    return this->m_spmv_descr;
+}
+
+void hipsparseSpMVDescr_st::set_spmv_descr(rocsparse_spmv_descr value)
+{
+    this->m_spmv_descr = value;
+}
+
+bool hipsparseSpMVDescr_st::is_stage_analysis_called() const
+{
+    return this->m_is_stage_analysis_called;
+}
+
+bool hipsparseSpMVDescr_st::is_implicit_stage_analysis_called() const
+{
+    return this->m_is_implicit_stage_analysis_called;
+}
+
+size_t hipsparseSpMVDescr_st::get_buffer_size_stage_analysis() const
+{
+    return this->m_buffer_size_stage_analysis;
+}
+
+size_t hipsparseSpMVDescr_st::get_buffer_size_stage_compute() const
+{
+    return this->m_buffer_size_stage_compute;
+}
+
+void* hipsparseSpMVDescr_st::get_buffer()
+{
+    return this->m_buffer;
+}
+
+void** hipsparseSpMVDescr_st::get_buffer_reference()
+{
+    return &this->m_buffer;
+}
+
+bool hipsparseSpMVDescr_st::is_stage_compute_subsequent() const
+{
+    return this->m_is_stage_compute_subsequent;
+}
+
+bool hipsparseSpMVDescr_st::is_buffer_size_called() const
+{
+    return this->m_is_buffer_size_called;
+}
+
+void hipsparseSpMVDescr_st::stage_analysis_called()
+{
+    this->m_is_stage_analysis_called = true;
+}
+
+void hipsparseSpMVDescr_st::implicit_stage_analysis_called()
+{
+    this->m_is_implicit_stage_analysis_called = true;
+}
+
+void hipsparseSpMVDescr_st::set_buffer_size_stage_analysis(size_t value)
+{
+    this->m_buffer_size_stage_analysis = value;
+}
+
+void hipsparseSpMVDescr_st::set_buffer_size_stage_compute(size_t value)
+{
+    this->m_buffer_size_stage_compute = value;
+}
+
+void hipsparseSpMVDescr_st::set_buffer(void* value)
+{
+    this->m_buffer = value;
+}
+
+void hipsparseSpMVDescr_st::stage_compute_subsequent()
+{
+    this->m_is_stage_compute_subsequent = true;
+}
+
+void hipsparseSpMVDescr_st::buffer_size_called()
+{
+    this->m_is_buffer_size_called = true;
+}
+
+hipsparseSpMVDescr_st::~hipsparseSpMVDescr_st()
+{
+    (void)hipFree(this->get_buffer());
+}
+
+//
+// hipsparseSpMatDescr_st
+//
+rocsparse_spmat_descr hipsparseSpMatDescr_st::get_spmat_descr()
+{
+    return this->m_spmat_descr;
+}
+
+rocsparse_const_spmat_descr hipsparseSpMatDescr_st::get_const_spmat_descr() const
+{
+    return this->m_spmat_descr;
+}
+
+void hipsparseSpMatDescr_st::set_spmat_descr(rocsparse_spmat_descr value)
+{
+    this->m_spmat_descr = value;
+}
+
+hipsparseSpMVDescr_st* hipsparseSpMatDescr_st::get_hip_spmv_descr()
+{
+    return &this->m_hip_spmv_descr;
+}
+
+hipsparseSpMVDescr_st* hipsparseSpMatDescr_st::get_hip_spmv_descr() const
+{
+    return &this->m_hip_spmv_descr;
+}
+
+rocsparse_spmat_descr* hipsparseSpMatDescr_st::get_spmat_descr_reference()
+{
+    return &this->m_spmat_descr;
+}
+
+rocsparse_const_spmat_descr* hipsparseSpMatDescr_st::get_const_spmat_descr_reference() const
+{
+    return (rocsparse_const_spmat_descr*)&this->m_spmat_descr;
+}
+
+//
+// Cast hipsparseSpMatDescr_st to rocsparse_spmat_descr.
+//
+rocsparse_const_spmat_descr to_rocsparse_const_spmat_descr(const hipsparseConstSpMatDescr_t source)
+{
+    return (source != nullptr) ? source->get_const_spmat_descr() : nullptr;
+}
+
+rocsparse_spmat_descr to_rocsparse_spmat_descr(const hipsparseSpMatDescr_t source)
+{
+    return (source != nullptr) ? source->get_spmat_descr() : nullptr;
+}
+
 /* Generic API */
 hipsparseStatus_t hipsparseCreateSpVec(hipsparseSpVecDescr_t* spVecDescr,
                                        int64_t                size,
@@ -179,8 +323,13 @@ hipsparseStatus_t hipsparseCreateCoo(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_coo_descr((rocsparse_spmat_descr*)spMatDescr,
+        rocsparse_create_coo_descr(spMatDescr[0]->get_spmat_descr_reference(),
                                    rows,
                                    cols,
                                    nnz,
@@ -203,8 +352,13 @@ hipsparseStatus_t hipsparseCreateConstCoo(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_const_coo_descr((rocsparse_const_spmat_descr*)spMatDescr,
+        rocsparse_create_const_coo_descr(spMatDescr[0]->get_const_spmat_descr_reference(),
                                          rows,
                                          cols,
                                          nnz,
@@ -227,8 +381,13 @@ hipsparseStatus_t hipsparseCreateBlockedEll(hipsparseSpMatDescr_t* spMatDescr,
                                             hipsparseIndexBase_t   idxBase,
                                             hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_bell_descr((rocsparse_spmat_descr*)spMatDescr,
+        rocsparse_create_bell_descr(spMatDescr[0]->get_spmat_descr_reference(),
                                     rows,
                                     cols,
                                     rocsparse_direction_column,
@@ -252,8 +411,13 @@ hipsparseStatus_t hipsparseCreateConstBlockedEll(hipsparseConstSpMatDescr_t* spM
                                                  hipsparseIndexBase_t        idxBase,
                                                  hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_const_bell_descr((rocsparse_const_spmat_descr*)spMatDescr,
+        rocsparse_create_const_bell_descr(spMatDescr[0]->get_const_spmat_descr_reference(),
                                           rows,
                                           cols,
                                           rocsparse_direction_column,
@@ -276,8 +440,13 @@ hipsparseStatus_t hipsparseCreateCooAoS(hipsparseSpMatDescr_t* spMatDescr,
                                         hipsparseIndexBase_t   idxBase,
                                         hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_coo_aos_descr((rocsparse_spmat_descr*)spMatDescr,
+        rocsparse_create_coo_aos_descr(spMatDescr[0]->get_spmat_descr_reference(),
                                        rows,
                                        cols,
                                        nnz,
@@ -319,8 +488,14 @@ hipsparseStatus_t hipsparseCreateCsr(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
+
     return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_create_csr_descr_SWDEV_453599(
-        (rocsparse_spmat_descr*)spMatDescr,
+        spMatDescr[0]->get_spmat_descr_reference(),
         rows,
         cols,
         nnz,
@@ -345,8 +520,14 @@ hipsparseStatus_t hipsparseCreateConstCsr(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
+
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_const_csr_descr((rocsparse_const_spmat_descr*)spMatDescr,
+        rocsparse_create_const_csr_descr(spMatDescr[0]->get_const_spmat_descr_reference(),
                                          rows,
                                          cols,
                                          nnz,
@@ -371,8 +552,14 @@ hipsparseStatus_t hipsparseCreateCsc(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
+
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_csc_descr((rocsparse_spmat_descr*)spMatDescr,
+        rocsparse_create_csc_descr(spMatDescr[0]->get_spmat_descr_reference(),
                                    rows,
                                    cols,
                                    nnz,
@@ -397,8 +584,13 @@ hipsparseStatus_t hipsparseCreateConstCsc(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+    spMatDescr[0] = new hipsparseSpMatDescr_st();
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_create_const_csc_descr((rocsparse_const_spmat_descr*)spMatDescr,
+        rocsparse_create_const_csc_descr(spMatDescr[0]->get_const_spmat_descr_reference(),
                                          rows,
                                          cols,
                                          nnz,
@@ -413,8 +605,9 @@ hipsparseStatus_t hipsparseCreateConstCsc(hipsparseConstSpMatDescr_t* spMatDescr
 
 hipsparseStatus_t hipsparseDestroySpMat(hipsparseConstSpMatDescr_t spMatDescr)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_destroy_spmat_descr((rocsparse_const_spmat_descr)spMatDescr));
+    RETURN_IF_ROCSPARSE_ERROR(
+        rocsparse_destroy_spmat_descr(to_rocsparse_const_spmat_descr(spMatDescr)));
+    return HIPSPARSE_STATUS_SUCCESS;
 }
 
 hipsparseStatus_t hipsparseBlockedEllGet(const hipsparseSpMatDescr_t spMatDescr,
@@ -433,7 +626,7 @@ hipsparseStatus_t hipsparseBlockedEllGet(const hipsparseSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
     rocsparse_direction  hcc_block_direction;
 
-    RETURN_IF_ROCSPARSE_ERROR(rocsparse_bell_get((const rocsparse_spmat_descr)spMatDescr,
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_bell_get(to_rocsparse_spmat_descr(spMatDescr),
                                                  rows,
                                                  cols,
                                                  &hcc_block_direction,
@@ -469,7 +662,7 @@ hipsparseStatus_t hipsparseConstBlockedEllGet(hipsparseConstSpMatDescr_t spMatDe
     rocsparse_direction  hcc_block_direction;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_const_bell_get((const rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_const_bell_get(to_rocsparse_const_spmat_descr(spMatDescr),
                                  rows,
                                  cols,
                                  &hcc_block_direction,
@@ -503,7 +696,7 @@ hipsparseStatus_t hipsparseCooGet(const hipsparseSpMatDescr_t spMatDescr,
     rocsparse_index_base hcc_index_base;
     rocsparse_datatype   hcc_data_type;
 
-    RETURN_IF_ROCSPARSE_ERROR(rocsparse_coo_get((const rocsparse_spmat_descr)spMatDescr,
+    RETURN_IF_ROCSPARSE_ERROR(rocsparse_coo_get(to_rocsparse_spmat_descr(spMatDescr),
                                                 rows,
                                                 cols,
                                                 nnz,
@@ -537,7 +730,7 @@ hipsparseStatus_t hipsparseConstCooGet(hipsparseConstSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_const_coo_get((const rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_const_coo_get(to_rocsparse_const_spmat_descr(spMatDescr),
                                 rows,
                                 cols,
                                 nnz,
@@ -570,7 +763,7 @@ hipsparseStatus_t hipsparseCooAoSGet(const hipsparseSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_coo_aos_get((const rocsparse_spmat_descr)spMatDescr,
+        rocsparse_coo_aos_get(to_rocsparse_spmat_descr(spMatDescr),
                               rows,
                               cols,
                               nnz,
@@ -605,7 +798,7 @@ hipsparseStatus_t hipsparseCsrGet(const hipsparseSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_csr_get((const rocsparse_spmat_descr)spMatDescr,
+        rocsparse_csr_get(to_rocsparse_spmat_descr(spMatDescr),
                           rows,
                           cols,
                           nnz,
@@ -643,7 +836,7 @@ hipsparseStatus_t hipsparseConstCsrGet(hipsparseConstSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_const_csr_get((const rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_const_csr_get(to_rocsparse_const_spmat_descr(spMatDescr),
                                 rows,
                                 cols,
                                 nnz,
@@ -668,8 +861,9 @@ hipsparseStatus_t hipsparseCsrSetPointers(hipsparseSpMatDescr_t spMatDescr,
                                           void*                 csrColInd,
                                           void*                 csrValues)
 {
+
     return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_csr_set_pointers(
-        (rocsparse_spmat_descr)spMatDescr, csrRowOffsets, csrColInd, csrValues));
+        to_rocsparse_spmat_descr(spMatDescr), csrRowOffsets, csrColInd, csrValues));
 }
 
 hipsparseStatus_t hipsparseCscGet(const hipsparseSpMatDescr_t spMatDescr,
@@ -690,7 +884,7 @@ hipsparseStatus_t hipsparseCscGet(const hipsparseSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_csc_get((const rocsparse_spmat_descr)spMatDescr,
+        rocsparse_csc_get(to_rocsparse_spmat_descr(spMatDescr),
                           rows,
                           cols,
                           nnz,
@@ -728,7 +922,7 @@ hipsparseStatus_t hipsparseConstCscGet(hipsparseConstSpMatDescr_t spMatDescr,
     rocsparse_datatype   hcc_data_type;
 
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_const_csc_get((const rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_const_csc_get(to_rocsparse_const_spmat_descr(spMatDescr),
                                 rows,
                                 cols,
                                 nnz,
@@ -754,7 +948,7 @@ hipsparseStatus_t hipsparseCscSetPointers(hipsparseSpMatDescr_t spMatDescr,
                                           void*                 cscValues)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_csc_set_pointers(
-        (rocsparse_spmat_descr)spMatDescr, cscColOffsets, cscRowInd, cscValues));
+        to_rocsparse_spmat_descr(spMatDescr), cscColOffsets, cscRowInd, cscValues));
 }
 
 hipsparseStatus_t hipsparseCooSetPointers(hipsparseSpMatDescr_t spMatDescr,
@@ -763,7 +957,7 @@ hipsparseStatus_t hipsparseCooSetPointers(hipsparseSpMatDescr_t spMatDescr,
                                           void*                 cooValues)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_coo_set_pointers(
-        (rocsparse_spmat_descr)spMatDescr, cooRowInd, cooColInd, cooValues));
+        to_rocsparse_spmat_descr(spMatDescr), cooRowInd, cooColInd, cooValues));
 }
 
 hipsparseStatus_t hipsparseSpMatGetSize(hipsparseConstSpMatDescr_t spMatDescr,
@@ -772,7 +966,7 @@ hipsparseStatus_t hipsparseSpMatGetSize(hipsparseConstSpMatDescr_t spMatDescr,
                                         int64_t*                   nnz)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_get_size((rocsparse_const_spmat_descr)spMatDescr, rows, cols, nnz));
+        rocsparse_spmat_get_size(to_rocsparse_const_spmat_descr(spMatDescr), rows, cols, nnz));
 }
 
 hipsparseStatus_t hipsparseSpMatGetFormat(hipsparseConstSpMatDescr_t spMatDescr,
@@ -780,7 +974,7 @@ hipsparseStatus_t hipsparseSpMatGetFormat(hipsparseConstSpMatDescr_t spMatDescr,
 {
     rocsparse_format hcc_format;
     RETURN_IF_ROCSPARSE_ERROR(rocsparse_spmat_get_format(
-        (const rocsparse_const_spmat_descr)spMatDescr, format != nullptr ? &hcc_format : nullptr));
+        to_rocsparse_const_spmat_descr(spMatDescr), format != nullptr ? &hcc_format : nullptr));
 
     *format = hipsparse::HCCFormatToHIPFormat(hcc_format);
 
@@ -792,7 +986,7 @@ hipsparseStatus_t hipsparseSpMatGetIndexBase(hipsparseConstSpMatDescr_t spMatDes
 {
     rocsparse_index_base hcc_index_base;
     RETURN_IF_ROCSPARSE_ERROR(
-        rocsparse_spmat_get_index_base((const rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_spmat_get_index_base(to_rocsparse_const_spmat_descr(spMatDescr),
                                        idxBase != nullptr ? &hcc_index_base : nullptr));
 
     *idxBase = hipsparse::HCCBaseToHIPBase(hcc_index_base);
@@ -803,33 +997,33 @@ hipsparseStatus_t hipsparseSpMatGetIndexBase(hipsparseConstSpMatDescr_t spMatDes
 hipsparseStatus_t hipsparseSpMatGetValues(hipsparseSpMatDescr_t spMatDescr, void** values)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_get_values((rocsparse_spmat_descr)spMatDescr, values));
+        rocsparse_spmat_get_values(to_rocsparse_spmat_descr(spMatDescr), values));
 }
 
 hipsparseStatus_t hipsparseConstSpMatGetValues(hipsparseConstSpMatDescr_t spMatDescr,
                                                const void**               values)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_const_spmat_get_values((rocsparse_const_spmat_descr)spMatDescr, values));
+        rocsparse_const_spmat_get_values(to_rocsparse_const_spmat_descr(spMatDescr), values));
 }
 
 hipsparseStatus_t hipsparseSpMatSetValues(hipsparseSpMatDescr_t spMatDescr, void* values)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_set_values((rocsparse_spmat_descr)spMatDescr, values));
+        rocsparse_spmat_set_values(to_rocsparse_spmat_descr(spMatDescr), values));
 }
 
 hipsparseStatus_t hipsparseSpMatGetStridedBatch(hipsparseConstSpMatDescr_t spMatDescr,
                                                 int*                       batchCount)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_get_strided_batch((rocsparse_const_spmat_descr)spMatDescr, batchCount));
+        rocsparse_spmat_get_strided_batch(to_rocsparse_const_spmat_descr(spMatDescr), batchCount));
 }
 
 hipsparseStatus_t hipsparseSpMatSetStridedBatch(hipsparseSpMatDescr_t spMatDescr, int batchCount)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_set_strided_batch((rocsparse_spmat_descr)spMatDescr, batchCount));
+        rocsparse_spmat_set_strided_batch(to_rocsparse_spmat_descr(spMatDescr), batchCount));
 }
 
 hipsparseStatus_t hipsparseCooSetStridedBatch(hipsparseSpMatDescr_t spMatDescr,
@@ -837,7 +1031,7 @@ hipsparseStatus_t hipsparseCooSetStridedBatch(hipsparseSpMatDescr_t spMatDescr,
                                               int64_t               batchStride)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_coo_set_strided_batch(
-        (rocsparse_spmat_descr)spMatDescr, batchCount, batchStride));
+        to_rocsparse_spmat_descr(spMatDescr), batchCount, batchStride));
 }
 
 hipsparseStatus_t hipsparseCsrSetStridedBatch(hipsparseSpMatDescr_t spMatDescr,
@@ -846,7 +1040,7 @@ hipsparseStatus_t hipsparseCsrSetStridedBatch(hipsparseSpMatDescr_t spMatDescr,
                                               int64_t               columnsValuesBatchStride)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_csr_set_strided_batch((rocsparse_spmat_descr)spMatDescr,
+        rocsparse_csr_set_strided_batch(to_rocsparse_spmat_descr(spMatDescr),
                                         batchCount,
                                         offsetsBatchStride,
                                         columnsValuesBatchStride));
@@ -858,7 +1052,7 @@ hipsparseStatus_t hipsparseSpMatGetAttribute(hipsparseConstSpMatDescr_t spMatDes
                                              size_t                     dataSize)
 {
     return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmat_get_attribute((rocsparse_const_spmat_descr)spMatDescr,
+        rocsparse_spmat_get_attribute(to_rocsparse_const_spmat_descr(spMatDescr),
                                       (rocsparse_spmat_attribute)attribute,
                                       data,
                                       dataSize));
@@ -869,8 +1063,11 @@ hipsparseStatus_t hipsparseSpMatSetAttribute(hipsparseSpMatDescr_t     spMatDesc
                                              const void*               data,
                                              size_t                    dataSize)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(rocsparse_spmat_set_attribute(
-        (rocsparse_spmat_descr)spMatDescr, (rocsparse_spmat_attribute)attribute, data, dataSize));
+    return hipsparse::rocSPARSEStatusToHIPStatus(
+        rocsparse_spmat_set_attribute(to_rocsparse_spmat_descr(spMatDescr),
+                                      (rocsparse_spmat_attribute)attribute,
+                                      data,
+                                      dataSize));
 }
 
 hipsparseStatus_t hipsparseCreateDnVec(hipsparseDnVecDescr_t* dnVecDescr,
diff --git a/library/src/amd_detail/utility.h b/library/src/amd_detail/utility.h
index b875801d..424ab0a1 100644
--- a/library/src/amd_detail/utility.h
+++ b/library/src/amd_detail/utility.h
@@ -666,3 +666,67 @@ namespace hipsparse
         }
     }
 }
+
+struct hipsparseSpMVDescr_st
+{
+protected:
+    rocsparse_spmv_descr m_spmv_descr{};
+    bool                 m_is_stage_analysis_called{};
+    bool                 m_is_implicit_stage_analysis_called{};
+    size_t               m_buffer_size_stage_analysis{};
+    size_t               m_buffer_size_stage_compute{};
+    void*                m_buffer{};
+    bool                 m_is_stage_compute_subsequent{};
+    bool                 m_is_buffer_size_called{};
+
+public:
+    rocsparse_spmv_descr get_spmv_descr();
+    void                 set_spmv_descr(rocsparse_spmv_descr value);
+
+    bool is_stage_analysis_called() const;
+    void stage_analysis_called();
+
+    bool is_implicit_stage_analysis_called() const;
+    void implicit_stage_analysis_called();
+
+    bool is_stage_compute_subsequent() const;
+    void stage_compute_subsequent();
+
+    bool is_buffer_size_called() const;
+    void buffer_size_called();
+
+    size_t get_buffer_size_stage_analysis() const;
+    void   set_buffer_size_stage_analysis(size_t value);
+
+    size_t get_buffer_size_stage_compute() const;
+    void   set_buffer_size_stage_compute(size_t value);
+
+    void* get_buffer();
+    void  set_buffer(void* value);
+
+    void** get_buffer_reference();
+
+    hipsparseSpMVDescr_st() = default;
+    ~hipsparseSpMVDescr_st();
+};
+
+struct hipsparseSpMatDescr_st
+{
+protected:
+    rocsparse_spmat_descr         m_spmat_descr{};
+    mutable hipsparseSpMVDescr_st m_hip_spmv_descr{};
+
+public:
+    hipsparseSpMatDescr_st()  = default;
+    ~hipsparseSpMatDescr_st() = default;
+    hipsparseSpMVDescr_st*       get_hip_spmv_descr();
+    hipsparseSpMVDescr_st*       get_hip_spmv_descr() const;
+    rocsparse_spmat_descr        get_spmat_descr();
+    rocsparse_const_spmat_descr  get_const_spmat_descr() const;
+    rocsparse_spmat_descr*       get_spmat_descr_reference();
+    rocsparse_const_spmat_descr* get_const_spmat_descr_reference() const;
+    void                         set_spmat_descr(rocsparse_spmat_descr value);
+};
+
+rocsparse_spmat_descr       to_rocsparse_spmat_descr(const hipsparseSpMatDescr_t source);
+rocsparse_const_spmat_descr to_rocsparse_const_spmat_descr(const hipsparseConstSpMatDescr_t source);


Reviews:
user: login: jsandham
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T22:17:03Z
user: login: kliegeois
body: Looks overall good to me, just some `LCOV_EXCL` are missing for some `HIPSPARSE_STATUS_INVALID_VALUE` see comments.
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-27T22:20:51Z
user: login: jsandham
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T22:24:59Z
user: login: ntrost57
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T05:17:51Z
user: login: ntrost57
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T05:19:04Z
user: login: ntrost57
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T05:21:00Z
user: login: YvanMokwinski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-28T16:30:29Z
user: login: YvanMokwinski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-28T16:33:25Z
user: login: YvanMokwinski
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-28T16:34:35Z
user: login: jsandham
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T18:40:28Z

Review comments:
diff_hunk: @@ -41,19 +41,134 @@ hipsparseStatus_t hipsparseSpMV_bufferSize(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            size_t*                     pBufferSizeInBytes)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_buffer_size,
-                       pBufferSizeInBytes,
-                       nullptr));
+
+    if(handle == nullptr)
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(handle == nullptr)
```
created_at: 2025-05-27T22:12:27Z
author_association: COLLABORATOR
diff_hunk: @@ -41,19 +41,134 @@ hipsparseStatus_t hipsparseSpMV_bufferSize(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            size_t*                     pBufferSizeInBytes)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_buffer_size,
-                       pBufferSizeInBytes,
-                       nullptr));
+
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(pBufferSizeInBytes == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:12:44Z
author_association: COLLABORATOR
diff_hunk: @@ -67,20 +182,118 @@ hipsparseStatus_t hipsparseSpMV_preprocess(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_preprocess,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(handle == nullptr)
```
created_at: 2025-05-27T22:13:12Z
author_association: COLLABORATOR
diff_hunk: @@ -67,20 +182,118 @@ hipsparseStatus_t hipsparseSpMV_preprocess(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_preprocess,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:13:22Z
author_association: COLLABORATOR
diff_hunk: @@ -94,18 +307,214 @@ hipsparseStatus_t hipsparseSpMV(hipsparseHandle_t           handle,
                                 hipsparseSpMVAlg_t          alg,
                                 void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_compute,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(handle == nullptr)
```
created_at: 2025-05-27T22:13:45Z
author_association: COLLABORATOR
diff_hunk: @@ -94,18 +307,214 @@ hipsparseStatus_t hipsparseSpMV(hipsparseHandle_t           handle,
                                 hipsparseSpMVAlg_t          alg,
                                 void*                       externalBuffer)
 {
-    size_t bufferSize;
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_compute,
-                       &bufferSize,
-                       externalBuffer));
+    if(handle == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(alpha == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(matA == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecX == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(beta == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
+
+    if(vecY == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: kliegeois
body: ```suggestion
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:13:54Z
author_association: COLLABORATOR
diff_hunk: @@ -179,8 +323,13 @@ hipsparseStatus_t hipsparseCreateCoo(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:15:19Z
author_association: COLLABORATOR
diff_hunk: @@ -203,8 +352,13 @@ hipsparseStatus_t hipsparseCreateConstCoo(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:15:39Z
author_association: COLLABORATOR
diff_hunk: @@ -227,8 +381,13 @@ hipsparseStatus_t hipsparseCreateBlockedEll(hipsparseSpMatDescr_t* spMatDescr,
                                             hipsparseIndexBase_t   idxBase,
                                             hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:15:59Z
author_association: COLLABORATOR
diff_hunk: @@ -262,7 +262,7 @@ int main(int argc, char** argv)
     int ret = RUN_ALL_TESTS();
 
     // Reset HIP device
-    hipDeviceReset();
+    (void)hipDeviceReset();
path: clients/tests/hipsparse_gtest_main.cpp
user: login: jsandham
body: What does the (void) do?
created_at: 2025-05-27T22:17:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -252,8 +411,13 @@ hipsparseStatus_t hipsparseCreateConstBlockedEll(hipsparseConstSpMatDescr_t* spM
                                                  hipsparseIndexBase_t        idxBase,
                                                  hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:17:45Z
author_association: COLLABORATOR
diff_hunk: @@ -276,8 +440,13 @@ hipsparseStatus_t hipsparseCreateCooAoS(hipsparseSpMatDescr_t* spMatDescr,
                                         hipsparseIndexBase_t   idxBase,
                                         hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:18:20Z
author_association: COLLABORATOR
diff_hunk: @@ -319,8 +488,14 @@ hipsparseStatus_t hipsparseCreateCsr(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:18:41Z
author_association: COLLABORATOR
diff_hunk: @@ -345,8 +520,14 @@ hipsparseStatus_t hipsparseCreateConstCsr(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:19:04Z
author_association: COLLABORATOR
diff_hunk: @@ -371,8 +552,14 @@ hipsparseStatus_t hipsparseCreateCsc(hipsparseSpMatDescr_t* spMatDescr,
                                      hipsparseIndexBase_t   idxBase,
                                      hipDataType            valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:19:25Z
author_association: COLLABORATOR
diff_hunk: @@ -397,8 +584,13 @@ hipsparseStatus_t hipsparseCreateConstCsc(hipsparseConstSpMatDescr_t* spMatDescr
                                           hipsparseIndexBase_t        idxBase,
                                           hipDataType                 valueType)
 {
+    if(spMatDescr == nullptr)
+    {
+        return HIPSPARSE_STATUS_INVALID_VALUE;
+    }
path: library/src/amd_detail/hipsparse_generic_auxiliary.cpp
user: login: kliegeois
body: ```suggestion
    // LCOV_EXCL_START
    if(spMatDescr == nullptr)
    {
        return HIPSPARSE_STATUS_INVALID_VALUE;
    }
    // LCOV_EXCL_STOP
```
created_at: 2025-05-27T22:19:45Z
author_association: COLLABORATOR
diff_hunk: @@ -16,6 +16,7 @@ Documentation for hipSPARSE is available at
 ### Changed
 
 * Switch to defaulting to C++17 when building hipSPARSE from source. Previously hipSPARSE was using C++14 by default.
+* Implementation of hipsparseSpMV is now using rocsparse_v2_spmv since rocsparse_spmv is deprecated.
path: CHANGELOG.md
user: login: jsandham
body: I am not sure we need to include this in the changelog as this is purely an implementation detail that does not affect the public API. In the past we have never noted these kinds of changes in the changelog I don't think.
created_at: 2025-05-27T22:24:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -16,6 +16,7 @@ Documentation for hipSPARSE is available at
 ### Changed
 
 * Switch to defaulting to C++17 when building hipSPARSE from source. Previously hipSPARSE was using C++14 by default.
+* Implementation of hipsparseSpMV is now using rocsparse_v2_spmv since rocsparse_spmv is deprecated.
path: CHANGELOG.md
user: login: ntrost57
body: Yeah, I'd leave that out as it doesnt impact anyone.
created_at: 2025-05-28T05:17:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -262,7 +262,7 @@ int main(int argc, char** argv)
     int ret = RUN_ALL_TESTS();
 
     // Reset HIP device
-    hipDeviceReset();
+    (void)hipDeviceReset();
path: clients/tests/hipsparse_gtest_main.cpp
user: login: ntrost57
body: I think you can put it to suppress compiler warning for ignoring the return value.
created_at: 2025-05-28T05:19:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,19 +41,134 @@ hipsparseStatus_t hipsparseSpMV_bufferSize(hipsparseHandle_t           handle,
                                            hipsparseSpMVAlg_t          alg,
                                            size_t*                     pBufferSizeInBytes)
 {
-    return hipsparse::rocSPARSEStatusToHIPStatus(
-        rocsparse_spmv((rocsparse_handle)handle,
-                       hipsparse::hipOperationToHCCOperation(opA),
-                       alpha,
-                       (rocsparse_const_spmat_descr)matA,
-                       (rocsparse_const_dnvec_descr)vecX,
-                       beta,
-                       (const rocsparse_dnvec_descr)vecY,
-                       hipsparse::hipDataTypeToHCCDataType(computeType),
-                       hipsparse::hipSpMVAlgToHCCSpMVAlg(alg),
-                       rocsparse_spmv_stage_buffer_size,
-                       pBufferSizeInBytes,
-                       nullptr));
+
+    if(handle == nullptr)
path: library/src/amd_detail/generic/hipsparse_spmv.cpp
user: login: YvanMokwinski
body: No, these are tested in bad_arg.
created_at: 2025-05-28T16:30:29Z
author_association: COLLABORATOR
diff_hunk: @@ -16,6 +16,7 @@ Documentation for hipSPARSE is available at
 ### Changed
 
 * Switch to defaulting to C++17 when building hipSPARSE from source. Previously hipSPARSE was using C++14 by default.
+* Implementation of hipsparseSpMV is now using rocsparse_v2_spmv since rocsparse_spmv is deprecated.
path: CHANGELOG.md
user: login: YvanMokwinski
body: k
created_at: 2025-05-28T16:33:24Z
author_association: COLLABORATOR
diff_hunk: @@ -262,7 +262,7 @@ int main(int argc, char** argv)
     int ret = RUN_ALL_TESTS();
 
     // Reset HIP device
-    hipDeviceReset();
+    (void)hipDeviceReset();
path: clients/tests/hipsparse_gtest_main.cpp
user: login: YvanMokwinski
body: To explicitly ignore the returned value.
created_at: 2025-05-28T16:34:35Z
author_association: COLLABORATOR
diff_hunk: @@ -262,7 +262,7 @@ int main(int argc, char** argv)
     int ret = RUN_ALL_TESTS();
 
     // Reset HIP device
-    hipDeviceReset();
+    (void)hipDeviceReset();
path: clients/tests/hipsparse_gtest_main.cpp
user: login: jsandham
body: You can use std::ignore which is what we do in rocSPARSE, std::ignore = hipDeviceReset();
created_at: 2025-05-28T18:40:28Z
author_association: CONTRIBUTOR

PR comments:
user: login: ntrost57
created_at: 2025-05-28T05:22:36Z
body: bad arg test from spmat descriptor fails
author_association: CONTRIBUTOR
user: login: YvanMokwinski
created_at: 2025-05-28T16:34:05Z
body: > Looks overall good to me, just some `LCOV_EXCL` are missing for some `HIPSPARSE_STATUS_INVALID_VALUE` see comments.

No. These are tested.
author_association: COLLABORATOR
user: login: kliegeois
created_at: 2025-05-28T16:36:35Z
body: > > Looks overall good to me, just some `LCOV_EXCL` are missing for some `HIPSPARSE_STATUS_INVALID_VALUE` see comments.
> 
> No. These are tested.

Sounds good to me then! 
author_association: COLLABORATOR