// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
//
// SPDX-License-Identifier: BSD-3-Clause

#ifndef GKO_HIP_BASE_HIPSPARSE_BINDINGS_HIP_HPP_
#define GKO_HIP_BASE_HIPSPARSE_BINDINGS_HIP_HPP_


#include <hip/hip_runtime.h>
#if HIP_VERSION >= 50200000
#include <hipsparse/hipsparse.h>
#else
#include <hipsparse.h>
#endif


#include <ginkgo/core/base/exception_helpers.hpp>
#include <ginkgo/core/base/executor.hpp>


#include "hip/base/types.hip.hpp"


namespace gko {
namespace kernels {
namespace hip {
/**
 * @brief The HIPSPARSE namespace.
 *
 * @ingroup hipsparse
 */
namespace hipsparse {
/**
 * @brief The detail namespace.
 *
 * @ingroup detail
 */
namespace detail {


template <typename... Args>
inline int64 not_implemented(Args...)
{
    return static_cast<int64>(HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED);
}


}  // namespace detail


template <typename ValueType, typename IndexType>
struct is_supported : std::false_type {};

template <>
struct is_supported<float, int32> : std::true_type {};

template <>
struct is_supported<double, int32> : std::true_type {};

template <>
struct is_supported<std::complex<float>, int32> : std::true_type {};

template <>
struct is_supported<std::complex<double>, int32> : std::true_type {};

#define GKO_BIND_HIPSPARSE32_SPMV(ValueType, HipsparseName)                  \
    inline void spmv(hipsparseHandle_t handle, hipsparseOperation_t transA,  \
                     int32 m, int32 n, int32 nnz, const ValueType* alpha,    \
                     const hipsparseMatDescr_t descrA,                       \
                     const ValueType* csrValA, const int32* csrRowPtrA,      \
                     const int32* csrColIndA, const ValueType* x,            \
                     const ValueType* beta, ValueType* y)                    \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                        \
            handle, transA, m, n, nnz, as_hiplibs_type(alpha), descrA,       \
            as_hiplibs_type(csrValA), csrRowPtrA, csrColIndA,                \
            as_hiplibs_type(x), as_hiplibs_type(beta), as_hiplibs_type(y))); \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_SPMV(ValueType, HipsparseName)                    \
    inline void spmv(hipsparseHandle_t handle, hipsparseOperation_t transA,    \
                     int64 m, int64 n, int64 nnz, const ValueType* alpha,      \
                     const hipsparseMatDescr_t descrA,                         \
                     const ValueType* csrValA, const int64* csrRowPtrA,        \
                     const int64* csrColIndA, const ValueType* x,              \
                     const ValueType* beta, ValueType* y) GKO_NOT_IMPLEMENTED; \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_SPMV(float, hipsparseScsrmv);
GKO_BIND_HIPSPARSE32_SPMV(double, hipsparseDcsrmv);
GKO_BIND_HIPSPARSE32_SPMV(std::complex<float>, hipsparseCcsrmv);
GKO_BIND_HIPSPARSE32_SPMV(std::complex<double>, hipsparseZcsrmv);
GKO_BIND_HIPSPARSE64_SPMV(float, hipsparseScsrmv);
GKO_BIND_HIPSPARSE64_SPMV(double, hipsparseDcsrmv);
GKO_BIND_HIPSPARSE64_SPMV(std::complex<float>, hipsparseCcsrmv);
GKO_BIND_HIPSPARSE64_SPMV(std::complex<double>, hipsparseZcsrmv);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_SPMV(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_SPMV(ValueType, detail::not_implemented);


#undef GKO_BIND_HIPSPARSE32_SPMV
#undef GKO_BIND_HIPSPARSE64_SPMV


#define GKO_BIND_HIPSPARSE32_SPMM(ValueType, HipsparseName)                    \
    inline void spmm(hipsparseHandle_t handle, hipsparseOperation_t transA,    \
                     int32 m, int32 n, int32 k, int32 nnz,                     \
                     const ValueType* alpha, const hipsparseMatDescr_t descrA, \
                     const ValueType* csrValA, const int32* csrRowPtrA,        \
                     const int32* csrColIndA, const ValueType* B, int32 ldb,   \
                     const ValueType* beta, ValueType* C, int32 ldc)           \
    {                                                                          \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                          \
            handle, transA, m, n, k, nnz, as_hiplibs_type(alpha), descrA,      \
            as_hiplibs_type(csrValA), csrRowPtrA, csrColIndA,                  \
            as_hiplibs_type(B), ldb, as_hiplibs_type(beta),                    \
            as_hiplibs_type(C), ldc));                                         \
    }                                                                          \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_SPMM(ValueType, HipsparseName)                    \
    inline void spmm(hipsparseHandle_t handle, hipsparseOperation_t transA,    \
                     int64 m, int64 n, int64 k, int64 nnz,                     \
                     const ValueType* alpha, const hipsparseMatDescr_t descrA, \
                     const ValueType* csrValA, const int64* csrRowPtrA,        \
                     const int64* csrColIndA, const ValueType* B, int64 ldb,   \
                     const ValueType* beta, ValueType* C, int64 ldc)           \
        GKO_NOT_IMPLEMENTED;                                                   \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_SPMM(float, hipsparseScsrmm);
GKO_BIND_HIPSPARSE32_SPMM(double, hipsparseDcsrmm);
GKO_BIND_HIPSPARSE32_SPMM(std::complex<float>, hipsparseCcsrmm);
GKO_BIND_HIPSPARSE32_SPMM(std::complex<double>, hipsparseZcsrmm);
GKO_BIND_HIPSPARSE64_SPMM(float, hipsparseScsrmm);
GKO_BIND_HIPSPARSE64_SPMM(double, hipsparseDcsrmm);
GKO_BIND_HIPSPARSE64_SPMM(std::complex<float>, hipsparseCcsrmm);
GKO_BIND_HIPSPARSE64_SPMM(std::complex<double>, hipsparseZcsrmm);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_SPMM(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_SPMM(ValueType, detail::not_implemented);


#undef GKO_BIND_HIPSPARSE32_SPMM
#undef GKO_BIND_HIPSPARSE64_SPMM


#define GKO_BIND_HIPSPARSE32_SPMV(ValueType, HipsparseName)                    \
    inline void spmv(hipsparseHandle_t handle, hipsparseOperation_t transA,    \
                     const ValueType* alpha, const hipsparseMatDescr_t descrA, \
                     const hipsparseHybMat_t hybA, const ValueType* x,         \
                     const ValueType* beta, ValueType* y)                      \
    {                                                                          \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                          \
            handle, transA, as_hiplibs_type(alpha), descrA, hybA,              \
            as_hiplibs_type(x), as_hiplibs_type(beta), as_hiplibs_type(y)));   \
    }                                                                          \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_SPMV(float, hipsparseShybmv);
GKO_BIND_HIPSPARSE32_SPMV(double, hipsparseDhybmv);
GKO_BIND_HIPSPARSE32_SPMV(std::complex<float>, hipsparseChybmv);
GKO_BIND_HIPSPARSE32_SPMV(std::complex<double>, hipsparseZhybmv);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_SPMV(ValueType, detail::not_implemented);


#undef GKO_BIND_HIPSPARSE32_SPMV


template <typename ValueType, typename IndexType>
void spgemm_buffer_size(
    hipsparseHandle_t handle, IndexType m, IndexType n, IndexType k,
    const ValueType* alpha, const hipsparseMatDescr_t descrA, IndexType nnzA,
    const IndexType* csrRowPtrA, const IndexType* csrColIndA,
    const hipsparseMatDescr_t descrB, IndexType nnzB,
    const IndexType* csrRowPtrB, const IndexType* csrColIndB,
    const ValueType* beta, const hipsparseMatDescr_t descrD, IndexType nnzD,
    const IndexType* csrRowPtrD, const IndexType* csrColIndD,
    csrgemm2Info_t info, size_type& result) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE(ValueType, HipsparseName)        \
    template <>                                                                \
    inline void spgemm_buffer_size<ValueType, int32>(                          \
        hipsparseHandle_t handle, int32 m, int32 n, int32 k,                   \
        const ValueType* alpha, const hipsparseMatDescr_t descrA, int32 nnzA,  \
        const int32* csrRowPtrA, const int32* csrColIndA,                      \
        const hipsparseMatDescr_t descrB, int32 nnzB, const int32* csrRowPtrB, \
        const int32* csrColIndB, const ValueType* beta,                        \
        const hipsparseMatDescr_t descrD, int32 nnzD, const int32* csrRowPtrD, \
        const int32* csrColIndD, csrgemm2Info_t info, size_type& result)       \
    {                                                                          \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                          \
            handle, m, n, k, as_hiplibs_type(alpha), descrA, nnzA, csrRowPtrA, \
            csrColIndA, descrB, nnzB, csrRowPtrB, csrColIndB,                  \
            as_hiplibs_type(beta), descrD, nnzD, csrRowPtrD, csrColIndD, info, \
            &result));                                                         \
    }                                                                          \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE(float, hipsparseScsrgemm2_bufferSizeExt);
GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE(double, hipsparseDcsrgemm2_bufferSizeExt);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE(std::complex<float>,
                                      hipsparseCcsrgemm2_bufferSizeExt);
GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE(std::complex<double>,
                                      hipsparseZcsrgemm2_bufferSizeExt);
#endif  // hipsparse version >= 1.4


#undef GKO_BIND_HIPSPARSE_SPGEMM_BUFFER_SIZE


template <typename IndexType>
void spgemm_nnz(hipsparseHandle_t handle, IndexType m, IndexType n, IndexType k,
                const hipsparseMatDescr_t descrA, IndexType nnzA,
                const IndexType* csrRowPtrA, const IndexType* csrColIndA,
                const hipsparseMatDescr_t descrB, IndexType nnzB,
                const IndexType* csrRowPtrB, const IndexType* csrColIndB,
                const hipsparseMatDescr_t descrD, IndexType nnzD,
                const IndexType* csrRowPtrD, const IndexType* csrColIndD,
                const hipsparseMatDescr_t descrC, IndexType* csrRowPtrC,
                IndexType* nnzC, csrgemm2Info_t info,
                void* buffer) GKO_NOT_IMPLEMENTED;

template <>
inline void spgemm_nnz<int32>(
    hipsparseHandle_t handle, int32 m, int32 n, int32 k,
    const hipsparseMatDescr_t descrA, int32 nnzA, const int32* csrRowPtrA,
    const int32* csrColIndA, const hipsparseMatDescr_t descrB, int32 nnzB,
    const int32* csrRowPtrB, const int32* csrColIndB,
    const hipsparseMatDescr_t descrD, int32 nnzD, const int32* csrRowPtrD,
    const int32* csrColIndD, const hipsparseMatDescr_t descrC,
    int32* csrRowPtrC, int32* nnzC, csrgemm2Info_t info, void* buffer)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseXcsrgemm2Nnz(
        handle, m, n, k, descrA, nnzA, csrRowPtrA, csrColIndA, descrB, nnzB,
        csrRowPtrB, csrColIndB, descrD, nnzD, csrRowPtrD, csrColIndD, descrC,
        csrRowPtrC, nnzC, info, buffer));
}


template <typename ValueType, typename IndexType>
void spgemm(hipsparseHandle_t handle, IndexType m, IndexType n, IndexType k,
            const ValueType* alpha, const hipsparseMatDescr_t descrA,
            IndexType nnzA, const ValueType* csrValA,
            const IndexType* csrRowPtrA, const IndexType* csrColIndA,
            const hipsparseMatDescr_t descrB, IndexType nnzB,
            const ValueType* csrValB, const IndexType* csrRowPtrB,
            const IndexType* csrColIndB, const ValueType* beta,
            const hipsparseMatDescr_t descrD, IndexType nnzD,
            const ValueType* csrValD, const IndexType* csrRowPtrD,
            const IndexType* csrColIndD, const hipsparseMatDescr_t descrC,
            ValueType* csrValC, const IndexType* csrRowPtrC,
            IndexType* csrColIndC, csrgemm2Info_t info,
            void* buffer) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_SPGEMM(ValueType, HipsparseName)                    \
    template <>                                                                \
    inline void spgemm<ValueType, int32>(                                      \
        hipsparseHandle_t handle, int32 m, int32 n, int32 k,                   \
        const ValueType* alpha, const hipsparseMatDescr_t descrA, int32 nnzA,  \
        const ValueType* csrValA, const int32* csrRowPtrA,                     \
        const int32* csrColIndA, const hipsparseMatDescr_t descrB, int32 nnzB, \
        const ValueType* csrValB, const int32* csrRowPtrB,                     \
        const int32* csrColIndB, const ValueType* beta,                        \
        const hipsparseMatDescr_t descrD, int32 nnzD,                          \
        const ValueType* csrValD, const int32* csrRowPtrD,                     \
        const int32* csrColIndD, const hipsparseMatDescr_t descrC,             \
        ValueType* csrValC, const int32* csrRowPtrC, int32* csrColIndC,        \
        csrgemm2Info_t info, void* buffer)                                     \
    {                                                                          \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                          \
            handle, m, n, k, as_hiplibs_type(alpha), descrA, nnzA,             \
            as_hiplibs_type(csrValA), csrRowPtrA, csrColIndA, descrB, nnzB,    \
            as_hiplibs_type(csrValB), csrRowPtrB, csrColIndB,                  \
            as_hiplibs_type(beta), descrD, nnzD, as_hiplibs_type(csrValD),     \
            csrRowPtrD, csrColIndD, descrC, as_hiplibs_type(csrValC),          \
            csrRowPtrC, csrColIndC, info, buffer));                            \
    }                                                                          \
    static_assert(true,                                                        \
                  "This assert is used to counter the false positive extra "   \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_SPGEMM(float, hipsparseScsrgemm2);
GKO_BIND_HIPSPARSE_SPGEMM(double, hipsparseDcsrgemm2);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_SPGEMM(std::complex<float>, hipsparseCcsrgemm2);
GKO_BIND_HIPSPARSE_SPGEMM(std::complex<double>, hipsparseZcsrgemm2);
#endif  // hipsparse version >= 1.4


#undef GKO_BIND_HIPSPARSE_SPGEMM


#define GKO_BIND_HIPSPARSE32_CSR2HYB(ValueType, HipsparseName)               \
    inline void csr2hyb(hipsparseHandle_t handle, int32 m, int32 n,          \
                        const hipsparseMatDescr_t descrA,                    \
                        const ValueType* csrValA, const int32* csrRowPtrA,   \
                        const int32* csrColIndA, hipsparseHybMat_t hybA,     \
                        int32 userEllWidth,                                  \
                        hipsparseHybPartition_t partitionType)               \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                        \
            handle, m, n, descrA, as_hiplibs_type(csrValA), csrRowPtrA,      \
            csrColIndA, hybA, userEllWidth, partitionType));                 \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_CSR2HYB(ValueType, HipsparseName)               \
    inline void csr2hyb(                                                     \
        hipsparseHandle_t handle, int64 m, int64 n,                          \
        const hipsparseMatDescr_t descrA, const ValueType* csrValA,          \
        const int64* csrRowPtrA, const int64* csrColIndA,                    \
        hipsparseHybMat_t hybA, int64 userEllWidth,                          \
        hipsparseHybPartition_t partitionType) GKO_NOT_IMPLEMENTED;          \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_CSR2HYB(float, hipsparseScsr2hyb);
GKO_BIND_HIPSPARSE32_CSR2HYB(double, hipsparseDcsr2hyb);
GKO_BIND_HIPSPARSE64_CSR2HYB(float, hipsparseScsr2hyb);
GKO_BIND_HIPSPARSE64_CSR2HYB(double, hipsparseDcsr2hyb);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_CSR2HYB(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_CSR2HYB(ValueType, detail::not_implemented);


#undef GKO_BIND_HIPSPARSE32_CSR2HYB
#undef GKO_BIND_HIPSPARSE64_CSR2HYB


#define GKO_BIND_HIPSPARSE_TRANSPOSE32(ValueType, HipsparseName)              \
    inline void transpose(hipsparseHandle_t handle, size_type m, size_type n, \
                          size_type nnz, const ValueType* OrigValA,           \
                          const int32* OrigRowPtrA, const int32* OrigColIndA, \
                          ValueType* TransValA, int32* TransRowPtrA,          \
                          int32* TransColIndA, hipsparseAction_t copyValues,  \
                          hipsparseIndexBase_t idxBase)                       \
    {                                                                         \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                         \
            handle, m, n, nnz, as_hiplibs_type(OrigValA), OrigRowPtrA,        \
            OrigColIndA, as_hiplibs_type(TransValA), TransColIndA,            \
            TransRowPtrA, copyValues, idxBase));                              \
    }                                                                         \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE_TRANSPOSE64(ValueType, HipsparseName)              \
    inline void transpose(hipsparseHandle_t handle, size_type m, size_type n, \
                          size_type nnz, const ValueType* OrigValA,           \
                          const int64* OrigRowPtrA, const int64* OrigColIndA, \
                          ValueType* TransValA, int64* TransRowPtrA,          \
                          int64* TransColIndA, hipsparseAction_t copyValues,  \
                          hipsparseIndexBase_t idxBase) GKO_NOT_IMPLEMENTED;  \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_TRANSPOSE32(float, hipsparseScsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE32(double, hipsparseDcsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE32(std::complex<float>, hipsparseCcsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE32(std::complex<double>, hipsparseZcsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE64(float, hipsparseScsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE64(double, hipsparseDcsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE64(std::complex<float>, hipsparseCcsr2csc);
GKO_BIND_HIPSPARSE_TRANSPOSE64(std::complex<double>, hipsparseZcsr2csc);
template <typename ValueType>
GKO_BIND_HIPSPARSE_TRANSPOSE32(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE_TRANSPOSE64(ValueType, detail::not_implemented);

#undef GKO_BIND_HIPSPARSE_TRANSPOSE

#define GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(ValueType, HipsparseName)        \
    inline void conj_transpose(                                              \
        hipsparseHandle_t handle, size_type m, size_type n, size_type nnz,   \
        const ValueType* OrigValA, const int32* OrigRowPtrA,                 \
        const int32* OrigColIndA, ValueType* TransValA, int32* TransRowPtrA, \
        int32* TransColIndA, hipsparseAction_t copyValues,                   \
        hipsparseIndexBase_t idxBase) GKO_NOT_IMPLEMENTED;                   \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(ValueType, HipsparseName)        \
    inline void conj_transpose(                                              \
        hipsparseHandle_t handle, size_type m, size_type n, size_type nnz,   \
        const ValueType* OrigValA, const int64* OrigRowPtrA,                 \
        const int64* OrigColIndA, ValueType* TransValA, int64* TransRowPtrA, \
        int64* TransColIndA, hipsparseAction_t copyValues,                   \
        hipsparseIndexBase_t idxBase) GKO_NOT_IMPLEMENTED;                   \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(float, hipsparseScsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(double, hipsparseDcsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(std::complex<float>, hipsparseCcsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(std::complex<double>, hipsparseZcsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(float, hipsparseScsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(double, hipsparseDcsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(std::complex<float>, hipsparseCcsr2csc);
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(std::complex<double>, hipsparseZcsr2csc);
template <typename ValueType>
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE32(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE64(ValueType, detail::not_implemented);

#undef GKO_BIND_HIPSPARSE_CONJ_TRANSPOSE


#define GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(ValueType, HipsparseName)     \
    inline void csrsv2_buffer_size(                                          \
        hipsparseHandle_t handle, hipsparseOperation_t trans,                \
        const size_type m, size_type nnz, const hipsparseMatDescr_t descr,   \
        const ValueType* csrVal, const int32* csrRowPtr,                     \
        const int32* csrColInd, csrsv2Info_t factor_info,                    \
        int* factor_work_size)                                               \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                        \
            handle, trans, m, nnz, descr,                                    \
            as_hiplibs_type(const_cast<ValueType*>(csrVal)), csrRowPtr,      \
            csrColInd, factor_info, factor_work_size));                      \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(ValueType, HipsparseName)   \
    inline void csrsv2_buffer_size(                                        \
        hipsparseHandle_t handle, hipsparseOperation_t trans, size_type m, \
        size_type nnz, const hipsparseMatDescr_t descr,                    \
        const ValueType* csrVal, const int64* csrRowPtr,                   \
        const int64* csrColInd, csrsv2Info_t factor_info,                  \
        int* factor_work_size) GKO_NOT_IMPLEMENTED;                        \
    static_assert(true,                                                    \
                  "This assert is used to counter the "                    \
                  "false positive extra "                                  \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(float, hipsparseScsrsv2_bufferSize);
GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(double, hipsparseDcsrsv2_bufferSize);
GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(std::complex<float>,
                                       hipsparseCcsrsv2_bufferSize);
GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(std::complex<double>,
                                       hipsparseZcsrsv2_bufferSize);
GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(float, hipsparseScsrsv2_bufferSize);
GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(double, hipsparseDcsrsv2_bufferSize);
GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(std::complex<float>,
                                       hipsparseCcsrsv2_bufferSize);
GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(std::complex<double>,
                                       hipsparseZcsrsv2_bufferSize);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE(ValueType, detail::not_implemented);
#undef GKO_BIND_HIPSPARSE32_CSRSV2_BUFFERSIZE
#undef GKO_BIND_HIPSPARSE64_CSRSV2_BUFFERSIZE

#define GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(ValueType, HipsparseName)        \
    inline void csrsv2_analysis(                                              \
        hipsparseHandle_t handle, hipsparseOperation_t trans, size_type m,    \
        size_type nnz, const hipsparseMatDescr_t descr,                       \
        const ValueType* csrVal, const int32* csrRowPtr,                      \
        const int32* csrColInd, csrsv2Info_t factor_info,                     \
        hipsparseSolvePolicy_t policy, void* factor_work_vec)                 \
    {                                                                         \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                         \
            handle, trans, m, nnz, descr, as_hiplibs_type(csrVal), csrRowPtr, \
            csrColInd, factor_info, policy, factor_work_vec));                \
    }                                                                         \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(ValueType, HipsparseName)     \
    inline void csrsv2_analysis(                                           \
        hipsparseHandle_t handle, hipsparseOperation_t trans, size_type m, \
        size_type nnz, const hipsparseMatDescr_t descr,                    \
        const ValueType* csrVal, const int64* csrRowPtr,                   \
        const int64* csrColInd, csrsv2Info_t factor_info,                  \
        hipsparseSolvePolicy_t policy, void* factor_work_vec)              \
        GKO_NOT_IMPLEMENTED;                                               \
    static_assert(true,                                                    \
                  "This assert is used to counter the "                    \
                  "false positive extra "                                  \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(float, hipsparseScsrsv2_analysis);
GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(double, hipsparseDcsrsv2_analysis);
GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(std::complex<float>,
                                     hipsparseCcsrsv2_analysis);
GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(std::complex<double>,
                                     hipsparseZcsrsv2_analysis);
GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(float, hipsparseScsrsv2_analysis);
GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(double, hipsparseDcsrsv2_analysis);
GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(std::complex<float>,
                                     hipsparseCcsrsv2_analysis);
GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(std::complex<double>,
                                     hipsparseZcsrsv2_analysis);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS(ValueType, detail::not_implemented);
#undef GKO_BIND_HIPSPARSE32_CSRSV2_ANALYSIS
#undef GKO_BIND_HIPSPARSE64_CSRSV2_ANALYSIS

#define GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(ValueType, HipsparseName)           \
    inline void csrsv2_solve(                                                 \
        hipsparseHandle_t handle, hipsparseOperation_t trans, size_type m,    \
        size_type nnz, const ValueType* one, const hipsparseMatDescr_t descr, \
        const ValueType* csrVal, const int32* csrRowPtr,                      \
        const int32* csrColInd, csrsv2Info_t factor_info,                     \
        const ValueType* rhs, ValueType* sol, hipsparseSolvePolicy_t policy,  \
        void* factor_work_vec)                                                \
    {                                                                         \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                       \
            HipsparseName(handle, trans, m, nnz, as_hiplibs_type(one), descr, \
                          as_hiplibs_type(csrVal), csrRowPtr, csrColInd,      \
                          factor_info, as_hiplibs_type(rhs),                  \
                          as_hiplibs_type(sol), policy, factor_work_vec));    \
    }                                                                         \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

#define GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(ValueType, HipsparseName)           \
    inline void csrsv2_solve(                                                 \
        hipsparseHandle_t handle, hipsparseOperation_t trans, size_type m,    \
        size_type nnz, const ValueType* one, const hipsparseMatDescr_t descr, \
        const ValueType* csrVal, const int64* csrRowPtr,                      \
        const int64* csrColInd, csrsv2Info_t factor_info,                     \
        const ValueType* rhs, ValueType* sol, hipsparseSolvePolicy_t policy,  \
        void* factor_work_vec) GKO_NOT_IMPLEMENTED;                           \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(float, hipsparseScsrsv2_solve);
GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(double, hipsparseDcsrsv2_solve);
GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(std::complex<float>, hipsparseCcsrsv2_solve);
GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(std::complex<double>, hipsparseZcsrsv2_solve);
GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(float, hipsparseScsrsv2_solve);
GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(double, hipsparseDcsrsv2_solve);
GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(std::complex<float>, hipsparseCcsrsv2_solve);
GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(std::complex<double>, hipsparseZcsrsv2_solve);
template <typename ValueType>
GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE(ValueType, detail::not_implemented);
template <typename ValueType>
GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE(ValueType, detail::not_implemented);
#undef GKO_BIND_HIPSPARSE32_CSRSV2_SOLVE
#undef GKO_BIND_HIPSPARSE64_CSRSV2_SOLVE


inline hipsparseContext* init(hipStream_t stream)
{
    hipsparseHandle_t handle{};
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseCreate(&handle));
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(
        hipsparseSetPointerMode(handle, HIPSPARSE_POINTER_MODE_DEVICE));
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseSetStream(handle, stream));
    return reinterpret_cast<hipsparseContext*>(handle);
}


inline void destroy_hipsparse_handle(hipsparseContext* handle)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(
        hipsparseDestroy(reinterpret_cast<hipsparseHandle_t>(handle)));
}


inline hipsparseMatDescr_t create_mat_descr()
{
    hipsparseMatDescr_t descr{};
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseCreateMatDescr(&descr));
    return descr;
}


inline void destroy(hipsparseMatDescr_t descr)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseDestroyMatDescr(descr));
}


inline csrgemm2Info_t create_spgemm_info()
{
    csrgemm2Info_t info{};
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseCreateCsrgemm2Info(&info));
    return info;
}


inline void destroy_spgemm_info(csrgemm2Info_t info)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseDestroyCsrgemm2Info(info));
}


inline csrilu02Info_t create_ilu0_info()
{
    csrilu02Info_t info{};
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseCreateCsrilu02Info(&info));
    return info;
}


inline void destroy_ilu0_info(csrilu02Info_t info)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseDestroyCsrilu02Info(info));
}


inline csric02Info_t create_ic0_info()
{
    csric02Info_t info{};
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseCreateCsric02Info(&info));
    return info;
}


inline void destroy_ic0_info(csric02Info_t info)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseDestroyCsric02Info(info));
}


template <typename IndexType>
void create_identity_permutation(hipsparseHandle_t handle, IndexType size,
                                 IndexType* permutation) GKO_NOT_IMPLEMENTED;

template <>
inline void create_identity_permutation<int32>(hipsparseHandle_t handle,
                                               int32 size, int32* permutation)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(
        hipsparseCreateIdentityPermutation(handle, size, permutation));
}


template <typename IndexType>
void csrsort_buffer_size(hipsparseHandle_t handle, IndexType m, IndexType n,
                         IndexType nnz, const IndexType* row_ptrs,
                         const IndexType* col_idxs,
                         size_type& buffer_size) GKO_NOT_IMPLEMENTED;

template <>
inline void csrsort_buffer_size<int32>(hipsparseHandle_t handle, int32 m,
                                       int32 n, int32 nnz,
                                       const int32* row_ptrs,
                                       const int32* col_idxs,
                                       size_type& buffer_size)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseXcsrsort_bufferSizeExt(
        handle, m, n, nnz, row_ptrs, col_idxs, &buffer_size));
}


template <typename IndexType>
void csrsort(hipsparseHandle_t handle, IndexType m, IndexType n, IndexType nnz,
             const hipsparseMatDescr_t descr, const IndexType* row_ptrs,
             IndexType* col_idxs, IndexType* permutation,
             void* buffer) GKO_NOT_IMPLEMENTED;

template <>
inline void csrsort<int32>(hipsparseHandle_t handle, int32 m, int32 n,
                           int32 nnz, const hipsparseMatDescr_t descr,
                           const int32* row_ptrs, int32* col_idxs,
                           int32* permutation, void* buffer)
{
    GKO_ASSERT_NO_HIPSPARSE_ERRORS(hipsparseXcsrsort(
        handle, m, n, nnz, descr, row_ptrs, col_idxs, permutation, buffer));
}


template <typename ValueType, typename IndexType>
void gather(hipsparseHandle_t handle, IndexType nnz, const ValueType* in,
            ValueType* out, const IndexType* permutation) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_GATHER(ValueType, HipsparseName)                   \
    template <>                                                               \
    inline void gather<ValueType, int32>(hipsparseHandle_t handle, int32 nnz, \
                                         const ValueType* in, ValueType* out, \
                                         const int32* permutation)            \
    {                                                                         \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(HipsparseName(                         \
            handle, nnz, as_hiplibs_type(in), as_hiplibs_type(out),           \
            permutation, HIPSPARSE_INDEX_BASE_ZERO));                         \
    }                                                                         \
    static_assert(true,                                                       \
                  "This assert is used to counter the false positive extra "  \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_GATHER(float, hipsparseSgthr);
GKO_BIND_HIPSPARSE_GATHER(double, hipsparseDgthr);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_GATHER(std::complex<float>, hipsparseCgthr);
GKO_BIND_HIPSPARSE_GATHER(std::complex<double>, hipsparseZgthr);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_GATHER


template <typename ValueType, typename IndexType>
void ilu0_buffer_size(hipsparseHandle_t handle, IndexType m, IndexType nnz,
                      const hipsparseMatDescr_t descr, const ValueType* vals,
                      const IndexType* row_ptrs, const IndexType* col_idxs,
                      csrilu02Info_t info,
                      size_type& buffer_size) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE(ValueType, HipsparseName)        \
    template <>                                                              \
    inline void ilu0_buffer_size<ValueType, int32>(                          \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, const ValueType* vals,              \
        const int32* row_ptrs, const int32* col_idxs, csrilu02Info_t info,   \
        size_type& buffer_size)                                              \
    {                                                                        \
        int tmp_buffer_size{};                                               \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr,                             \
                          as_hiplibs_type(const_cast<ValueType*>(vals)),     \
                          row_ptrs, col_idxs, info, &tmp_buffer_size));      \
        buffer_size = tmp_buffer_size;                                       \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE(float, hipsparseScsrilu02_bufferSize);
GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE(double, hipsparseDcsrilu02_bufferSize);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE(std::complex<float>,
                                    hipsparseCcsrilu02_bufferSize);
GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE(std::complex<double>,
                                    hipsparseZcsrilu02_bufferSize);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE


template <typename ValueType, typename IndexType>
void ilu0_analysis(hipsparseHandle_t handle, IndexType m, IndexType nnz,
                   const hipsparseMatDescr_t descr, const ValueType* vals,
                   const IndexType* row_ptrs, const IndexType* col_idxs,
                   csrilu02Info_t info, hipsparseSolvePolicy_t policy,
                   void* buffer) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_ILU0_ANALYSIS(ValueType, HipsparseName)           \
    template <>                                                              \
    inline void ilu0_analysis<ValueType, int32>(                             \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, const ValueType* vals,              \
        const int32* row_ptrs, const int32* col_idxs, csrilu02Info_t info,   \
        hipsparseSolvePolicy_t policy, void* buffer)                         \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr, as_hiplibs_type(vals),      \
                          row_ptrs, col_idxs, info, policy, buffer));        \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_ILU0_ANALYSIS(float, hipsparseScsrilu02_analysis);
GKO_BIND_HIPSPARSE_ILU0_ANALYSIS(double, hipsparseDcsrilu02_analysis);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_ILU0_ANALYSIS(std::complex<float>,
                                 hipsparseCcsrilu02_analysis);
GKO_BIND_HIPSPARSE_ILU0_ANALYSIS(std::complex<double>,
                                 hipsparseZcsrilu02_analysis);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_ILU0_ANALYSIS


template <typename ValueType, typename IndexType>
void ilu0(hipsparseHandle_t handle, IndexType m, IndexType nnz,
          const hipsparseMatDescr_t descr, ValueType* vals,
          const IndexType* row_ptrs, const IndexType* col_idxs,
          csrilu02Info_t info, hipsparseSolvePolicy_t policy,
          void* buffer) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_ILU0(ValueType, HipsparseName)                    \
    template <>                                                              \
    inline void ilu0<ValueType, int32>(                                      \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, ValueType* vals,                    \
        const int32* row_ptrs, const int32* col_idxs, csrilu02Info_t info,   \
        hipsparseSolvePolicy_t policy, void* buffer)                         \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr, as_hiplibs_type(vals),      \
                          row_ptrs, col_idxs, info, policy, buffer));        \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_ILU0(float, hipsparseScsrilu02);
GKO_BIND_HIPSPARSE_ILU0(double, hipsparseDcsrilu02);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_ILU0(std::complex<float>, hipsparseCcsrilu02);
GKO_BIND_HIPSPARSE_ILU0(std::complex<double>, hipsparseZcsrilu02);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_ILU0


template <typename ValueType, typename IndexType>
void ic0_buffer_size(hipsparseHandle_t handle, IndexType m, IndexType nnz,
                     const hipsparseMatDescr_t descr, const ValueType* vals,
                     const IndexType* row_ptrs, const IndexType* col_idxs,
                     csric02Info_t info,
                     size_type& buffer_size) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_IC0_BUFFER_SIZE(ValueType, HipsparseName)         \
    template <>                                                              \
    inline void ic0_buffer_size<ValueType, int32>(                           \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, const ValueType* vals,              \
        const int32* row_ptrs, const int32* col_idxs, csric02Info_t info,    \
        size_type& buffer_size)                                              \
    {                                                                        \
        int tmp_buffer_size{};                                               \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr,                             \
                          as_hiplibs_type(const_cast<ValueType*>(vals)),     \
                          row_ptrs, col_idxs, info, &tmp_buffer_size));      \
        buffer_size = tmp_buffer_size;                                       \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_IC0_BUFFER_SIZE(float, hipsparseScsric02_bufferSize);
GKO_BIND_HIPSPARSE_IC0_BUFFER_SIZE(double, hipsparseDcsric02_bufferSize);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_IC0_BUFFER_SIZE(std::complex<float>,
                                   hipsparseCcsric02_bufferSize);
GKO_BIND_HIPSPARSE_IC0_BUFFER_SIZE(std::complex<double>,
                                   hipsparseZcsric02_bufferSize);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_ILU0_BUFFER_SIZE


template <typename ValueType, typename IndexType>
void ic0_analysis(hipsparseHandle_t handle, IndexType m, IndexType nnz,
                  const hipsparseMatDescr_t descr, const ValueType* vals,
                  const IndexType* row_ptrs, const IndexType* col_idxs,
                  csric02Info_t info, hipsparseSolvePolicy_t policy,
                  void* buffer) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_IC0_ANALYSIS(ValueType, HipsparseName)            \
    template <>                                                              \
    inline void ic0_analysis<ValueType, int32>(                              \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, const ValueType* vals,              \
        const int32* row_ptrs, const int32* col_idxs, csric02Info_t info,    \
        hipsparseSolvePolicy_t policy, void* buffer)                         \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr, as_hiplibs_type(vals),      \
                          row_ptrs, col_idxs, info, policy, buffer));        \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_IC0_ANALYSIS(float, hipsparseScsric02_analysis);
GKO_BIND_HIPSPARSE_IC0_ANALYSIS(double, hipsparseDcsric02_analysis);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_IC0_ANALYSIS(std::complex<float>,
                                hipsparseCcsric02_analysis);
GKO_BIND_HIPSPARSE_IC0_ANALYSIS(std::complex<double>,
                                hipsparseZcsric02_analysis);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_IC0_ANALYSIS


template <typename ValueType, typename IndexType>
void ic0(hipsparseHandle_t handle, IndexType m, IndexType nnz,
         const hipsparseMatDescr_t descr, ValueType* vals,
         const IndexType* row_ptrs, const IndexType* col_idxs,
         csric02Info_t info, hipsparseSolvePolicy_t policy,
         void* buffer) GKO_NOT_IMPLEMENTED;

#define GKO_BIND_HIPSPARSE_IC0(ValueType, HipsparseName)                     \
    template <>                                                              \
    inline void ic0<ValueType, int32>(                                       \
        hipsparseHandle_t handle, int32 m, int32 nnz,                        \
        const hipsparseMatDescr_t descr, ValueType* vals,                    \
        const int32* row_ptrs, const int32* col_idxs, csric02Info_t info,    \
        hipsparseSolvePolicy_t policy, void* buffer)                         \
    {                                                                        \
        GKO_ASSERT_NO_HIPSPARSE_ERRORS(                                      \
            HipsparseName(handle, m, nnz, descr, as_hiplibs_type(vals),      \
                          row_ptrs, col_idxs, info, policy, buffer));        \
    }                                                                        \
    static_assert(true,                                                      \
                  "This assert is used to counter the false positive extra " \
                  "semi-colon warnings")

GKO_BIND_HIPSPARSE_IC0(float, hipsparseScsric02);
GKO_BIND_HIPSPARSE_IC0(double, hipsparseDcsric02);
#if defined(hipsparseVersionMajor) && defined(hipsparseVersionMinor) && \
    ((hipsparseVersionMajor > 1) ||                                     \
     (hipsparseVersionMajor == 1 && hipsparseVersionMinor >= 4))
GKO_BIND_HIPSPARSE_IC0(std::complex<float>, hipsparseCcsric02);
GKO_BIND_HIPSPARSE_IC0(std::complex<double>, hipsparseZcsric02);
#endif  // hipsparse version >= 1.4

#undef GKO_BIND_HIPSPARSE_IC0


}  // namespace hipsparse
}  // namespace hip
}  // namespace kernels
}  // namespace gko


#endif  // GKO_HIP_BASE_HIPSPARSE_BINDINGS_HIP_HPP_
