/* ========================================================================== */
/* === UMFPACK_report_symbolic ============================================== */
/* ========================================================================== */

/* -------------------------------------------------------------------------- */
/* UMFPACK Version 3.2 (Jan. 1, 2002), Copyright (c) 2002 by Timothy A.       */
/* Davis, University of Florida, davis@cise.ufl.edu.  All Rights Reserved.    */
/* See README, umfpack.h, or type "umfpack_details" in Matlab for License.    */
/* -------------------------------------------------------------------------- */

/*
    User-callable.  Prints the Symbolic object. See umfpack_report_symbolic.h
    for details.

    Dynamic memory usage:  Allocates a size n*sizeof(Int)
    workspace via a single call to UMF_malloc and then frees all of it via
    UMF_free on return.  The workspace is not allocated if an early error
    return occurs  before the workspace is needed.

*/

#include "umf_internal.h"
#include "umf_valid_symbolic.h"
#include "umf_report_perm.h"
#include "umf_malloc.h"
#include "umf_free.h"

GLOBAL Int UMFPACK_report_symbolic
(
    const char name [ ],
    void *SymbolicHandle,
    const double Control [UMFPACK_CONTROL]
)
{
    Int n, nz, nchains, nfr, maxfrsize, maxnrows, maxncols, prl,
	k, chain, frontid, frontid1, frontid2, kk, *Chain_start, *W,
	*Chain_maxrows, *Chain_maxcols, *Front_npivots, *Front_parent, done,
	status ;
    SymbolicType *Symbolic ;

    if (Control)
    {
	prl = (Int) Control [UMFPACK_PRL] ;
    }
    else
    {
	prl = UMFPACK_DEFAULT_PRL ;
    }

    if (prl <= 2)
    {
	return (UMFPACK_OK) ;
    }

    PRINTF (("\n")) ;
    if (name)
    {
	PRINTF (("%s: ", name)) ;
    }
    PRINTF (("Symbolic object: ")) ;

    Symbolic = (SymbolicType *) SymbolicHandle ;
    if (!UMF_valid_symbolic (Symbolic))
    {
	PRINTF (("ERROR: invalid\n")) ;
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    n = Symbolic->n ;

    nz = Symbolic->nz ;

    nchains = Symbolic->nchains ;
    nfr = Symbolic->nfr ;
    maxfrsize = Symbolic->maxfrsize ;
    maxnrows = Symbolic->maxnrows ;
    maxncols = Symbolic->maxncols ;

    Chain_start = Symbolic->Chain_start ;
    Chain_maxrows = Symbolic->Chain_maxrows ;
    Chain_maxcols = Symbolic->Chain_maxcols ;
    Front_npivots = Symbolic->Front_npivots ;
    Front_parent = Symbolic->Front_parent ;

    PRINTF4 (("\n    matrix to be factorized:\n")) ;
    PRINTF4 (("\tn: "ID"\n", n)) ;
    PRINTF4 (("\tnumber of entries: "ID"\n", nz)) ;
    PRINTF4 (("\tdense row contol parameter used: %g\n", Symbolic->drow)) ;
    PRINTF4 (("\tdense column contol parameter used: %g\n", Symbolic->dcol)) ;
    PRINTF4 (("\tblock size used for dense matrix kernels:  "ID"\n",
	Symbolic->nb)) ;

    PRINTF4 (("    variable-size part of Numeric object:\n")) ;
    PRINTF4 (("\tminimum initial size (Units): "ID"\n",
	Symbolic->num_mem_init_usage)) ;
    PRINTF4 (("\testimated peak size (Units):  %g\n",
	Symbolic->num_mem_usage_est)) ;
    PRINTF4 (("\testimated final size (Units): %g\n",
	Symbolic->num_mem_size_est)) ;
    if (Symbolic->num_mem_usage_est > Int_MAX / sizeof (Int))
    {
	PRINTF4 (("\tWarning: peak size (in bytes) exceeds maximum integer\n"));
    }
    PRINTF4 (("    peak memory usage for symbolic factorization (Units): %g\n",
	Symbolic->peak_sym_usage)) ;

    PRINTF4 (("    frontal matrices / supercolumns:\n")) ;
    PRINTF4 (("\tnumber of frontal chains: "ID"\n", nchains)) ;
    PRINTF4 (("\tnumber of frontal matrices: "ID"\n", nfr)) ;
    PRINTF4 (("\tlargest frontal matrix size (entries): "ID"\n", maxfrsize)) ;
    PRINTF4 (("\tlargest frontal matrix row dimension: "ID"\n", maxnrows)) ;
    PRINTF4 (("\tlargest frontal matrix column dimension: "ID"\n", maxncols)) ;

    k = 0 ;
    done = FALSE ;

    for (chain = 0 ; chain < nchains ; chain++)
    {
	frontid1 = Chain_start [chain] ;
	frontid2 = Chain_start [chain+1] - 1 ;
	PRINTF4 (("\n    Frontal chain: "ID".  Frontal matrices "ID" to "ID"\n",
	    INDEX (chain), INDEX (frontid1), INDEX (frontid2))) ;
	PRINTF4 (("\tLargest frontal matrix in Frontal chain: "ID"-by-"ID"\n",
	    Chain_maxrows [chain], Chain_maxcols [chain])) ;
	for (frontid = frontid1 ; frontid <= frontid2 ; frontid++)
	{
	    kk = Front_npivots [frontid] ;
	    PRINTF4 (("\tFront: "ID"  pivots: "ID" (pivot columns "ID" to "ID
		")  ", INDEX (frontid), kk, INDEX (k), INDEX (k+kk-1))) ;
	    if (Front_parent [frontid] == EMPTY)
	    {
		PRINTF4 (("parent: (none)\n")) ;
	    }
	    else
	    {
		PRINTF4 (("parent: "ID"\n", INDEX (Front_parent [frontid]))) ;
	    }
	    done = (frontid == 20 && frontid < nfr-1 && prl == 4) ;
	    if (done)
	    {
		PRINTF4 (("\t...\n")) ;
		break ;
	    }
	    k += kk ;
	}
	if (done)
	{
	    break ;
	}
    }

    W = (Int *) UMF_malloc (n, sizeof (Int)) ;
    if (!W)
    {
	PRINTF (("ERROR: out of memory to check Symbolic object\n\n")) ;
	return (UMFPACK_ERROR_out_of_memory) ;
    }

    status = UMF_report_perm ("Initial column permutation, Qtree",
	n, Symbolic->Cperm_init, W, prl, 0) ;

    (void) UMF_free ((void *) W) ;

    if (status != UMFPACK_OK)
    {
	return (UMFPACK_ERROR_invalid_Symbolic_object) ;
    }

    PRINTF4 (("    ")) ;
    if (name)
    {
	PRINTF4 (("%s: ", name)) ;
    }
    PRINTF4 (("Symbolic object:  ")) ;
    PRINTF (("OK\n\n")) ;
    return (UMFPACK_OK) ;
}

