/*
 * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: LicenseRef-NvidiaProprietary
 *
 * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
 * property and proprietary rights in and to this material, related
 * documentation and any modifications thereto. Any use, reproduction,
 * disclosure or distribution of this material and related documentation
 * without an express license agreement from NVIDIA CORPORATION or
 * its affiliates is strictly prohibited.
 */

#pragma once

namespace __nvhpc_std {

namespace __cb = __cublas_std;

/*
 * Going from row-major to column-major
 * - Matrices are effectively transposed
 * - Upper-triangular matrices become lower-triangular matrices, and vice versa
 * Left-side op:
 * In C with row-major layout        : A   * X   = B
 * In cuBLAS with column-major layout: X^t * A^t = B^t
 * which is what cuBLAS Trsm computes with input A^t, B^t, and SIDE = right
 * Right-side op:
 * In C with row-major layout        : X   * A   = B
 * In cuBLAS with column-major layout: A^t * X^t = B^t
 * which is what cuBLAS Trsm computes with input A^t, B^t, and SIDE = left
 */

template<class _SyncType,
         class _ElementType_A,
         class _SizeType_A,
         ::std::size_t _numRows_A,
         ::std::size_t _numCols_A,
         class _Layout_A,
         class _Accessor_A,
         class _ElementType_B,
         class _SizeType_B,
         ::std::size_t _numRows_B,
         ::std::size_t _numCols_B,
         class _Layout_B,
         class _Accessor_B>
void __triangular_matrix_matrix_solve_impl( __nvhpc_exec<__cublas_exec_space<_SyncType>> __exec
                                          , _ElementType_B __alpha
                                          , std::mdspan<_ElementType_A, std::extents<_SizeType_A, _numRows_A, _numCols_A>, _Layout_A, _Accessor_A> __A
                                          , char __trans
                                          , char __uplo
                                          , char __side
                                          , char __diag
                                          , bool __is_transposed
                                          , std::mdspan<_ElementType_B, std::extents<_SizeType_B, _numRows_B, _numCols_B>, _Layout_B, _Accessor_B> __B
                                          )
{
#ifdef STDBLAS_VERBOSE
    __STDBLAS_BACKEND_MESSAGE( triangular_matrix_matrix_solve, cuBLAS );
#endif

    __cb::__check_cublas_status( __cb::__cublas_trsm( __cb::__get_cublas_handle()
                                                    , __cb::__to_cublas_side_mode( __side )
                                                    , __cb::__to_cublas_fill_mode( __uplo )
                                                    , __cb::__op_to_cublas_op( __trans )
                                                    , __cb::__to_cublas_diag_type( __diag )
                                                    , std::linalg::__get_row_count( __B, __is_transposed )
                                                    , std::linalg::__get_col_count( __B, __is_transposed )
                                                    , &__alpha
                                                    , __A.data_handle()
                                                    , std::linalg::__get_leading_dim( __A )
                                                    , __B.data_handle()
                                                    , std::linalg::__get_leading_dim( __B )
                                                    )
                               , "triangular_matrix_matrix_solve"
                               , "cublas_trsm"
                               );

    __cb::__synchronize( __exec );
}

}
