/**
 *
 * @file d_spm_print.c
 *
 * SParse Matrix package printing routines.
 *
 * @copyright 2016-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @version 1.2.4
 * @author Mathieu Faverge
 * @author Alban Bellot
 * @author Matias Hastaran
 * @author Tony Delarue
 * @author Alycia Lisito
 * @date 2024-06-25
 *
 * @generated from /build/pastix/src/pastix-6.4.0/spm/src/z_spm_print.c, normal z -> d, Sun Feb 15 18:01:29 2026
 *
 * @ingroup spm_dev_print
 * @{
 *
 **/
#include "common.h"

/**
 *******************************************************************************
 *
 * @brief Print a diagonal element within a symmetric/symmetric
 * matrix with column/row major storage
 *
 * Note that column major is using the low triangular part only of the diagonal
 * element matrices, and row major, by symmetry, is using only the upper
 * triangular part.
 *
 * The comments in the code are made for column major storage.
 *
 *******************************************************************************
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] conjfct
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt_sym_diag( spm_int_t              row,
                          spm_int_t              dofi,
                          spm_dconj_fct_t        conjfct,
                          const double *valptr,
                          FILE                  *f )
{
    spm_int_t ii, jj;

    for(jj=0; jj<dofi; jj++)
    {
        /* Skip unused upper triangular part */
        for(ii=0; ii<jj; ii++) {
            valptr++;
        }

        /* Diagonal element */
        d_spmPrintElt( f, row + ii, row + jj, *valptr );
        valptr++;

        for(ii=jj+1; ii<dofi; ii++, valptr++)
        {
            /* Lower part */
            d_spmPrintElt( f, row + ii, row + jj,         *valptr  );
            /* Upper part */
            d_spmPrintElt( f, row + jj, row + ii, conjfct(*valptr) );
        }
    }
    (void)conjfct;
}

/**
 *******************************************************************************
 *
 * @brief Print a general element matrix with column major storage
 *
 *******************************************************************************
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] col
 *          TODO
 *
 * @param[in] dofj
 *          TODO
 *
 * @param[in] conjfct
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt_gen_col( spm_int_t              row,
                         spm_int_t              dofi,
                         spm_int_t              col,
                         spm_int_t              dofj,
                         spm_dconj_fct_t        conjfct,
                         const double *valptr,
                         FILE                  *f )
{
    spm_int_t ii, jj;

    for(jj=0; jj<dofj; jj++)
    {
        for(ii=0; ii<dofi; ii++, valptr++)
        {
            d_spmPrintElt( f, row + ii, col + jj, conjfct(*valptr) );
        }
    }
    (void)conjfct;
}

/**
 *******************************************************************************
 *
 * @brief Print a general element matrix with row major storage
 *
 *******************************************************************************
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] col
 *          TODO
 *
 * @param[in] dofj
 *          TODO
 *
 * @param[in] conjfct
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt_gen_row( spm_int_t              row,
                         spm_int_t              dofi,
                         spm_int_t              col,
                         spm_int_t              dofj,
                         spm_dconj_fct_t        conjfct,
                         const double *valptr,
                         FILE                  *f )
{
    spm_int_t ii, jj;

    for(ii=0; ii<dofi; ii++)
    {
        for(jj=0; jj<dofj; jj++, valptr++)
        {
            d_spmPrintElt( f, row + ii, col + jj, conjfct(*valptr) );
        }
    }
    (void)conjfct;
}

/**
 *******************************************************************************
 *
 * @brief Print a general element matrix
 *
 *******************************************************************************
 *
 * @param[in] layout
 *          TODO
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] col
 *          TODO
 *
 * @param[in] dofj
 *          TODO
 *
 * @param[in] conjfct
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt_gen( spm_layout_t           layout,
                     spm_int_t              row,
                     spm_int_t              dofi,
                     spm_int_t              col,
                     spm_int_t              dofj,
                     const spm_dconj_fct_t  conjfct,
                     const double *valptr,
                     FILE                  *f )
{
    if ( layout == SpmColMajor ) {
        d_spm_print_elt_gen_col( row, dofi, col, dofj, conjfct, valptr, f );
    }
    else {
        d_spm_print_elt_gen_row( row, dofi, col, dofj, conjfct, valptr, f );
    }
}

/**
 *******************************************************************************
 *
 * @brief Print an off-diagonal element matrix in the symmetric/symmetric case
 *
 *******************************************************************************
 *
 * @param[in] layout
 *          TODO
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] col
 *          TODO
 *
 * @param[in] dofj
 *          TODO
 *
 * @param[in] conjfct
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt_sym_offd( spm_layout_t           layout,
                          spm_int_t              row,
                          spm_int_t              dofi,
                          spm_int_t              col,
                          spm_int_t              dofj,
                          spm_dconj_fct_t        conjfct,
                          const double *valptr,
                          FILE                  *f )
{
    if ( layout == SpmColMajor ) {
        /* A[ row, col ] */
        d_spm_print_elt_gen_col( row, dofi, col, dofj, __spm_did, valptr, f );
        /*
         * A[ col, row ] = ( A[ row, col ]^t )
         * => Let's exploit the row major kernel to make it transpose
         */
        d_spm_print_elt_gen_row( col, dofj, row, dofi, conjfct,  valptr, f );
    }
    else {
        d_spm_print_elt_gen_row( row, dofi, col, dofj, __spm_did, valptr, f );
        d_spm_print_elt_gen_col( col, dofj, row, dofi, conjfct,  valptr, f );
    }
}

/**
 *******************************************************************************
 *
 * @brief Print an element matrix
 *
 *******************************************************************************
 *
 * @param[in] mtxtype
 *          TODO
 *
 * @param[in] layout
 *          TODO
 *
 * @param[in] row
 *          TODO
 *
 * @param[in] dofi
 *          TODO
 *
 * @param[in] col
 *          TODO
 *
 * @param[in] dofj
 *          TODO
 *
 * @param[in] valptr
 *          TODO
 *
 * @param[inout] f
 *          TODO
 *
 *******************************************************************************/
static inline void
d_spm_print_elt( spm_mtxtype_t          mtxtype,
                 spm_layout_t           layout,
                 spm_int_t              row,
                 spm_int_t              dofi,
                 spm_int_t              col,
                 spm_int_t              dofj,
                 const double *valptr,
                 FILE                  *f )
{
    if ( mtxtype == SpmGeneral ) {
        d_spm_print_elt_gen( layout, row, dofi, col, dofj, __spm_did, valptr, f );
    }
    else {
        spm_dconj_fct_t conjfct;

#if defined(PRECISION_c) || defined(PRECISION_z)
        if ( mtxtype == SpmSymmetric ) {
            conjfct = __spm_dconj;
        }
        else
#endif
        {
            conjfct = __spm_did;
        }

        if ( row == col ) {
            assert( dofi == dofj );
            d_spm_print_elt_sym_diag( row, dofi, conjfct, valptr, f );
        }
        else {
            d_spm_print_elt_sym_offd( layout, row, dofi, col, dofj, conjfct, valptr, f );
        }
    }
}

/**
 *******************************************************************************
 *
 * @brief Write CSC matrix in a file
 *
 *******************************************************************************
 *
 * @param[inout] f
 *          Output file
 *
 * @param[in] spm
 *          The spm structure describing the matrix.
 *
 *******************************************************************************/
void
d_spmCSCPrint( FILE             *f,
               const spmatrix_t *spm )
{
    spm_int_t              j, k, baseval;
    spm_int_t              ig, dofi, row;
    spm_int_t              jg, dofj, col;
    const spm_int_t       *colptr, *rowptr, *dofs, *loc2glob;
    const double *valptr;

    assert( spm->fmttype == SpmCSC );
    assert( spm->flttype == SpmDouble );

    baseval = spm->baseval;

    colptr   = spm->colptr;
    rowptr   = spm->rowptr;
    valptr   = (double*)(spm->values);
    dofs     = spm->dofs;
    loc2glob = spm->loc2glob;

    for(j=0; j<spm->n; j++, colptr++, loc2glob++)
    {
        jg = spm->replicated ? j : (*loc2glob) - baseval;
        if ( spm->dof > 0 ) {
            dofj = spm->dof;
            col  = spm->dof * jg;
        }
        else {
            dofj = dofs[jg+1] - dofs[jg];
            col  = dofs[jg] - baseval;
        }

        for(k=colptr[0]; k<colptr[1]; k++, rowptr++)
        {
            ig = (*rowptr - baseval);
            if ( spm->dof > 0 ) {
                dofi = spm->dof;
                row  = spm->dof * ig;
            }
            else {
                dofi = dofs[ig+1] - dofs[ig];
                row  = dofs[ig] - baseval;
            }

            d_spm_print_elt( spm->mtxtype, spm->layout,
                             row, dofi, col, dofj, valptr, f );
            valptr += dofi * dofj;
        }
    }
    return;
}

/**
 *******************************************************************************
 *
 * @brief Write CSR matrix in a file
 *
 *******************************************************************************
 *
 * @param[in] f
 *          Output file
 *
 * @param[in] spm
 *          The spm structure describing the matrix.
 *
 *******************************************************************************/
void
d_spmCSRPrint( FILE             *f,
               const spmatrix_t *spm )
{
    spm_int_t              i, k, baseval;
    spm_int_t              ig, dofi, row;
    spm_int_t              jg, dofj, col;
    const spm_int_t       *colptr;
    const spm_int_t       *rowptr;
    const spm_int_t       *dofs;
    const spm_int_t       *loc2glob;
    const double *valptr;

    assert( spm->fmttype == SpmCSR );
    assert( spm->flttype == SpmDouble );

    baseval = spm->baseval;

    colptr   = spm->colptr;
    rowptr   = spm->rowptr;
    valptr   = (double*)(spm->values);
    dofs     = spm->dofs;
    loc2glob = spm->loc2glob;

    for(i=0; i<spm->n; i++, rowptr++, loc2glob++)
    {
        ig = spm->replicated ? i : (*loc2glob) - baseval;
        if ( spm->dof > 0 ) {
            dofi = spm->dof;
            row  = spm->dof * ig;
        }
        else {
            dofi = dofs[ig+1] - dofs[ig];
            row  = dofs[ig] - baseval;
        }

        for(k=rowptr[0]; k<rowptr[1]; k++, colptr++)
        {
            jg = (*colptr - baseval);
            if ( spm->dof > 0 ) {
                dofj = spm->dof;
                col  = spm->dof * jg;
            }
            else {
                dofj = dofs[jg+1] - dofs[jg];
                col  = dofs[jg] - baseval;
            }

            d_spm_print_elt( spm->mtxtype, spm->layout,
                             row, dofi, col, dofj, valptr, f );
            valptr += dofi * dofj;
        }
    }

    return;
}

/**
 *******************************************************************************
 *
 * @brief Write IJV matrix in a file
 *
 *******************************************************************************
 *
 * @param[in] f
 *          Output file
 *
 * @param[in] spm
 *          The spm structure describing the matrix.
 *
 *******************************************************************************/
void
d_spmIJVPrint( FILE             *f,
               const spmatrix_t *spm )
{
    spm_int_t              k, baseval;
    spm_int_t              i, dofi, row;
    spm_int_t              j, dofj, col;
    const spm_int_t       *colptr;
    const spm_int_t       *rowptr;
    const spm_int_t       *dofs;
    const double *valptr;

    assert( spm->fmttype == SpmIJV );
    assert( spm->flttype == SpmDouble );

    baseval = spm->baseval;

    colptr = spm->colptr;
    rowptr = spm->rowptr;
    valptr = (double*)(spm->values);
    dofs   = spm->dofs;

    for(k=0; k<spm->nnz; k++, rowptr++, colptr++)
    {
        i = *rowptr - baseval;
        j = *colptr - baseval;

        if ( spm->dof > 0 ) {
            dofi = spm->dof;
            row  = spm->dof * i;
            dofj = spm->dof;
            col  = spm->dof * j;
        }
        else {
            dofi = dofs[i+1] - dofs[i];
            row  = dofs[i] - baseval;
            dofj = dofs[j+1] - dofs[j];
            col  = dofs[j] - baseval;
        }

        d_spm_print_elt( spm->mtxtype, spm->layout,
                         row, dofi, col, dofj, valptr, f );
        valptr += dofi * dofj;
    }
    return;
}

/**
 *******************************************************************************
 *
 * @brief Write a spm matrix in a file
 *
 *******************************************************************************
 *
 * @param[in] f
 *          Output file
 *
 * @param[in] spm
 *          The spm structure describing the matrix.
 *
 *******************************************************************************/
void
d_spmPrint( FILE *f, const spmatrix_t *spm )
{
    switch (spm->fmttype) {
    case SpmCSC:
        d_spmCSCPrint( f, spm );
        break;
    case SpmCSR:
        d_spmCSRPrint( f, spm );
        break;
    case SpmIJV:
        d_spmIJVPrint( f, spm );
    }
    return;
}

/**
 *******************************************************************************
 *
 * @brief Write into a file the vectors associated to a spm.
 *
 *******************************************************************************
 *
 * @param[inout] f
 *          Output file
 *
 * @param[in] spm
 *          The spm structure describing the matrix.
 *
 * @param[in] nrhs
 *          The number of columns of x.
 *
 * @param[in] x
 *          The set of vectors associated to the spm of size ldx-by-nrhs.
 *
 * @param[in] ldx
 *          The local leading dimension of the set of vectors (ldx >= spm->n).
 *
 *******************************************************************************/
void
d_spmPrintRHS( FILE *f, const spmatrix_t *spm,
               int nrhs, const void *x, spm_int_t ldx )
{
    const double *xptr = (const double *)x;
    spm_int_t i, j, ig, baseval;

    baseval = spm->baseval;

    for( j=0; j<nrhs; j++) {
        for( i=0; i < spm->nexp; i++, xptr++ ) {
            ig = spm->replicated ? i : spm->loc2glob[i] - baseval;

            d_spmPrintElt( f, ig, j, *xptr );
        }
        xptr += ldx - i;
    }
}

/**
 * @}
 */
