/*!\page LICENSE LICENSE
 
Copyright (C) 2003 by the Board of Trustees of Massachusetts Institute of
Technology, hereafter designated as the Copyright Owners.
 
License to use, copy, modify, sell and/or distribute this software and
its documentation for any purpose is hereby granted without royalty,
subject to the following terms and conditions:
 
1.  The above copyright notice and this permission notice must
appear in all copies of the software and related documentation.
 
2.  The names of the Copyright Owners may not be used in advertising or
publicity pertaining to distribution of the software without the specific,
prior written permission of the Copyright Owners.
 
3.  THE SOFTWARE IS PROVIDED "AS-IS" AND THE COPYRIGHT OWNERS MAKE NO
REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, BY WAY OF EXAMPLE, BUT NOT
LIMITATION.  THE COPYRIGHT OWNERS MAKE NO REPRESENTATIONS OR WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE
SOFTWARE WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS TRADEMARKS OR OTHER
RIGHTS. THE COPYRIGHT OWNERS SHALL NOT BE LIABLE FOR ANY LIABILITY OR DAMAGES
WITH RESPECT TO ANY CLAIM BY LICENSEE OR ANY THIRD PARTY ON ACCOUNT OF, OR
ARISING FROM THE LICENSE, OR ANY SUBLICENSE OR USE OF THE SOFTWARE OR ANY
SERVICE OR SUPPORT.
 
LICENSEE shall indemnify, hold harmless and defend the Copyright Owners and
their trustees, officers, employees, students and agents against any and all
claims arising out of the exercise of any rights under this Agreement,
including, without limiting the generality of the foregoing, against any
damages, losses or liabilities whatsoever with respect to death or injury to
person or damage to property arising from or out of the possession, use, or
operation of Software or Licensed Program(s) by LICENSEE or its customers.
 
*//*
 *  EXPORTS for sparse matrix routines.
 *
 *  Author:                     Advising professor:
 *      Kenneth S. Kundert          Alberto Sangiovanni-Vincentelli
 *      UC Berkeley
 *
 *  This file contains definitions that are useful to the calling
 *  program.  In particular, this file contains error keyword
 *  definitions, some macro functions that are used to quickly enter
 *  data into the matrix and the type definition of a data structure
 *  that acts as a template for entering admittances into the matrix.
 *  Also included is the type definitions for the various functions
 *  available to the user.
 */


/*
 *  Revision and copyright information.
 *
 *  Copyright (c) 1985,86,87,88
 *  by Kenneth S. Kundert and the University of California.
 *
 *  Permission to use, copy, modify, and distribute this software and
 *  its documentation for any purpose and without fee is hereby granted,
 *  provided that the copyright notices appear in all copies and
 *  supporting documentation and that the authors and the University of
 *  California are properly credited.  The authors and the University of
 *  California make no representations as to the suitability of this
 *  software for any purpose.  It is provided `as is', without express
 *  or implied warranty.
 *
 *  $Date: 88/06/24 05:03:01 $
 *  $Revision: 1.1 $
 */




#ifndef  spOKAY

/*
 *  IMPORTS
 *
 *  >>> Import descriptions:
 *  spConfig.h
 *      Macros that customize the sparse matrix routines.
 */

#include "spConfig.h"






/*
 *  ERROR KEYWORDS
 *
 *  The actual numbers used in the error codes are not sacred, they can be
 *  changed under the condition that the codes for the nonfatal errors are
 *  less than the code for spFATAL and similarly the codes for the fatal
 *  errors are greater than that for spFATAL.
 *
 *  >>> Error descriptions:
 *  spOKAY
 *      No error has occurred.
 *  spSMALL_PIVOT
 *      When reordering the matrix, no element was found which satisfies the
 *      threshold criteria.  The largest element in the matrix was chosen
 *      as pivot.  Non-fatal.
 *  spZERO_DIAG
 *      Fatal error.  A zero was encountered on the diagonal the matrix.  This
 *      does not necessarily imply that the matrix is singular.  When this
 *      error occurs, the matrix should be reconstructed and factored using
 *      spOrderAndFactor().  In spCOMPATIBILITY mode, spZERO_DIAG is
 *      indistinguishable from spSINGULAR.
 *  spSINGULAR
 *      Fatal error.  Matrix is singular, so no unique solution exists.
 *  spNO_MEMORY
 *      Fatal error.  Indicates that not enough memory is available to handle
 *      the matrix.
 *  spPANIC
 *      Fatal error indicating that the routines are not prepared to
 *      handle the matrix that has been requested.  This may occur when
 *      the matrix is specified to be real and the routines are not
 *      compiled for real matrices, or when the matrix is specified to
 *      be complex and the routines are not compiled to handle complex
 *      matrices.
 *  spFATAL
 *      Not an error flag, but rather the dividing line between fatal errors
 *      and warnings.
 */

#include "../include/SPerror.h"  /* Spice error definitions. */

/* Begin error macros. */
#define  spOKAY                 OK
#define  spSMALL_PIVOT          OK
#define  spZERO_DIAG            E_SINGULAR
#define  spSINGULAR             E_SINGULAR
#define  spNO_MEMORY            E_NOMEM
#define  spPANIC                E_BADMATRIX

#define  spFATAL                E_BADMATRIX


#if spCOMPATIBILITY
#define  NO_ERROR               spOKAY
#define  UNDER_FLOW             spOKAY
#define  OVER_FLOW              spOKAY
#define  ILL_CONDITIONED        spSMALL_PIVOT
#define  SINGULAR               spSINGULAR
#define  NO_MEMORY              spNO_MEMORY
#define  RANGE                  spPANIC

#define  FATAL                  spFATAL

#undef   spZERO_DIAG
#define  spZERO_DIAG            spSINGULAR
#endif /* spCOMPATIBILITY */





/*
 *  KEYWORD DEFINITIONS
 *
 *  Here we define what precision arithmetic Sparse will use.  Double
 *  precision is suggested as being most appropriate for circuit
 *  simulation and for C.  However, it is possible to change spREAL
 *  to a float for single precision arithmetic.  Note that in C, single
 *  precision arithmetic is often slower than double precision.  Sparse
 *  internally refers to spREALs as RealNumbers.
 *
 *  Some C compilers, notably the old VMS compiler, do not handle the keyword
 *  "void" correctly.  If this is true for your compiler, remove the
 *  comment delimiters from the redefinition of void to int below.
 */

#define  spREAL double
/* #define  void    int   */

#if spCOMPATIBILITY
#define SPARSE_REAL     spREAL
#endif



/*
 *  PARTITION TYPES
 *
 *  When factoring a previously ordered matrix using spFactor(), Sparse
 *  operates on a row-at-a-time basis.  For speed, on each step, the row
 *  being updated is copied into a full vector and the operations are
 *  performed on that vector.  This can be done one of two ways, either
 *  using direct addressing or indirect addressing.  Direct addressing
 *  is fastest when the matrix is relatively dense and indirect addressing
 *  is quite sparse.  The user can select which partitioning mode is used.
 *  The following keywords are passed to spPartition() and indicate that
 *  Sparse should use only direct addressing, only indirect addressing, or
 *  that it should choose the best mode on a row-by-row basis.  The time
 *  required to choose a partition is of the same order of the cost to factor
 *  the matrix.
 *
 *  If you plan to factor a large number of matrices with the same structure,
 *  it is best to let Sparse choose the partition.  Otherwise, you should
 *  choose the partition based on the predicted density of the matrix.
 */

/* Begin partition keywords. */

#define spDEFAULT_PARTITION     0
#define spDIRECT_PARTITION      1
#define spINDIRECT_PARTITION    2
#define spAUTO_PARTITION        3





/*
 *  MACRO FUNCTION DEFINITIONS
 *
 *  >>> Macro descriptions:
 *  spADD_REAL_ELEMENT
 *      Macro function that adds data to a real element in the matrix by a
 *      pointer.
 *  spADD_IMAG_ELEMENT
 *      Macro function that adds data to a imaginary element in the matrix by
 *      a pointer.
 *  spADD_COMPLEX_ELEMENT
 *      Macro function that adds data to a complex element in the matrix by a
 *      pointer.
 *  spADD_REAL_QUAD
 *      Macro function that adds data to each of the four real matrix elements
 *      specified by the given template.
 *  spADD_IMAG_QUAD
 *      Macro function that adds data to each of the four imaginary matrix
 *      elements specified by the given template.
 *  spADD_COMPLEX_QUAD
 *      Macro function that adds data to each of the four complex matrix
 *      elements specified by the given template.
 */

/* Begin Macros. */
#define  spADD_REAL_ELEMENT(element,real)       *(element) += real

#define  spADD_IMAG_ELEMENT(element,imag)       *(element+1) += imag

#define  spADD_COMPLEX_ELEMENT(element,real,imag)       \
{   *(element) += real;                                 \
    *(element+1) += imag;                               \
}

#define  spADD_REAL_QUAD(template,real)         \
{   *((template).Element1) += real;             \
    *((template).Element2) += real;             \
    *((template).Element3Negated) -= real;      \
    *((template).Element4Negated) -= real;      \
}

#define  spADD_IMAG_QUAD(template,imag)         \
{   *((template).Element1+1) += imag;           \
    *((template).Element2+1) += imag;           \
    *((template).Element3Negated+1) -= imag;    \
    *((template).Element4Negated+1) -= imag;    \
}

#define  spADD_COMPLEX_QUAD(template,real,imag) \
{   *((template).Element1) += real;             \
    *((template).Element2) += real;             \
    *((template).Element3Negated) -= real;      \
    *((template).Element4Negated) -= real;      \
    *((template).Element1+1) += imag;           \
    *((template).Element2+1) += imag;           \
    *((template).Element3Negated+1) -= imag;    \
    *((template).Element4Negated+1) -= imag;    \
}

#if spCOMPATIBILITY
#define  ADD_REAL_ELEMENT_TO_MATRIX             spADD_REAL_ELEMENT
#define  ADD_IMAG_ELEMENT_TO_MATRIX             spADD_IMAG_ELEMENT
#define  ADD_COMPLEX_ELEMENT_TO_MATRIX          spADD_COMPLEX_ELEMENT
#define  ADD_REAL_QUAD_ELEMENT_TO_MATRIX        spADD_REAL_ELEMENT
#define  ADD_IMAG_QUAD_ELEMENT_TO_MATRIX        spADD_IMAG_ELEMENT
#define  ADD_COMPLEX_QUAD_ELEMENT_TO_MATRIX     spADD_COMPLEX_ELEMENT
#endif






/*
 *   TYPE DEFINITION FOR COMPONENT TEMPLATE
 *
 *   This data structure is used to hold pointers to four related elements in
 *   matrix.  It is used in conjunction with the routines
 *       spGetAdmittance
 *       spGetQuad
 *       spGetOnes
 *   These routines stuff the structure which is later used by the spADD_QUAD
 *   macro functions above.  It is also possible for the user to collect four
 *   pointers returned by spGetElement and stuff them into the template.
 *   The spADD_QUAD routines stuff data into the matrix in locations specified
 *   by Element1 and Element2 without changing the data.  The data is negated
 *   before being placed in Element3 and Element4.
 */

#if spCOMPATIBILITY
#define spTemplate TemplateStruct
#endif

/* Begin `spTemplate'. */
struct  spTemplate
{   spREAL    *Element1       ;
    spREAL    *Element2       ;
    spREAL    *Element3Negated;
    spREAL    *Element4Negated;
};





/*
 *   FUNCTION TYPE DEFINITIONS
 *
 *   The type of every user accessible function is declared here.
 */

/* Begin function declarations. */

#ifdef __STDC__

/* For compilers that understand function prototypes. */

extern  void     spClear( char* );
extern  spREAL   spCondition( char*, spREAL, int* );
extern  char    *spCreate( int, int, int* );
extern  void     spDeleteRowAndCol( char*, int, int );
extern  void     spDestroy( char* );
extern  int      spElementCount( char* );
extern  int      spError( char* );
extern  int      spFactor( char* );
extern  int      spFileMatrix( char*, char*, char*, int, int, int );
extern  int      spFileStats( char*, char*, char* );
extern  int      spFillinCount( char* );
extern  int      spGetAdmittance( char*, int, int, struct spTemplate* );
extern  spREAL  *spGetElement( char*, int, int );
extern  char    *spGetInitInfo( spREAL* );
extern  int      spGetOnes( char*, int, int, int, struct spTemplate* );
extern  int      spGetQuad( char*, int, int, int, int, struct spTemplate* );
extern  int      spGetSize( char*, int );
extern  int      spInitialize( char*, int (*)() );
extern  void     spInstallInitInfo( spREAL*, char* );
extern  spREAL   spLargestElement( char* );
extern  void     spMNA_Preorder( char* );
extern  spREAL   spNorm( char* );
extern  int      spOrderAndFactor( char*, spREAL[], spREAL, spREAL, int );
extern  void     spPartition( char*, int );
extern  void     spPrint( char*, int, int, int );
extern  spREAL   spPseudoCondition( char* );
extern  spREAL   spRoundoff( char*, spREAL );
extern  void     spScale( char*, spREAL[], spREAL[] );
extern  void     spSetComplex( char* );
extern  void     spSetReal( char* );
extern  void     spStripFills( char* );
extern  void     spWhereSingular( char*, int*, int* );

/* Functions with argument lists that are dependent on options. */

#if spCOMPLEX
extern  void     spDeterminant ( char*, int*, spREAL*, spREAL* );
#else /* NOT spCOMPLEX */
extern  void     spDeterminant ( char*, int*, spREAL* );
#endif /* NOT spCOMPLEX */
#if spCOMPLEX && spSEPARATED_COMPLEX_VECTORS
extern  int      spFileVector( char*, char* , spREAL[], spREAL[]);
extern  void     spMultiply( char*, spREAL[], spREAL[], spREAL[], spREAL[] );
extern  void     spMultTransposed(char*,spREAL[],spREAL[],spREAL[],spREAL[]);
extern  void     spSolve( char*, spREAL[], spREAL[], spREAL[], spREAL[] );
extern  void     spSolveTransposed(char*,spREAL[],spREAL[],spREAL[],spREAL[]);
#else /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */
extern  int      spFileVector( char*, char* , spREAL[] );
extern  void     spMultiply( char*, spREAL[], spREAL[] );
extern  void     spMultTransposed( char*, spREAL[], spREAL[] );
extern  void     spSolve( char*, spREAL[], spREAL[] );
extern  void     spSolveTransposed( char*, spREAL[], spREAL[] );
#endif /* NOT (spCOMPLEX && spSEPARATED_COMPLEX_VECTORS) */

#else /* NOT defined(__STDC__) */

/* For compilers that do not understand function prototypes. */

extern  void     spClear();
extern  spREAL   spCondition();
extern  char    *spCreate();
extern  void     spDeleteRowAndCol();
extern  void     spDestroy();
extern  void     spDeterminant ();
extern  int      spElementCount();
extern  int      spError();
extern  int      spFactor();
extern  int      spFileMatrix();
extern  int      spFileStats();
extern  int      spFileVector();
extern  int      spFillinCount();
extern  int      spGetAdmittance();
extern  spREAL  *spGetElement();
extern  char    *spGetInitInfo();
extern  int      spGetOnes();
extern  int      spGetQuad();
extern  int      spGetSize();
extern  int      spInitialize();
extern  void     spInstallInitInfo();
extern  spREAL   spLargestElement();
extern  void     spMNA_Preorder();
extern  void     spMultiply();
extern  void     spMultTransposed();
extern  spREAL   spNorm();
extern  int      spOrderAndFactor();
extern  void     spPartition();
extern  void     spPrint();
extern  spREAL   spPseudoCondition();
extern  spREAL   spRoundoff();
extern  void     spScale();
extern  void     spSetComplex();
extern  void     spSetReal();
extern  void     spSolve();
extern  void     spSolveTransposed();
extern  void     spStripFills();
extern  void     spWhereSingular();
#endif /* defined(__STDC__) */

#if spCOMPATIBILITY
extern  char    *AllocateMatrix();
extern  spREAL  *AddElementToMatrix();
extern  void     AddRealElementToMatrix();
extern  void     AddImagElementToMatrix();
extern  void     AddComplexElementToMatrix();
extern  void     AddAdmittanceToMatrix();
extern  void     AddOnesToMatrix();
extern  void     AddQuadToMatrix();
extern  void     AddRealQuadElementToMatrix();
extern  void     AddImagQuadElementToMatrix();
extern  void     AddComplexQuadElementToMatrix();
extern  void     CleanMatrix();
extern  void     ClearMatrix();
extern  int      ClearMatrixError();
extern  void     DeallocateMatrix();
extern  void     DeleteRowAndColFromMatrix();
extern  void     Determinant();
extern  int      DecomposeMatrix();
extern  int      GetMatrixSize();
extern  int      MatrixElementCount();
extern  int      MatrixFillinCount();
extern  void     MatrixMultiply();
extern  spREAL   MatrixRoundoffError();
extern  int      MatrixError();
extern  int      OrderAndDecomposeMatrix();
extern  void     OutputMatrixToFile();
extern  void     OutputStatisticsToFile();
extern  void     OutputVectorToFile();
extern  void     PreorderForModifiedNodal();
extern  void     PrintMatrix();
extern  void     SetMatrixComplex();
extern  void     SetMatrixReal();
extern  void     SolveMatrix();
extern  void     SolveTransposedMatrix();
extern  void     ScaleMatrix();
#endif /* spCOMPATIBILITY */

#endif  /* spOKAY */
