//------------------------------------------------------------------------------
// RBio/Include/RBio.h: include file for RBio
//------------------------------------------------------------------------------

// RBio, Copyright (c) 2009-2023, Timothy A. Davis.  All Rights Reserved.
// SPDX-License-Identifier: GPL-2.0+

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

#ifndef _RBIO_H
#define _RBIO_H

/* -------------------------------------------------------------------------- */
/* large file I/O support */
/* -------------------------------------------------------------------------- */

/* Definitions required for large file I/O, which must come before any other
 * #includes.  These are not used if -DNLARGEFILE is defined at compile time.
 * Large file support may not be portable across all platforms and compilers;
 * if you encounter an error here, compile your code with -DNLARGEFILE.  In
 * particular, you must use -DNLARGEFILE for MATLAB 6.5 or earlier (which does
 * not have the io64.h include file).   See also CHOLMOD/Include/cholmod_io64.h.
 */

/* skip all of this if NLARGEFILE is defined at the compiler command line */
#ifndef NLARGEFILE

#if defined(MATLAB_MEX_FILE) || defined(MATHWORKS)

/* RBio is being compiled as a MATLAB mexFunction, or for use in MATLAB */
#include "io64.h"

#else

/* RBio is being compiled in a stand-alone library */
#undef  _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#undef  _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64

#endif

#endif


/* -------------------------------------------------------------------------- */
/* include files */
/* -------------------------------------------------------------------------- */

#include "SuiteSparse_config.h"

/* -------------------------------------------------------------------------- */
/* error codes */
/* -------------------------------------------------------------------------- */

#define RBIO_OK (0)               /* matrix is OK */

/* data structure errors */
#define RBIO_CP_INVALID (-1)      /* column pointers are invalid */
#define RBIO_ROW_INVALID (-2)     /* row indices are out of range */
#define RBIO_DUPLICATE (-3)       /* duplicate entry */
#define RBIO_EXTRANEOUS (-4)      /* entries in upper tri part of sym matrix */
#define RBIO_TYPE_INVALID (-5)    /* matrix type (RUA, etc) invalid */
#define RBIO_DIM_INVALID (-6)     /* matrix dimensions invalid */
#define RBIO_JUMBLED (-7)         /* matrix contains unsorted columns */
#define RBIO_ARG_ERROR (-8)       /* input arguments invalid */
#define RBIO_OUT_OF_MEMORY (-9)   /* out of memory */
#define RBIO_MKIND_INVALID (-10)  /* mkind is invalid */
#define RBIO_UNSUPPORTED (-11)    /* finite-element form unsupported */

/* I/O errors */
#define RBIO_HEADER_IOERROR (-91) /* I/O error: header */
#define RBIO_CP_IOERROR (-92)     /* I/O error: column pointers */
#define RBIO_ROW_IOERROR (-93)    /* I/O error: row indices */
#define RBIO_VALUE_IOERROR (-94)  /* I/O error: numerical values */
#define RBIO_FILE_IOERROR (-95)   /* I/O error: cannot read/write the file */

#define RBIO_DATE "Jan 10, 2024"
#define RBIO_MAIN_VERSION   4
#define RBIO_SUB_VERSION    3
#define RBIO_SUBSUB_VERSION 1

#define RBIO_VER_CODE(main,sub) SUITESPARSE_VER_CODE(main,sub)
#define RBIO_VERSION RBIO_VER_CODE(4,3)

#define RBIO__VERSION SUITESPARSE__VERCODE(4,3,1)
#if !defined (SUITESPARSE__VERSION) || \
    (SUITESPARSE__VERSION < SUITESPARSE__VERCODE(7,5,0))
#error "RBio 4.3.1 requires SuiteSparse_config 7.5.0 or later"
#endif

/* -------------------------------------------------------------------------- */
/* user-callable functions */
/* -------------------------------------------------------------------------- */

/*
    RBread:         read a Rutherford/Boeing matrix from a file
    RBwrite:        write a matrix to a file in R/B format

    RBkind:         determine the matrix type (RUA, RSA, etc)
    RBreadraw:      read the raw contents of a R/B file

    RBget_entry:    get a single numerical value from a matrix
    RBput_entry:    put a single numerical value into a matrix

    RBmalloc:       malloc-wrapper for RBio
    RBfree:         free-wrapper for RBio
    RBok:           test the validity of a sparse matrix

    Each function comes in two versions: one with int32_t integers, the other
    with int64_t integers.  The default type is int64_t.  Functions for int32_t
    integers have the _i suffix appended to their names.
*/

#ifdef __cplusplus
extern "C" {
#endif

int RBkind_i        /* 0: OK, < 0: error, > 0: warning */
(
    /* input */
    int32_t nrow,       /* A is nrow-by-ncol */
    int32_t ncol,
    const int32_t *Ap,  /* Ap [0...ncol]: column pointers */
    const int32_t *Ai,  /* Ai [0...nnz-1]: row indices */
    const double *Ax,   /* Ax [0...nnz-1]: real values.  Az holds imaginary part */
    const double *Az,   /* if real, Az is NULL. if complex, Az is non-NULL */
    int32_t mkind_in,   /* 0:R, 1:P: 2:Csplit, 3:I, 4:Cmerged */

    /* output */
    int32_t *mkind, /* 0:R, 1:P: 2:Csplit, 3:I, 4:Cmerged */
    int32_t *skind, /* r: -1 (rectangular), u: 0 (unsymmetric), s: 1 symmetric,
                       h: 2 (Hermitian), z: 3 (skew symmetric) */
    char mtype [4], /* rua, psa, rra, cha, etc */
    double *xmin,   /* smallest value */
    double *xmax,   /* largest value */

    /* workspace: allocated internally if NULL */
    int32_t *cp     /* workspace of size ncol+1, undefined on input and output*/
) ;

int RBkind (int64_t nrow, int64_t ncol,
    const int64_t *Ap, const int64_t *Ai, const double *Ax, const double *Az,
    int64_t mkind_in, int64_t *mkind, int64_t *skind,
    char mtype [4], double *xmin, double *xmax, int64_t *cp) ;

int RBread_i            /* 0: OK, < 0: error, > 0: warning */
(
    /* input */
    const char *filename,   /* file to read from */
    int32_t build_upper,    /* if true, construct upper part for sym. matrices */
    int32_t zero_handling,  /* 0: do nothing, 1: prune zeros, 2: extract zeros */

    /* output */
    char title [73],
    char key [9],
    char mtype [4],     /* RUA, RSA, PUA, PSA, RRA, etc */
    int32_t *nrow,      /* A is nrow-by-ncol */
    int32_t *ncol,
    int32_t *mkind,     /* R: 0, P: 1, C: 2, I: 3 */
    int32_t *skind,     /* R: -1, U: 0, S: 1, H: 2, Z: 3 */
    int32_t *asize,     /* Ai array has size asize*sizeof(double) */
    int32_t *znz,       /* number of explicit zeros removed from A */

    /* output: these are malloc'ed below and must be freed by the caller */
    int32_t **Ap,       /* column pointers of A */
    int32_t **Ai,       /* row indices of A */
    double **Ax,        /* real values (ignored if NULL) of A */
    double **Az,        /* imaginary values (ignored if NULL) of A */
    int32_t **Zp,       /* column pointers of Z */
    int32_t **Zi        /* row indices of Z */
) ;

int RBread (const char *filename, int64_t build_upper,
    int64_t zero_handling, char title [73], char key [9],
    char mtype [4], int64_t *nrow, int64_t *ncol,
    int64_t *mkind, int64_t *skind, int64_t *asize,
    int64_t *znz, int64_t **Ap, int64_t **Ai,
    double **Ax, double **Az, int64_t **Zp, int64_t **Zi) ;


int RBreadraw_i         /* 0: OK, < 0: error, > 0: warning */
(
    /* input */
    const char *filename, /* file to read from */

    /* output */
    char title [73],
    char key [9],
    char mtype [4],     /* RUA, RSA, PUA, PSA, RRA, etc */
    int32_t *nrow,      /* A is nrow-by-ncol */
    int32_t *ncol,
    int32_t *nnz,       /* size of Ai */
    int32_t *nelnz,
    int32_t *mkind,     /* 0:R, 1:P: 2:Csplit, 3:I, 4:Cmerged */
    int32_t *skind,     /* R: -1, U: 0, S: 1, H: 2, Z: 3 */
    int32_t *fem,       /* 0:__A, 1:__E */
    int32_t *xsize,     /* size of Ax */

    /* output: these are malloc'ed below and must be freed by the caller */
    int32_t **p_Ap,     /* size ncol+1, column pointers of A */
    int32_t **p_Ai,     /* size nnz, row indices of A */
    double **p_Ax       /* size xsize, numerical values of A */
) ;


int RBreadraw (const char *filename, char title [73], char key [9],
    char mtype[4], int64_t *nrow, int64_t *ncol,
    int64_t *nnz, int64_t *nelnz, int64_t *mkind,
    int64_t *skind, int64_t *fem, int64_t *xsize,
    int64_t **p_Ap, int64_t **p_Ai, double **p_Ax) ;


int RBwrite_i       /* 0:OK, < 0: error, > 0: warning */
(
    /* input */
    const char *filename, /* filename to write to (stdout if NULL) */
    const char *title,    /* title (72 char max), may be NULL */
    const char *key,      /* key (8 char max), may be NULL */
    int32_t nrow,         /* A is nrow-by-ncol */
    int32_t ncol,
    const int32_t *Ap,    /* size ncol+1, column pointers */
    const int32_t *Ai,    /* size anz=Ap[ncol], row indices (sorted) */
    const double *Ax,     /* size anz or 2*anz, numerical values (binary if NULL) */
    const double *Az,     /* size anz, imaginary part (real if NULL) */
    const int32_t *Zp,    /* size ncol+1, column pointers for Z (or NULL) */
    const int32_t *Zi,    /* size znz=Zp[ncol], row indices for Z (or NULL) */
    int32_t mkind_in,     /* 0:R, 1:P: 2:Csplit, 3:I, 4:Cmerged */

    /* output */
    char mtype [4]  /* matrix type (RUA, RSA, etc), may be NULL */
) ;

int RBwrite (const char *filename, const char *title, const char *key,
    int64_t nrow, int64_t ncol, const int64_t *Ap,
    const int64_t *Ai, const double *Ax, const double *Az, const int64_t *Zp,
    const int64_t *Zi, int64_t mkind_in, char mtype [4]) ;


void RBget_entry_i
(
    int32_t mkind,      /* R: 0, P: 1, C: 2, I: 3 */
    const double *Ax,   /* real part, or both if merged-complex */
    const double *Az,   /* imaginary part if split-complex */
    int32_t p,          /* index of the entry */
    double *xr,         /* real part */
    double *xz          /* imaginary part */
) ;

void RBget_entry (int64_t mkind, const double *Ax, const double *Az,
    int64_t p, double *xr, double *xz) ;


void RBput_entry_i
(
    int32_t mkind,      /* R: 0, P: 1, C: 2, I: 3 */
    double *Ax,         /* real part, or both if merged-complex */
    double *Az,         /* imaginary part if split-complex */
    int32_t p,          /* index of the entry */
    double xr,          /* real part */
    double xz           /* imaginary part */
) ;

void RBput_entry (int64_t mkind, double *Ax, double *Az,
    int64_t p, double xr, double xz) ;


int RBok_i          /* 0:OK, < 0: error, > 0: warning */
(
    /* inputs, not modified */
    int32_t nrow,       /* number of rows */
    int32_t ncol,       /* number of columns */
    int32_t nzmax,      /* max # of entries */
    const int32_t *Ap,  /* size ncol+1, column pointers */
    const int32_t *Ai,  /* size nz = Ap [ncol], row indices */
    const double *Ax,   /* real part, or both if merged-complex */
    const double *Az,   /* imaginary part for split-complex */
    const char *As,     /* logical matrices (useful for MATLAB caller only) */
    int32_t mkind,      /* 0:real, 1:logical/pattern, 2:split-complex, 3:integer,
                           4:merged-complex */

    /* outputs, not defined on input */
    int32_t *p_njumbled,   /* # of jumbled row indices (-1 if not computed) */
    int32_t *p_nzeros      /* number of explicit zeros (-1 if not computed) */
) ;

int RBok (int64_t nrow, int64_t ncol,
    int64_t nzmax, const int64_t *Ap, const int64_t *Ai,
    const double *Ax, const double *Az, const char *As, int64_t mkind,
    int64_t *p_njumbled, int64_t *p_nzeros) ;

#ifdef MATLAB_MEX_FILE
void RBerror (int status) ;     /* only for MATLAB mexFunctions */
#endif

void RBio_version (int version [3]) ;

#ifdef __cplusplus
}
#endif
#endif
