398 lines
11 KiB
C++
398 lines
11 KiB
C++
// =============================================================================
|
|
// === spqr.hpp ================================================================
|
|
// =============================================================================
|
|
|
|
// Internal definitions and non-user-callable routines. This should not be
|
|
// included in the user's code.
|
|
|
|
#ifndef SPQR_INTERNAL_H
|
|
#define SPQR_INTERNAL_H
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// include files
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#include "UFconfig.h"
|
|
extern "C" {
|
|
#include "cholmod_core.h"
|
|
#include "cholmod_blas.h"
|
|
}
|
|
#include "SuiteSparseQR_definitions.h"
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <stdio.h>
|
|
#include <cstring>
|
|
|
|
#include <complex>
|
|
typedef std::complex<double> Complex ;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// debugging and printing control
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// force debugging off
|
|
#ifndef NDEBUG
|
|
#define NDEBUG
|
|
#endif
|
|
|
|
// force printing off
|
|
#ifndef NPRINT
|
|
#define NPRINT
|
|
#endif
|
|
|
|
// uncomment the following line to turn on debugging (SPQR will be slow!)
|
|
/*
|
|
#undef NDEBUG
|
|
*/
|
|
|
|
// uncomment the following line to turn on printing (LOTS of output!)
|
|
/*
|
|
#undef NPRINT
|
|
*/
|
|
|
|
// uncomment the following line to turn on expensive debugging (very slow!)
|
|
/*
|
|
#define DEBUG_EXPENSIVE
|
|
*/
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Int is defined at UF_long, from UFconfig.h
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#define Int UF_long
|
|
#define Int_max UF_long_max
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// basic macros
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
#define EMPTY (-1)
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#define IMPLIES(p,q) (!(p) || (q))
|
|
|
|
// NULL should already be defined, but ensure it is here.
|
|
#ifndef NULL
|
|
#define NULL ((void *) 0)
|
|
#endif
|
|
|
|
// column-major indexing; A[i,j] is A (INDEX (i,j,lda))
|
|
#define INDEX(i,j,lda) ((i) + ((j)*(lda)))
|
|
|
|
// FLIP is a "negation about -1", and is used to mark an integer i that is
|
|
// normally non-negative. FLIP (EMPTY) is EMPTY. FLIP of a number > EMPTY
|
|
// is negative, and FLIP of a number < EMTPY is positive. FLIP (FLIP (i)) = i
|
|
// for all integers i. UNFLIP (i) is >= EMPTY.
|
|
#define EMPTY (-1)
|
|
#define FLIP(i) (-(i)-2)
|
|
#define UNFLIP(i) (((i) < EMPTY) ? FLIP (i) : (i))
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// additional include files
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
#include "mex.h"
|
|
#endif
|
|
|
|
#define ITYPE CHOLMOD_LONG
|
|
#define DTYPE CHOLMOD_DOUBLE
|
|
#define ID UF_long_id
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#define ERROR(status,msg) \
|
|
printf ("CHOLMOD error: %s\n",msg) // Kai: disable cholmod_l_error to prevent from including tons of files
|
|
|
|
// Check a pointer and return if null. Set status to invalid, unless the
|
|
// status is already "out of memory"
|
|
#define RETURN_IF_NULL(A,result) \
|
|
{ \
|
|
if ((A) == NULL) \
|
|
{ \
|
|
if (cc->status != CHOLMOD_OUT_OF_MEMORY) \
|
|
{ \
|
|
ERROR (CHOLMOD_INVALID, NULL) ; \
|
|
} \
|
|
return (result) ; \
|
|
} \
|
|
}
|
|
|
|
// Return if Common is NULL or invalid
|
|
#define RETURN_IF_NULL_COMMON(result) \
|
|
{ \
|
|
if (cc == NULL) \
|
|
{ \
|
|
return (result) ; \
|
|
} \
|
|
if (cc->itype != ITYPE || cc->dtype != DTYPE) \
|
|
{ \
|
|
cc->status = CHOLMOD_INVALID ; \
|
|
return (result) ; \
|
|
} \
|
|
}
|
|
|
|
#define RETURN_IF_XTYPE_INVALID(A,result) \
|
|
{ \
|
|
if (A->xtype != xtype) \
|
|
{ \
|
|
ERROR (CHOLMOD_INVALID, "invalid xtype") ; \
|
|
return (result) ; \
|
|
} \
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// debugging and printing macros
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#ifndef NDEBUG
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
|
|
// #define ASSERT(e) mxAssert (e, "error: ")
|
|
|
|
extern char spqr_mx_debug_string [200] ;
|
|
char *spqr_mx_id (int line) ;
|
|
|
|
#define ASSERT(e) \
|
|
((e) ? (void) 0 : \
|
|
mexErrMsgIdAndTxt (spqr_mx_id (__LINE__), \
|
|
"assert: (" #e ") file:" __FILE__ ))
|
|
|
|
#else
|
|
|
|
#include <assert.h>
|
|
#define ASSERT(e) assert (e)
|
|
|
|
#endif
|
|
|
|
#define DEBUG(e) e
|
|
#ifdef DEBUG_EXPENSIVE
|
|
#define DEBUG2(e) e
|
|
#define ASSERT2(e) ASSERT(e)
|
|
#else
|
|
#define DEBUG2(e)
|
|
#define ASSERT2(e)
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define ASSERT(e)
|
|
#define ASSERT2(e)
|
|
#define DEBUG(e)
|
|
#define DEBUG2(e)
|
|
|
|
#endif
|
|
|
|
#ifndef NPRINT
|
|
|
|
#ifdef MATLAB_MEX_FILE
|
|
#define PR(e) mexPrintf e
|
|
#else
|
|
#define PR(e) printf e
|
|
#endif
|
|
|
|
#define PRVAL(e) spqrDebug_print (e)
|
|
|
|
#else
|
|
|
|
#define PR(e)
|
|
#define PRVAL(e)
|
|
|
|
#endif
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// For counting flops; disabled if TBB is used or timing not enabled
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#if defined(TIMING)
|
|
#define FLOP_COUNT(f) { if (cc->SPQR_grain <= 1) cc->other1 [0] += (f) ; }
|
|
#else
|
|
#define FLOP_COUNT(f)
|
|
#endif
|
|
|
|
template <typename Entry> void spqr_larftb
|
|
(
|
|
// inputs, not modified (V is modified and then restored on output)
|
|
int method, // 0,1,2,3
|
|
Int m, // C is m-by-n
|
|
Int n,
|
|
Int k, // V is v-by-k
|
|
// for methods 0 and 1, v = m,
|
|
// for methods 2 and 3, v = n
|
|
Int ldc, // leading dimension of C
|
|
Int ldv, // leading dimension of V
|
|
Entry *V, // V is v-by-k, unit lower triangular (diag not stored)
|
|
Entry *Tau, // size k, the k Householder coefficients
|
|
|
|
// input/output
|
|
Entry *C, // C is m-by-n, with leading dimension ldc
|
|
|
|
// workspace, not defined on input or output
|
|
Entry *W, // for methods 0,1: size k*k + n*k
|
|
// for methods 2,3: size k*k + m*k
|
|
cholmod_common *cc
|
|
) ;
|
|
|
|
// returns rank of F, or 0 on error
|
|
template <typename Entry> Int spqr_front
|
|
(
|
|
// input, not modified
|
|
Int m, // F is m-by-n with leading dimension m
|
|
Int n,
|
|
Int npiv, // number of pivot columns
|
|
double tol, // a column is flagged as dead if its norm is <= tol
|
|
Int ntol, // apply tol only to first ntol pivot columns
|
|
Int fchunk, // block size for compact WY Householder reflections,
|
|
// treated as 1 if fchunk <= 1
|
|
|
|
// input/output
|
|
Entry *F, // frontal matrix F of size m-by-n
|
|
Int *Stair, // size n, entries F (Stair[k]:m-1, k) are all zero,
|
|
// and remain zero on output.
|
|
char *Rdead, // size npiv; all zero on input. If k is dead,
|
|
// Rdead [k] is set to 1
|
|
|
|
// output, not defined on input
|
|
Entry *Tau, // size n, Householder coefficients
|
|
|
|
// workspace, undefined on input and output
|
|
Entry *W, // size b*(n+b), where b = min (fchunk,n,m)
|
|
|
|
// input/output
|
|
double *wscale,
|
|
double *wssq,
|
|
|
|
cholmod_common *cc // for cc->hypotenuse function
|
|
) ;
|
|
|
|
|
|
// =============================================================================
|
|
// === spqr_conj ===============================================================
|
|
// =============================================================================
|
|
|
|
inline double spqr_conj (double x)
|
|
{
|
|
return (x) ;
|
|
}
|
|
|
|
inline Complex spqr_conj (Complex x)
|
|
{
|
|
return (std::conj (x)) ;
|
|
}
|
|
|
|
// =============================================================================
|
|
// === spqr_abs ================================================================
|
|
// =============================================================================
|
|
|
|
inline double spqr_abs (double x, cholmod_common *cc) // cc is unused
|
|
{
|
|
return (fabs (x)) ;
|
|
}
|
|
|
|
inline double spqr_abs (Complex x, cholmod_common *cc)
|
|
{
|
|
return (cc->hypotenuse (x.real ( ), x.imag ( ))) ;
|
|
}
|
|
|
|
// =============================================================================
|
|
// === BLAS interface ==========================================================
|
|
// =============================================================================
|
|
|
|
// To compile SuiteSparseQR with 64-bit BLAS, use -DBLAS64. See also
|
|
// CHOLMOD/Include/cholmod_blas.h
|
|
|
|
extern "C" {
|
|
#include "cholmod_blas.h"
|
|
}
|
|
|
|
#ifdef SUN64
|
|
|
|
#define BLAS_DNRM2 dnrm2_64_
|
|
#define LAPACK_DLARF dlarf_64_
|
|
#define LAPACK_DLARFG dlarfg_64_
|
|
#define LAPACK_DLARFT dlarft_64_
|
|
#define LAPACK_DLARFB dlarfb_64_
|
|
|
|
#define BLAS_DZNRM2 dznrm2_64_
|
|
#define LAPACK_ZLARF zlarf_64_
|
|
#define LAPACK_ZLARFG zlarfg_64_
|
|
#define LAPACK_ZLARFT zlarft_64_
|
|
#define LAPACK_ZLARFB zlarfb_64_
|
|
|
|
#elif defined (BLAS_NO_UNDERSCORE)
|
|
|
|
#define BLAS_DNRM2 dnrm2
|
|
#define LAPACK_DLARF dlarf
|
|
#define LAPACK_DLARFG dlarfg
|
|
#define LAPACK_DLARFT dlarft
|
|
#define LAPACK_DLARFB dlarfb
|
|
|
|
#define BLAS_DZNRM2 dznrm2
|
|
#define LAPACK_ZLARF zlarf
|
|
#define LAPACK_ZLARFG zlarfg
|
|
#define LAPACK_ZLARFT zlarft
|
|
#define LAPACK_ZLARFB zlarfb
|
|
|
|
#else
|
|
|
|
#define BLAS_DNRM2 dnrm2_
|
|
#define LAPACK_DLARF dlarf_
|
|
#define LAPACK_DLARFG dlarfg_
|
|
#define LAPACK_DLARFT dlarft_
|
|
#define LAPACK_DLARFB dlarfb_
|
|
|
|
#define BLAS_DZNRM2 dznrm2_
|
|
#define LAPACK_ZLARF zlarf_
|
|
#define LAPACK_ZLARFG zlarfg_
|
|
#define LAPACK_ZLARFT zlarft_
|
|
#define LAPACK_ZLARFB zlarfb_
|
|
|
|
#endif
|
|
|
|
// =============================================================================
|
|
// === BLAS and LAPACK prototypes ==============================================
|
|
// =============================================================================
|
|
|
|
extern "C"
|
|
{
|
|
|
|
void LAPACK_DLARFT (char *direct, char *storev, BLAS_INT *n, BLAS_INT *k,
|
|
double *V, BLAS_INT *ldv, double *Tau, double *T, BLAS_INT *ldt) ;
|
|
|
|
void LAPACK_ZLARFT (char *direct, char *storev, BLAS_INT *n, BLAS_INT *k,
|
|
Complex *V, BLAS_INT *ldv, Complex *Tau, Complex *T, BLAS_INT *ldt) ;
|
|
|
|
void LAPACK_DLARFB (char *side, char *trans, char *direct, char *storev,
|
|
BLAS_INT *m, BLAS_INT *n, BLAS_INT *k, double *V, BLAS_INT *ldv,
|
|
double *T, BLAS_INT *ldt, double *C, BLAS_INT *ldc, double *Work,
|
|
BLAS_INT *ldwork) ;
|
|
|
|
void LAPACK_ZLARFB (char *side, char *trans, char *direct, char *storev,
|
|
BLAS_INT *m, BLAS_INT *n, BLAS_INT *k, Complex *V, BLAS_INT *ldv,
|
|
Complex *T, BLAS_INT *ldt, Complex *C, BLAS_INT *ldc, Complex *Work,
|
|
BLAS_INT *ldwork) ;
|
|
|
|
double BLAS_DNRM2 (BLAS_INT *n, double *X, BLAS_INT *incx) ;
|
|
|
|
double BLAS_DZNRM2 (BLAS_INT *n, Complex *X, BLAS_INT *incx) ;
|
|
|
|
void LAPACK_DLARFG (BLAS_INT *n, double *alpha, double *X, BLAS_INT *incx,
|
|
double *tau) ;
|
|
|
|
void LAPACK_ZLARFG (BLAS_INT *n, Complex *alpha, Complex *X, BLAS_INT *incx,
|
|
Complex *tau) ;
|
|
|
|
void LAPACK_DLARF (char *side, BLAS_INT *m, BLAS_INT *n, double *V,
|
|
BLAS_INT *incv, double *tau, double *C, BLAS_INT *ldc, double *Work) ;
|
|
|
|
void LAPACK_ZLARF (char *side, BLAS_INT *m, BLAS_INT *n, Complex *V,
|
|
BLAS_INT *incv, Complex *tau, Complex *C, BLAS_INT *ldc, Complex *Work) ;
|
|
|
|
}
|
|
|
|
#endif
|