// Copyright (c) 2024 The YAC Authors
//
// SPDX-License-Identifier: BSD-3-Clause

#ifndef YAC_LAPACK_INTERFACE_H
#define YAC_LAPACK_INTERFACE_H

#ifdef HAVE_CONFIG_H
// #include "config.h"
#endif

#define YAC_LAPACK_INTERFACE_ID 5
#define YAC_FC_GLOBAL(name, NAME) name##_

#ifndef YAC_LAPACK_INTERFACE_ID
#error None of the supported LAPACK interfaces is available
#endif

#if YAC_LAPACK_INTERFACE_ID == 1 // Intel MKL LAPACKE

#include <mkl_lapacke.h>

#elif YAC_LAPACK_INTERFACE_ID == 2 // Netlib LAPACKE

#include <lapacke.h>

#elif YAC_LAPACK_INTERFACE_ID == 3 // ATLAS CLAPACK

#include <clapack.h>

#ifndef ATL_INT
#define ATL_INT int
#endif

#ifndef lapack_int
#define lapack_int ATL_INT
#endif

#define LAPACK_COL_MAJOR CblasColMajor

#if 0
lapack_int LAPACKE_dgels_work( int matrix_layout, char trans, lapack_int m,
                               lapack_int n, lapack_int nrhs, double* a,
                               lapack_int lda, double* b, lapack_int ldb,
                               double* work, lapack_int lwork );
#endif

lapack_int LAPACKE_dgesv( int matrix_layout, lapack_int n, lapack_int nrhs,
                          double* a, lapack_int lda, lapack_int* ipiv,
                          double* b, lapack_int ldb );

lapack_int LAPACKE_dgetrf( int matrix_layout, lapack_int m, lapack_int n,
                           double* a, lapack_int lda, lapack_int* ipiv );

lapack_int LAPACKE_dgetri_work( int matrix_layout, lapack_int n, double* a,
                                lapack_int lda, const lapack_int* ipiv,
                                double* work, lapack_int lwork );

#define YAC_LAPACK_NO_DSYTR
#define YAC_LAPACK_C_INDEXING

#elif YAC_LAPACK_INTERFACE_ID == 4 // Netlib CLAPACK

#include <f2c.h>

#ifndef lapack_int
#define lapack_int integer
#endif

#define LAPACK_COL_MAJOR 102

#if 0
lapack_int LAPACKE_dgels_work( int matrix_layout, char trans, lapack_int m,
                               lapack_int n, lapack_int nrhs, double* a,
                               lapack_int lda, double* b, lapack_int ldb,
                               double* work, lapack_int lwork );
#endif

lapack_int LAPACKE_dgesv( int matrix_layout, lapack_int n, lapack_int nrhs,
                          double* a, lapack_int lda, lapack_int* ipiv,
                          double* b, lapack_int ldb );

lapack_int LAPACKE_dgetrf( int matrix_layout, lapack_int m, lapack_int n,
                           double* a, lapack_int lda, lapack_int* ipiv );

lapack_int LAPACKE_dgetri_work( int matrix_layout, lapack_int n, double* a,
                                lapack_int lda, const lapack_int* ipiv,
                                double* work, lapack_int lwork );

lapack_int LAPACKE_dsytrf_work( int matrix_layout, char uplo, lapack_int n,
                                double* a, lapack_int lda, lapack_int* ipiv,
                                double* work, lapack_int lwork );

lapack_int LAPACKE_dsytri_work( int matrix_layout, char uplo, lapack_int n,
                                double* a, lapack_int lda,
                                const lapack_int* ipiv, double* work );

#elif YAC_LAPACK_INTERFACE_ID == 5 // Fortran LAPACK

#ifndef lapack_int
#define lapack_int int
#endif

#define LAPACK_COL_MAJOR 102

#if 0
lapack_int LAPACKE_dgels_work( int matrix_layout, char trans, lapack_int m,
                               lapack_int n, lapack_int nrhs, double* a,
                               lapack_int lda, double* b, lapack_int ldb,
                               double* work, lapack_int lwork );
#endif

lapack_int LAPACKE_dgesv( int matrix_layout, lapack_int n, lapack_int nrhs,
                          double* a, lapack_int lda, lapack_int* ipiv,
                          double* b, lapack_int ldb );

lapack_int LAPACKE_dgetrf( int matrix_layout, lapack_int m, lapack_int n,
                           double* a, lapack_int lda, lapack_int* ipiv );

lapack_int LAPACKE_dgetri_work( int matrix_layout, lapack_int n, double* a,
                                lapack_int lda, const lapack_int* ipiv,
                                double* work, lapack_int lwork );

lapack_int LAPACKE_dsytrf_work( int matrix_layout, char uplo, lapack_int n,
                                double* a, lapack_int lda, lapack_int* ipiv,
                                double* work, lapack_int lwork );

lapack_int LAPACKE_dsytri_work( int matrix_layout, char uplo, lapack_int n,
                                double* a, lapack_int lda,
                                const lapack_int* ipiv, double* work );

#else

#error Unexpected value for YAC_LAPACK_INTERFACE_ID

#endif

#endif // YAC_LAPACK_INTERFACE_H

