//------------------------------------------------------------------------------
// SuiteSparse_config/SuiteSparse_config.h: common utilites for SuiteSparse
//------------------------------------------------------------------------------

// SuiteSparse_config, Copyright (c) 2012-2022, Timothy A. Davis.
// All Rights Reserved.
// SPDX-License-Identifier: BSD-3-clause

//------------------------------------------------------------------------------

// Configuration file for SuiteSparse: a Suite of Sparse matrix packages: AMD,
// COLAMD, CCOLAMD, CAMD, CHOLMOD, UMFPACK, CXSparse, SuiteSparseQR, ParU, ...

// The SuiteSparse_config.h file is configured by CMake to be specific to the
// C/C++ compiler and BLAS library being used for SuiteSparse.  The original
// file is SuiteSparse_config/SuiteSparse_config.h.in.  Do not edit the
// SuiteSparse_config.h file directly.

#ifndef SUITESPARSE_CONFIG_H
#define SUITESPARSE_CONFIG_H

#ifdef __cplusplus
extern "C"
{
#endif

//------------------------------------------------------------------------------
// SuiteSparse-wide ANSI C11 #include files
//------------------------------------------------------------------------------

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>

//------------------------------------------------------------------------------
// SuiteSparse_long is now int64_t in SuiteSparse v6.0.0 and later
//------------------------------------------------------------------------------

// The use of SuiteSparse_long is deprecated.  User applications should use
// int64_t instead.

#undef  SuiteSparse_long
#undef  SuiteSparse_long_max
#undef  SuiteSparse_long_idd
#undef  SuiteSparse_long_id

#define SuiteSparse_long int64_t
#define SuiteSparse_long_max INT64_MAX
#define SuiteSparse_long_idd PRId64
#define SuiteSparse_long_id "%" SuiteSparse_long_idd

//------------------------------------------------------------------------------
// OpenMP
//------------------------------------------------------------------------------

#if defined ( _OPENMP )

    #include <omp.h>
    #define SUITESPARSE_OPENMP_MAX_THREADS       omp_get_max_threads ( )
    #define SUITESPARSE_OPENMP_GET_NUM_THREADS   omp_get_num_threads ( )
    #define SUITESPARSE_OPENMP_GET_WTIME         omp_get_wtime ( )
    #define SUITESPARSE_OPENMP_GET_THREAD_ID     omp_get_thread_num ( )

#else

    // OpenMP not available
    #define SUITESPARSE_OPENMP_MAX_THREADS       (1)
    #define SUITESPARSE_OPENMP_GET_NUM_THREADS   (1)
    #define SUITESPARSE_OPENMP_GET_WTIME         (0)
    #define SUITESPARSE_OPENMP_GET_THREAD_ID     (0)

#endif

//------------------------------------------------------------------------------
// MATLAB/Octave
//------------------------------------------------------------------------------

#if defined ( MATLAB_MEX_FILE )
#include "mex.h"
#include "matrix.h"
#endif

//------------------------------------------------------------------------------
// string and token handling macros
//------------------------------------------------------------------------------

// SUITESPARSE_STR: convert the content of x into a string "x"
#define SUITESPARSE_XSTR(x) SUITESPARSE_STR(x)
#define SUITESPARSE_STR(x) #x

// SUITESPARSE_CAT(x,y): concatenate two tokens
#define SUITESPARSE_CAT2(x,y) x ## y
#define SUITESPARSE_CAT(x,y) SUITESPARSE_CAT2(x,y)

//------------------------------------------------------------------------------
// determine which compiler is in use
//------------------------------------------------------------------------------

#if defined ( __NVCC__ )

    // NVIDIA nvcc compiler
    #define SUITESPARSE_COMPILER_NVCC    1
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR __CUDACC_VER_MAJOR__
    #define SUITESPARSE_COMPILER_MINOR __CUDACC_VER_MINOR__
    #define SUITESPARSE_COMPILER_SUB   __CUDACC_VER_BUILD__
    #define SUITESPARSE_COMPILER_NAME  "nvcc"

#elif defined ( __INTEL_CLANG_COMPILER )

    // Intel icx compiler, 2022.0.0 based on clang/llvm 14.0.0
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     1
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR __INTEL_CLANG_COMPILER
    #define SUITESPARSE_COMPILER_MINOR 0
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  __VERSION__

#elif defined ( __INTEL_COMPILER )

    // Intel icc compiler: 2021.5.0 uses "gcc 7.5 mode"
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     1
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR __INTEL_COMPILER
    #define SUITESPARSE_COMPILER_MINOR __INTEL_COMPILER_UPDATE
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  __VERSION__

#elif defined ( __clang__ )

    // clang
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   1
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR __clang_major__
    #define SUITESPARSE_COMPILER_MINOR __clang_minor__
    #define SUITESPARSE_COMPILER_SUB   __clang_patchlevel__
    #define SUITESPARSE_COMPILER_NAME  "clang " __clang_version__

#elif defined ( __xlC__ )

    // xlc
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     1
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR ( __xlC__ / 256 )
    #define SUITESPARSE_COMPILER_MINOR \
        ( __xlC__ - 256 * SUITESPARSE_COMPILER_MAJOR)
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  "IBM xlc " SUITESPARSE_XSTR (__xlC__)

#elif defined ( __GNUC__ )

    // gcc
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     1
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR __GNUC__
    #define SUITESPARSE_COMPILER_MINOR __GNUC_MINOR__
    #define SUITESPARSE_COMPILER_SUB   __GNUC_PATCHLEVEL__
    #define SUITESPARSE_COMPILER_NAME  "GNU gcc "   \
        SUITESPARSE_XSTR (__GNUC__) "."             \
        SUITESPARSE_XSTR (__GNUC_MINOR__) "."       \
        SUITESPARSE_XSTR (__GNUC_PATCHLEVEL__)

#elif defined ( _MSC_VER )

    // Microsoft Visual Studio
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     1
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR ( _MSC_VER / 100 )
    #define SUITESPARSE_COMPILER_MINOR \
        ( _MSC_VER - 100 * SUITESPARSE_COMPILER_MAJOR)
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  \
        "Microsoft Visual Studio " SUITESPARSE_XSTR (_MSC_VER)

#elif defined ( __MINGW32__ ) || defined ( __MINGW64__ )

    // MinGW (32-bit or 64-bit)
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   1

    #if defined ( __MINGW32__ )
    #define SUITESPARSE_COMPILER_MAJOR ( __MINGW32_MAJOR_VERSION )
    #define SUITESPARSE_COMPILER_MINOR ( __MINGW32_MINOR_VERSION )
    #else
    #define SUITESPARSE_COMPILER_MAJOR ( __MINGW64_MAJOR_VERSION )
    #define SUITESPARSE_COMPILER_MINOR ( __MINGW64_MINOR_VERSION )
    #endif
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  "MinGW"

#else

    // other compiler
    #define SUITESPARSE_COMPILER_NVCC    0
    #define SUITESPARSE_COMPILER_ICX     0
    #define SUITESPARSE_COMPILER_ICC     0
    #define SUITESPARSE_COMPILER_CLANG   0
    #define SUITESPARSE_COMPILER_GCC     0
    #define SUITESPARSE_COMPILER_MSC     0
    #define SUITESPARSE_COMPILER_XLC     0
    #define SUITESPARSE_COMPILER_MINGW   0

    #define SUITESPARSE_COMPILER_MAJOR 0
    #define SUITESPARSE_COMPILER_MINOR 0
    #define SUITESPARSE_COMPILER_SUB   0
    #define SUITESPARSE_COMPILER_NAME  "other C compiler"

#endif

//------------------------------------------------------------------------------
// malloc.h: required include file for Microsoft Visual Studio
//------------------------------------------------------------------------------

#if SUITESPARSE_COMPILER_MSC
    #include <malloc.h>
#endif

//------------------------------------------------------------------------------
// importing/exporting symbols for Microsoft Visual Studio
//------------------------------------------------------------------------------

#if SUITESPARSE_COMPILER_MSC && 0

    // import/export for MS Visual Studio
    #ifdef SUITESPARSE_LIBRARY
        // compiling SuiteSparse itself, exporting symbols to user apps
        #define SUITESPARSE_PUBLIC extern __declspec ( dllexport )
    #else
        // compiling the user application, importing symbols from SuiteSparse
        #define SUITESPARSE_PUBLIC extern __declspec ( dllimport )
    #endif

#else

    // for other compilers
    #define SUITESPARSE_PUBLIC extern

#endif

//------------------------------------------------------------------------------
// determine the ANSI C version
//------------------------------------------------------------------------------

#ifdef __STDC_VERSION__
// ANSI C17: 201710L
// ANSI C11: 201112L
// ANSI C99: 199901L
// ANSI C95: 199409L
#define SUITESPARSE_STDC_VERSION __STDC_VERSION__
#else
// assume ANSI C90 / C89
#define SUITESPARSE_STDC_VERSION 199001L
#endif

//------------------------------------------------------------------------------
// handle the restrict keyword
//------------------------------------------------------------------------------

#if defined ( __cplusplus )

    // C++ does not have the "restrict" keyword
    #define SUITESPARSE_RESTRICT

#elif SUITESPARSE_COMPILER_MSC

    // MS Visual Studio
    #define SUITESPARSE_RESTRICT __restrict

#elif SUITESPARSE_COMPILER_NCSS

    // NVIDIA nvcc
    #define SUITESPARSE_RESTRICT __restrict__

#elif SUITESPARSE_STDC_VERSION >= 199901L

    // ANSI C99 or later
    #define SUITESPARSE_RESTRICT restrict

#else

    // ANSI C95 and earlier: no restrict keyword
    #define SUITESPARSE_RESTRICT

#endif

//==============================================================================
// SuiteSparse_config parameters and functions
//==============================================================================

// SuiteSparse-wide parameters are placed in this struct.  It is meant to be an
// extern, globally-accessible struct.  It is not meant to be updated
// frequently by multiple threads.  Rather, if an application needs to modify
// SuiteSparse_config, it should do it once at the beginning of the
// application, before multiple threads are launched.

// The intent of these function pointers is that they not be used in your
// application directly, except to assign them to the desired user-provided
// functions.  Rather, you should use the SuiteSparse_malloc/calloc, etc
// wrappers defined below to access them.

struct SuiteSparse_config_struct
{
    void *(*malloc_func) (size_t) ;             // pointer to malloc
    void *(*calloc_func) (size_t, size_t) ;     // pointer to calloc
    void *(*realloc_func) (void *, size_t) ;    // pointer to realloc
    void (*free_func) (void *) ;                // pointer to free
    int (*printf_func) (const char *, ...) ;    // pointer to printf
    double (*hypot_func) (double, double) ;     // pointer to hypot
    int (*divcomplex_func) (double, double, double, double, double *, double *);
} ;

SUITESPARSE_PUBLIC struct SuiteSparse_config_struct SuiteSparse_config ;

SUITESPARSE_PUBLIC
void SuiteSparse_start ( void ) ;   // called to start SuiteSparse

SUITESPARSE_PUBLIC
void SuiteSparse_finish ( void ) ;  // called to finish SuiteSparse

SUITESPARSE_PUBLIC
void *SuiteSparse_malloc    // pointer to allocated block of memory
(
    size_t nitems,          // number of items to malloc (>=1 is enforced)
    size_t size_of_item     // sizeof each item
) ;

SUITESPARSE_PUBLIC
void *SuiteSparse_calloc    // pointer to allocated block of memory
(
    size_t nitems,          // number of items to calloc (>=1 is enforced)
    size_t size_of_item     // sizeof each item
) ;

SUITESPARSE_PUBLIC
void *SuiteSparse_realloc   // pointer to reallocated block of memory, or
                            ///to original block if the realloc failed.
(
    size_t nitems_new,      // new number of items in the object
    size_t nitems_old,      // old number of items in the object
    size_t size_of_item,    // sizeof each item
    void *p,                // old object to reallocate
    int *ok                 // 1 if successful, 0 otherwise
) ;

SUITESPARSE_PUBLIC
void *SuiteSparse_free      // always returns NULL
(
    void *p                 // block to free
) ;

SUITESPARSE_PUBLIC
void SuiteSparse_tic    // start the timer
(
    double tic [2]      // output, contents undefined on input
) ;

SUITESPARSE_PUBLIC
double SuiteSparse_toc  // return time in seconds since last tic
(
    double tic [2]      // input: from last call to SuiteSparse_tic
) ;

SUITESPARSE_PUBLIC
double SuiteSparse_time  // returns current wall clock time in seconds
(
    void
) ;

// returns sqrt (x^2 + y^2), computed reliably
SUITESPARSE_PUBLIC
double SuiteSparse_hypot (double x, double y) ;

// complex division of c = a/b
SUITESPARSE_PUBLIC
int SuiteSparse_divcomplex
(
    double ar, double ai,       // real and imaginary parts of a
    double br, double bi,       // real and imaginary parts of b
    double *cr, double *ci      // real and imaginary parts of c
) ;

// determine which timer to use, if any
#ifndef NTIMER
    #if defined ( _OPENMP )
        #define SUITESPARSE_TIMER_ENABLED
    #elif defined ( _POSIX_C_SOURCE )
        #if _POSIX_C_SOURCE >= 199309L
        #define SUITESPARSE_TIMER_ENABLED
        #endif
    #endif
#endif

// SuiteSparse printf macro
#define SUITESPARSE_PRINTF(params)                          \
{                                                           \
    if (SuiteSparse_config.printf_func != NULL)             \
    {                                                       \
        (void) (SuiteSparse_config.printf_func) params ;    \
    }                                                       \
}

//==============================================================================
// SuiteSparse version
//==============================================================================

// SuiteSparse is not a package itself, but a collection of packages, some of
// which must be used together (UMFPACK requires AMD, CHOLMOD requires AMD,
// COLAMD, CAMD, and CCOLAMD, etc).  A version number is provided here for the
// collection itself, which is also the version number of SuiteSparse_config.

SUITESPARSE_PUBLIC
int SuiteSparse_version     // returns SUITESPARSE_VERSION
(
    // output, not defined on input.  Not used if NULL.  Returns
    // the three version codes in version [0..2]:
    // version [0] is SUITESPARSE_MAIN_VERSION
    // version [1] is SUITESPARSE_SUB_VERSION
    // version [2] is SUITESPARSE_SUBSUB_VERSION
    int version [3]
) ;

#define SUITESPARSE_HAS_VERSION_FUNCTION

#define SUITESPARSE_DATE "Nov 12, 2022"
#define SUITESPARSE_MAIN_VERSION    6
#define SUITESPARSE_SUB_VERSION     0
#define SUITESPARSE_SUBSUB_VERSION  1

#define SUITESPARSE_VER_CODE(main,sub) ((main) * 1000 + (sub))
#define SUITESPARSE_VERSION \
    SUITESPARSE_VER_CODE(SUITESPARSE_MAIN_VERSION,SUITESPARSE_SUB_VERSION)

//==============================================================================
// SuiteSparse interface to the BLAS and LAPACK libraries
//==============================================================================

// Several SuiteSparse packages rely on the BLAS/LAPACK libraries (UMFPACK
// CHOLMOD, and SPQR, and likely GraphBLAS in the future).  All of these
// packages are written in C/C++, but rely on the Fortran interface to
// BLAS/LAPACK.  SuiteSparse does not use the cblas / lapacke interfaces to
// these libraries, mainly because FindBLAS.cmake does not locate them (or at
// least does not locate their respective cblas.h and lapacke.h files).  In
// addition, the original definition of these files do not include a different
// name space for 64-bit integer versions.  Finally, Intel renames cblas.h as
// mkl_cblas.h.  As a result of these many portability issues, different
// implementations of those libraries extend them in different ways.  Thus,
// SuiteSparse simply calls the Fortran functions directly.

// However, the method for how C/C++ calling Fortran depends on the compilers
// involved.  This connection is handled by the FortranCInterface.cmake module
// of CMake.

// On typical systems (Linux with the GCC compiler for example, or on the Mac
// with clang) the Fortan name "dgemm" is called by C as "dgemm_",  Other
// systems do not append the underscore.

//------------------------------------------------------------------------------
// SUITESPARSE_FORTRAN: macros created by CMake describing how C calls Fortran
//------------------------------------------------------------------------------

// SUITESPARSE_FORTAN: for Fortran routines with no "_" in their names
// SUITESPARSE__FORTAN: for Fortran routines with "_" in their names

// The decision on which of these macros to use is based on the presence of
// underscores in the original Fortran names, not the (commonly) appended
// underscore needed for C to all the corresponding Fortran routine.

// These two macros are created by the CMake module, FortranCInterface.cmake,
// which is then used by CMake to configure this file.

// The CMAKE decision can be superceded by setting -DBLAS_NO_UNDERSCORE, so
// that "dgemm" remains "dgemm" (for MS Visual Studio for example).  Setting
// -DBLAS_UNDERSCORE changes "dgemm" to "dgemm_", the common case for Mac and
// Linux.

#if defined ( BLAS_NO_UNDERSCORE )

    // no name mangling, use lower case
    #define SUITESPARSE_FORTRAN(name,NAME)  name
    #define SUITESPARSE__FORTRAN(name,NAME) name

#elif defined ( BLAS_UNDERSCORE )

    // append an undescore, use lower case 
    #define SUITESPARSE_FORTRAN(name,NAME)  name ## _
    #define SUITESPARSE__FORTRAN(name,NAME) name ## _

#else

    // let CMake decide how C calls Fortran
    #define SUITESPARSE_FORTRAN(name,NAME) name##_
    #define SUITESPARSE__FORTRAN(name,NAME) name##_

#endif

//------------------------------------------------------------------------------
// SUITESPARSE_BLAS_INT: the BLAS/LAPACK integer (int32_t or int64_t)
//------------------------------------------------------------------------------

// CMake 3.22 and later allow the selection of the BLAS/LAPACK integer size.
// This information is then used to configure this file with the definition of
// this integer: int32_t or int64_t.

// When compiling SuiteSparse for a MATLAB mexFunction, the MATLAB libmwblas is
// used, which is a 64-bit integer version of the BLAS.  CMake is not used to
// configure SuiteSparse in this case.  The flag -DBLAS64 can be used to ensure
// a 64-bit BLAS is used.  Likewise, -DBLAS32 ensures a 32-bit BLAS is used.

#if defined ( BLAS64 )

    // override the BLAS found by CMake, and force a 64-bit interface
    #define SUITESPARSE_BLAS_INT int64_t

#elif defined ( BLAS32 )

    // override the BLAS found by CMake, and force a 32-bit interface
    #define SUITESPARSE_BLAS_INT int32_t

#else

    // let CMake determine the size of the integer in the Fortran BLAS
    #define SUITESPARSE_BLAS_INT int32_t

#endif

// SUITESPARSE_TO_BLAS_INT: convert an integer k to a BLAS integer K and set ok
// to false if the conversion changes its value.  This is implemented as a
// macro so that can work with any type of the integer k.
#define SUITESPARSE_TO_BLAS_INT(K,k,ok)         \
    SUITESPARSE_BLAS_INT K = (k) ;              \
    ok = ok && ((sizeof (K) >= sizeof (k)) || ((int64_t)(K) == (int64_t)(k))) ;

//------------------------------------------------------------------------------
// SUITESPARSE_BLAS_SUFFIX: modify the name of a Fortran BLAS/LAPACK routine
//------------------------------------------------------------------------------

// OpenBLAS can be compiled by appending a suffix to each routine, so that the
// Fortan routine dgemm becomes dgemm_64, which denotes a version of dgemm with
// 64-bit integer parameters.  The Sun Performance library does the same thing,
// but without the internal underscore, as dgemm64.

// If the suffix does not contain "_", use (Sun Perf., for example):

//     cd build ; cmake -DBLAS64_SUFFIX="64" ..

// If the suffix contains "_" (OpenBLAS in spack for example), use the
// following:

//     cd build ; cmake -DBLAS64_SUFFIX="_64" ..

// This setting could be used by the spack packaging of SuiteSparse when linked
// with the spack-installed OpenBLAS with 64-bit integers.  See
// https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/suite-sparse/package.py

#if defined ( BLAS64__SUFFIX )

    // The suffix includes an undersore (such as "_64"), so the Fortran name
    // must be processed with the SUITESPARSE__FORTRAN macro.
    #define SUITESPARSE_G(name,NAME) SUITESPARSE__FORTRAN(name,NAME)
    #define SUITESPARSE_F(name,NAME)                            \
        SUITESPARSE_G (SUITESPARSE_CAT (name, BLAS64__SUFFIX),  \
                       SUITESPARSE_CAT (NAME, BLAS64__SUFFIX))
    #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_F(name,NAME)

#elif defined ( BLAS64_SUFFIX )

    // The suffix does not include an undersore, and neither do the original
    // names of the BLAS and LAPACK routines.  Thus, the Fortran name must be
    // processed with the SUITESPARSE_FORTRAN macro.
    #define SUITESPARSE_G(name,NAME) SUITESPARSE_FORTRAN(name,NAME)
    #define SUITESPARSE_F(name,NAME)                            \
        SUITESPARSE_G (SUITESPARSE_CAT (name, BLAS64_SUFFIX),  \
                       SUITESPARSE_CAT (NAME, BLAS64_SUFFIX))
    #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_F(name,NAME)

#else

    // No suffix is need, so the final Fortran name includes no suffix.
    #define SUITESPARSE_BLAS(name,NAME) SUITESPARSE_FORTRAN(name,NAME)

#endif

//------------------------------------------------------------------------------
// C names of Fortan BLAS and LAPACK functions used by SuiteSparse
//------------------------------------------------------------------------------

#define SUITESPARSE_BLAS_DTRSV      SUITESPARSE_BLAS ( dtrsv  , DTRSV  )
#define SUITESPARSE_BLAS_DGEMV      SUITESPARSE_BLAS ( dgemv  , DGEMV  )
#define SUITESPARSE_BLAS_DTRSM      SUITESPARSE_BLAS ( dtrsm  , DTRSM  )
#define SUITESPARSE_BLAS_DGEMM      SUITESPARSE_BLAS ( dgemm  , DGEMM  )
#define SUITESPARSE_BLAS_DSYRK      SUITESPARSE_BLAS ( dsyrk  , DSYRK  )
#define SUITESPARSE_BLAS_DGER       SUITESPARSE_BLAS ( dger   , DGER   )
#define SUITESPARSE_BLAS_DSCAL      SUITESPARSE_BLAS ( dscal  , DSCAL  )
#define SUITESPARSE_LAPACK_DPOTRF   SUITESPARSE_BLAS ( dpotrf , DPOTRF )

#define SUITESPARSE_BLAS_ZTRSV      SUITESPARSE_BLAS ( ztrsv  , ZTRSV  )
#define SUITESPARSE_BLAS_ZGEMV      SUITESPARSE_BLAS ( zgemv  , ZGEMV  )
#define SUITESPARSE_BLAS_ZTRSM      SUITESPARSE_BLAS ( ztrsm  , ZTRSM  )
#define SUITESPARSE_BLAS_ZGEMM      SUITESPARSE_BLAS ( zgemm  , ZGEMM  )
#define SUITESPARSE_BLAS_ZHERK      SUITESPARSE_BLAS ( zherk  , ZHERK  )
#define SUITESPARSE_BLAS_ZGERU      SUITESPARSE_BLAS ( zgeru  , ZGERU  )
#define SUITESPARSE_BLAS_ZSCAL      SUITESPARSE_BLAS ( zscal  , ZSCAL  )
#define SUITESPARSE_LAPACK_ZPOTRF   SUITESPARSE_BLAS ( zpotrf , ZPOTRF )

#define SUITESPARSE_BLAS_DNRM2      SUITESPARSE_BLAS ( dnrm2  , DNRM2  )
#define SUITESPARSE_LAPACK_DLARF    SUITESPARSE_BLAS ( dlarf  , DLARF  )
#define SUITESPARSE_LAPACK_DLARFG   SUITESPARSE_BLAS ( dlarfg , DLARFG )
#define SUITESPARSE_LAPACK_DLARFT   SUITESPARSE_BLAS ( dlarft , DLARFT )
#define SUITESPARSE_LAPACK_DLARFB   SUITESPARSE_BLAS ( dlarfb , DLARFB )

#define SUITESPARSE_BLAS_DZNRM2     SUITESPARSE_BLAS ( dznrm2 , DZNRM2 )
#define SUITESPARSE_LAPACK_ZLARF    SUITESPARSE_BLAS ( zlarf  , ZLAR   )
#define SUITESPARSE_LAPACK_ZLARFG   SUITESPARSE_BLAS ( zlarfg , ZLARFG )
#define SUITESPARSE_LAPACK_ZLARFT   SUITESPARSE_BLAS ( zlarft , ZLARFT )
#define SUITESPARSE_LAPACK_ZLARFB   SUITESPARSE_BLAS ( zlarfb , ZLARFB )

//------------------------------------------------------------------------------
// prototypes of BLAS and SUITESPARSE_LAPACK functions
//------------------------------------------------------------------------------

// For complex functions, the (void *) parameters are actually pointers to
// arrays of complex values.  They are prototyped here as (void *) to allow
// them to be called from both C and C++.

// See https://netlib.org/blas/ and https://netlib.org/lapack/ for the
// definitions of the inputs/outputs of these functions.

// These prototypes need to be found by UMFPACK, CHOLMOD, and SPQR, and to do
// so, they need to appear in this public header to ensure the correct BLAS
// library and integer size is used.  However, these definitions should not
// (normally) be exposed to the user application.

// If a user application wishes to use these definitions, simply add

//      #define SUITESPARSE_BLAS_DEFINITIONS
//      #include "SuiteSparse_config.h"

// prior to #include'ing any SuiteSparse headers (amd.h, and so on).

#if defined ( SUITESPARSE_BLAS_DEFINITIONS )

void SUITESPARSE_BLAS_DGEMV         // Y = alpha*A*x + beta*Y
(
    // input:
    const char *trans,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const double *alpha,
    const double *A,
    const SUITESPARSE_BLAS_INT *lda,
    const double *X,
    const SUITESPARSE_BLAS_INT *incx,
    const double *beta,
    // input/output:
    double *Y,
    // input:
    const SUITESPARSE_BLAS_INT *incy
) ;

#define SUITESPARSE_BLAS_dgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok)   \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DGEMV (trans, &M_blas_int, &N_blas_int, alpha, A,    \
            &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ;      \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZGEMV         // Y = alpha*A*X + beta*Y
(
    // input:
    const char *trans,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const void *alpha,
    const void *A,
    const SUITESPARSE_BLAS_INT *lda,
    const void *X,
    const SUITESPARSE_BLAS_INT *incx,
    const void *beta,
    // input/output:
    void *Y,
    // input:
    const SUITESPARSE_BLAS_INT *incy
) ;

#define SUITESPARSE_BLAS_zgemv(trans,m,n,alpha,A,lda,X,incx,beta,Y,incy,ok)   \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZGEMV (trans, &M_blas_int, &N_blas_int, alpha, A,    \
            &LDA_blas_int, X, &INCX_blas_int, beta, Y, &INCY_blas_int) ;      \
    }                                                                         \
}

void SUITESPARSE_BLAS_DTRSV         // solve Lx=b, Ux=b, L'x=b, or U'x=b
(
    // input:
    const char *uplo,
    const char *trans,
    const char *diag,
    const SUITESPARSE_BLAS_INT *n,
    const double *A,
    const SUITESPARSE_BLAS_INT *lda,
    // input/output:
    double *X,
    // input:
    const SUITESPARSE_BLAS_INT *incx
) ;

#define SUITESPARSE_BLAS_dtrsv(uplo,trans,diag,n,A,lda,X,incx,ok)             \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DTRSV (uplo, trans, diag, &N_blas_int, A,            \
            &LDA_blas_int, X, &INCX_blas_int) ;                               \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZTRSV         // solve (L, L', L^H, U, U', or U^H)x=b
(
    // input:
    const char *uplo,
    const char *trans,
    const char *diag,
    const SUITESPARSE_BLAS_INT *n,
    const void *A,
    const SUITESPARSE_BLAS_INT *lda,
    // input/output:
    void *X,
    // input:
    const SUITESPARSE_BLAS_INT *incx
) ;

#define SUITESPARSE_BLAS_ztrsv(uplo,trans,diag,n,A,lda,X,incx,ok)             \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZTRSV (uplo, trans, diag, &N_blas_int, A,            \
            &LDA_blas_int, X, &INCX_blas_int) ;                               \
    }                                                                         \
}

void SUITESPARSE_BLAS_DTRSM         // solve LX=B, UX=B, L'X=B, or U'X=B
(
    // input:
    const char *side,
    const char *uplo,
    const char *transa,
    const char *diag,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const double *alpha,
    const double *A,
    const SUITESPARSE_BLAS_INT *lda,
    // input/output:
    double *B,
    // input:
    const SUITESPARSE_BLAS_INT *ldb
) ;

#define SUITESPARSE_BLAS_dtrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DTRSM (side, uplo, transa, diag, &M_blas_int,        \
            &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ;         \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZTRSM         // solve (L, L', L^H, U, U', or U^H)X=B
(
    // input:
    const char *side,
    const char *uplo,
    const char *transa,
    const char *diag,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const void *alpha,
    const void *A,
    const SUITESPARSE_BLAS_INT *lda,
    // input/output:
    void *B,
    // input:
    const SUITESPARSE_BLAS_INT *ldb
) ;

#define SUITESPARSE_BLAS_ztrsm(side,uplo,transa,diag,m,n,alpha,A,lda,B,ldb,ok)\
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZTRSM (side, uplo, transa, diag, &M_blas_int,        \
            &N_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int) ;         \
    }                                                                         \
}

void SUITESPARSE_BLAS_DGEMM         // C = alpha*A*B + beta*C
(
    // input:
    const char *transa,
    const char *transb,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const double *alpha,
    const double *A,
    const SUITESPARSE_BLAS_INT *lda,
    const double *B,
    const SUITESPARSE_BLAS_INT *ldb,
    const double *beta,
    // input/output:
    double *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc
) ;

#define SUITESPARSE_BLAS_dgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta,    \
    C,ldc,ok)                                                                 \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DGEMM (transa, transb, &M_blas_int, &N_blas_int,     \
            &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C,  \
            &LDC_blas_int) ;                                                  \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZGEMM         // C = alpha*A*B + beta*C
(
    // input:
    const char *transa,
    const char *transb,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const void *alpha,
    const void *A,
    const SUITESPARSE_BLAS_INT *lda,
    const void *B,
    const SUITESPARSE_BLAS_INT *ldb,
    const void *beta,
    // input/output:
    void *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc
) ;

#define SUITESPARSE_BLAS_zgemm(transa,transb,m,n,k,alpha,A,lda,B,ldb,beta,    \
    C,ldc,ok)                                                                 \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDB_blas_int, ldb, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZGEMM (transa, transb, &M_blas_int, &N_blas_int,     \
            &K_blas_int, alpha, A, &LDA_blas_int, B, &LDB_blas_int, beta, C,  \
            &LDC_blas_int) ;                                                  \
    }                                                                         \
}

void SUITESPARSE_BLAS_DSYRK         // C = alpha*A*A' + beta*C, or A'A
(
    // input:
    const char *uplo,
    const char *trans,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const double *alpha,
    const double *A,
    const SUITESPARSE_BLAS_INT *lda,
    const double *beta,
    // input/output:
    double *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc
) ;

#define SUITESPARSE_BLAS_dsyrk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok)      \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DSYRK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \
            A, &LDA_blas_int, beta, C, &LDC_blas_int) ;                       \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZHERK         // C = alpha*A*A^H + beta*C, or A^H*A
(
    // input:
    const char *uplo,
    const char *trans,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const void *alpha,
    const void *A,
    const SUITESPARSE_BLAS_INT *lda,
    const void *beta,
    // input/output:
    void *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc
) ;

#define SUITESPARSE_BLAS_zherk(uplo,trans,n,k,alpha,A,lda,beta,C,ldc,ok)      \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZHERK (uplo, trans, &N_blas_int, &K_blas_int, alpha, \
            A, &LDA_blas_int, beta, C, &LDC_blas_int) ;                       \
    }                                                                         \
}

void SUITESPARSE_LAPACK_DPOTRF      // Cholesky factorization
(
    // input:
    const char *uplo,
    const SUITESPARSE_BLAS_INT *n,
    // input/output:
    double *A,
    // input:
    const SUITESPARSE_BLAS_INT *lda,
    // output:
    SUITESPARSE_BLAS_INT *info
) ;

#define SUITESPARSE_LAPACK_dpotrf(uplo,n,A,lda,info,ok)                       \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    info = 1 ;                                                                \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_INT LAPACK_Info = -999 ;                             \
        SUITESPARSE_LAPACK_DPOTRF (uplo, &N_blas_int, A, &LDA_blas_int,       \
          &LAPACK_Info) ;                                                     \
        info = (Int) LAPACK_Info ;                                            \
    }                                                                         \
}

void SUITESPARSE_LAPACK_ZPOTRF      // Cholesky factorization
(
    // input:
    const char *uplo,
    const SUITESPARSE_BLAS_INT *n,
    // input/output:
    void *A,
    // input:
    const SUITESPARSE_BLAS_INT *lda,
    // output:
    SUITESPARSE_BLAS_INT *info
) ;

#define SUITESPARSE_LAPACK_zpotrf(uplo,n,A,lda,info,ok)                       \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    info = 1 ;                                                                \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_INT LAPACK_Info = -999 ;                             \
        SUITESPARSE_LAPACK_ZPOTRF (uplo, &N_blas_int, A, &LDA_blas_int,       \
            &LAPACK_Info) ;                                                   \
        info = LAPACK_Info ;                                                  \
    }                                                                         \
}

void SUITESPARSE_BLAS_DSCAL         // Y = alpha*Y
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    const double *alpha,
    // input/output:
    double *Y,
    // input:
    const SUITESPARSE_BLAS_INT *incy
) ;

#define SUITESPARSE_BLAS_dscal(n,alpha,Y,incy,ok)                             \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ;      \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZSCAL         // Y = alpha*Y
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    const void *alpha,
    // input/output:
    void *Y,
    // input:
    const SUITESPARSE_BLAS_INT *incy
) ;

#define SUITESPARSE_BLAS_zscal(n,alpha,Y,incy,ok)                             \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZSCAL (&N_blas_int, alpha, Y, &INCY_blas_int) ;      \
    }                                                                         \
}

void SUITESPARSE_BLAS_DGER          // A = alpha*x*y' + A
(
    // input:
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const double *alpha,
    const double *X,
    const SUITESPARSE_BLAS_INT *incx,
    const double *Y,
    const SUITESPARSE_BLAS_INT *incy,
    // input/output:
    double *A,
    // input:
    const SUITESPARSE_BLAS_INT *lda
) ;

#define SUITESPARSE_BLAS_dger(m,n,alpha,X,incx,Y,incy,A,lda,ok)               \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_DGER (&M_blas_int, &N_blas_int, alpha, X,            \
            &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ;            \
    }                                                                         \
}

void SUITESPARSE_BLAS_ZGERU         // A = alpha*x*y' + A
(
    // input:
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const void *alpha,
    const void *X,
    const SUITESPARSE_BLAS_INT *incx,
    const void *Y,
    const SUITESPARSE_BLAS_INT *incy,
    // input/output:
    void *A,
    // input:
    const SUITESPARSE_BLAS_INT *lda
) ;

#define SUITESPARSE_BLAS_zgeru(m,n,alpha,X,incx,Y,incy,A,lda,ok)              \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (INCY_blas_int, incy, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (LDA_blas_int, lda, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_BLAS_ZGERU (&M_blas_int, &N_blas_int, alpha, X,           \
            &INCX_blas_int, Y, &INCY_blas_int, A, &LDA_blas_int) ;            \
    }                                                                         \
}

void SUITESPARSE_LAPACK_DLARFT      // T = block Householder factor
(
    // input:
    const char *direct,
    const char *storev,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const double *V,
    const SUITESPARSE_BLAS_INT *ldv,
    const double *Tau,
    // output:
    double *T,
    // input:
    const SUITESPARSE_BLAS_INT *ldt
) ;

#define SUITESPARSE_LAPACK_dlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok)       \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_DLARFT (direct, storev, &N_blas_int, &K_blas_int,  \
            V, &LDV_blas_int, Tau, T, &LDT_blas_int) ;                        \
    }                                                                         \
}

void SUITESPARSE_LAPACK_ZLARFT      // T = block Householder factor
(
    // input:
    const char *direct,
    const char *storev,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const void *V,
    const SUITESPARSE_BLAS_INT *ldv,
    const void *Tau,
    // output:
    void *T,
    // input:
    const SUITESPARSE_BLAS_INT *ldt
) ;

#define SUITESPARSE_LAPACK_zlarft(direct,storev,n,k,V,ldv,Tau,T,ldt,ok)       \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_ZLARFT (direct, storev, &N_blas_int, &K_blas_int,  \
            V, &LDV_blas_int, Tau, T, &LDT_blas_int) ;                        \
    }                                                                         \
}

void SUITESPARSE_LAPACK_DLARFB      // apply block Householder reflector
(
    // input:
    const char *side,
    const char *trans,
    const char *direct,
    const char *storev,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const double *V,
    const SUITESPARSE_BLAS_INT *ldv,
    const double *T,
    const SUITESPARSE_BLAS_INT *ldt,
    // input/output:
    double *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc,
    // workspace:
    double *Work,
    // input:
    const SUITESPARSE_BLAS_INT *ldwork
) ;

#define SUITESPARSE_LAPACK_dlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \
    C,ldc,Work,ldwork,ok)                                                     \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ;                   \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_DLARFB (side, trans, direct, storev, &M_blas_int,  \
            &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C,  \
            &LDC_blas_int, Work, &LDWORK_blas_int) ;                          \
    }                                                                         \
}

void SUITESPARSE_LAPACK_ZLARFB      // apply block Householder reflector
(
    // input:
    const char *side,
    const char *trans,
    const char *direct,
    const char *storev,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const SUITESPARSE_BLAS_INT *k,
    const void *V,
    const SUITESPARSE_BLAS_INT *ldv,
    const void *T,
    const SUITESPARSE_BLAS_INT *ldt,
    // input/output:
    void *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc,
    // workspace:
    void *Work,
    // input:
    const SUITESPARSE_BLAS_INT *ldwork
) ;

#define SUITESPARSE_LAPACK_zlarfb(side,trans,direct,storev,m,n,k,V,ldv,T,ldt, \
    C,ldc,Work,ldwork,ok)                                                     \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (K_blas_int, k, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (LDV_blas_int, ldv, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDT_blas_int, ldt, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    SUITESPARSE_TO_BLAS_INT (LDWORK_blas_int, ldwork, ok) ;                   \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_ZLARFB (side, trans, direct, storev, &M_blas_int,  \
            &N_blas_int, &K_blas_int, V, &LDV_blas_int, T, &LDT_blas_int, C,  \
            &LDC_blas_int, Work, &LDWORK_blas_int) ;                          \
    }                                                                         \
}

double SUITESPARSE_BLAS_DNRM2       // vector 2-norm
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    const double *X,
    const SUITESPARSE_BLAS_INT *incx
) ;

#define SUITESPARSE_BLAS_dnrm2(result,n,X,incx,ok)                            \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    result = 0 ;                                                              \
    if (ok)                                                                   \
    {                                                                         \
        result = SUITESPARSE_BLAS_DNRM2 (&N_blas_int, X, &INCX_blas_int) ;    \
    }                                                                         \
}

double SUITESPARSE_BLAS_DZNRM2      // vector 2-norm
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    const void *X,
    const SUITESPARSE_BLAS_INT *incx
) ;

#define SUITESPARSE_BLAS_dznrm2(result,n,X,incx,ok)                           \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    result = 0 ;                                                              \
    if (ok)                                                                   \
    {                                                                         \
        result = SUITESPARSE_BLAS_DZNRM2 (&N_blas_int, X, &INCX_blas_int) ;   \
    }                                                                         \
}

void SUITESPARSE_LAPACK_DLARFG      // generate Householder reflector
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    // input/output:
    double *alpha,
    double *X,
    // input:
    const SUITESPARSE_BLAS_INT *incx,
    // output:
    double *tau
) ;

#define SUITESPARSE_LAPACK_dlarfg(n,alpha,X,incx,tau,ok)                      \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_DLARFG (&N_blas_int, alpha, X, &INCX_blas_int,     \
            tau) ;                                                            \
    }                                                                         \
}

void SUITESPARSE_LAPACK_ZLARFG      // generate Householder reflector
(
    // input:
    const SUITESPARSE_BLAS_INT *n,
    // input/output:
    void *alpha,
    void *X,
    // input:
    const SUITESPARSE_BLAS_INT *incx,
    // output:
    void *tau
) ;

#define SUITESPARSE_LAPACK_zlarfg(n,alpha,X,incx,tau,ok)                      \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCX_blas_int, incx, ok) ;                       \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_ZLARFG (&N_blas_int, alpha, X, &INCX_blas_int,     \
            tau) ;                                                            \
    }                                                                         \
}

void SUITESPARSE_LAPACK_DLARF       // apply Householder reflector
(
    // input:
    const char *side,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const double *V,
    const SUITESPARSE_BLAS_INT *incv,
    const double *tau,
    // input/output:
    double *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc,
    // workspace:
    double *Work
) ;

#define SUITESPARSE_LAPACK_dlarf(side,m,n,V,incv,tau,C,ldc,Work,ok)           \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_DLARF (side, &M_blas_int, &N_blas_int, V,          \
            &INCV_blas_int, tau, C, &LDC_blas_int, Work) ;                    \
    }                                                                         \
}

void SUITESPARSE_LAPACK_ZLARF       // apply Householder reflector
(
    // input:
    const char *side,
    const SUITESPARSE_BLAS_INT *m,
    const SUITESPARSE_BLAS_INT *n,
    const void *V,
    const SUITESPARSE_BLAS_INT *incv,
    const void *tau,
    // input/output:
    void *C,
    // input:
    const SUITESPARSE_BLAS_INT *ldc,
    // workspace:
    void *Work
) ;

#define SUITESPARSE_LAPACK_zlarf(side,m,n,V,incv,tau,C,ldc,Work,ok)           \
{                                                                             \
    SUITESPARSE_TO_BLAS_INT (M_blas_int, m, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (N_blas_int, n, ok) ;                             \
    SUITESPARSE_TO_BLAS_INT (INCV_blas_int, incv, ok) ;                       \
    SUITESPARSE_TO_BLAS_INT (LDC_blas_int, ldc, ok) ;                         \
    if (ok)                                                                   \
    {                                                                         \
        SUITESPARSE_LAPACK_ZLARF (side, &M_blas_int, &N_blas_int, V,          \
            &INCV_blas_int, tau, C, &LDC_blas_int, Work) ;                    \
    }                                                                         \
}

#endif

//------------------------------------------------------------------------------
// SuiteSparse_BLAS_library: return name of BLAS library found
//------------------------------------------------------------------------------

// Returns the name of the BLAS library found by SuiteSparse_config

const char *SuiteSparse_BLAS_library ( void ) ;

//------------------------------------------------------------------------------
// SuiteSparse_BLAS_integer_size: return sizeof (SUITESPARSE_BLAS_INT)
//------------------------------------------------------------------------------

size_t SuiteSparse_BLAS_integer_size ( void ) ;

#ifdef __cplusplus
}
#endif
#endif

