Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_rcond.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Cholesky/cholmod_rcond =============================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Cholesky Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Cholesky Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* Return a rough estimate of the reciprocal of the condition number:
14  * the minimum entry on the diagonal of L (or absolute entry of D for an LDL'
15  * factorization) divided by the maximum entry (squared for LL'). L can be
16  * real, complex, or zomplex. Returns -1 on error, 0 if the matrix is singular
17  * or has a zero entry on the diagonal of L, 1 if the matrix is 0-by-0, or
18  * min(diag(L))/max(diag(L)) otherwise. Never returns NaN; if L has a NaN on
19  * the diagonal it returns zero instead.
20  *
21  * For an LL' factorization, (min(diag(L))/max(diag(L)))^2 is returned.
22  * For an LDL' factorization, (min(diag(D))/max(diag(D))) is returned.
23  */
24 
25 #ifndef NCHOLESKY
26 
29 
30 /* ========================================================================== */
31 /* === LMINMAX ============================================================== */
32 /* ========================================================================== */
33 
34 /* Update lmin and lmax for one entry L(j,j) */
35 
36 #define FIRST_LMINMAX(Ljj,lmin,lmax) \
37 { \
38  double ljj = Ljj ; \
39  if (IS_NAN (ljj)) \
40  { \
41  return (0) ; \
42  } \
43  lmin = ljj ; \
44  lmax = ljj ; \
45 }
46 
47 #define LMINMAX(Ljj,lmin,lmax) \
48 { \
49  double ljj = Ljj ; \
50  if (IS_NAN (ljj)) \
51  { \
52  return (0) ; \
53  } \
54  if (ljj < lmin) \
55  { \
56  lmin = ljj ; \
57  } \
58  else if (ljj > lmax) \
59  { \
60  lmax = ljj ; \
61  } \
62 }
63 
64 /* ========================================================================== */
65 /* === cholmod_rcond ======================================================== */
66 /* ========================================================================== */
67 
68 double CHOLMOD(rcond) /* return min(diag(L)) / max(diag(L)) */
69 (
70  /* ---- input ---- */
71  cholmod_factor *L,
72  /* --------------- */
73  cholmod_common *Common
74 )
75 {
76  double lmin, lmax, rcond ;
77  double *Lx ;
78  Int *Lpi, *Lpx, *Super, *Lp ;
79  Int n, e, nsuper, s, k1, k2, psi, psend, psx, nsrow, nscol, jj, j ;
80 
81  /* ---------------------------------------------------------------------- */
82  /* check inputs */
83  /* ---------------------------------------------------------------------- */
84 
86  RETURN_IF_NULL (L, EMPTY) ;
88  Common->status = CHOLMOD_OK ;
89 
90  /* ---------------------------------------------------------------------- */
91  /* get inputs */
92  /* ---------------------------------------------------------------------- */
93 
94  n = L->n ;
95  if (n == 0)
96  {
97  return (1) ;
98  }
99  if (L->minor < L->n)
100  {
101  return (0) ;
102  }
103 
104  e = (L->xtype == CHOLMOD_COMPLEX) ? 2 : 1 ;
105 
106  if (L->is_super)
107  {
108  /* L is supernodal */
109  nsuper = L->nsuper ; /* number of supernodes in L */
110  Lpi = L->pi ; /* column pointers for integer pattern */
111  Lpx = L->px ; /* column pointers for numeric values */
112  Super = L->super ; /* supernode sizes */
113  Lx = L->x ; /* numeric values */
114  FIRST_LMINMAX (Lx [0], lmin, lmax) ; /* first diagonal entry of L */
115  for (s = 0 ; s < nsuper ; s++)
116  {
117  k1 = Super [s] ; /* first column in supernode s */
118  k2 = Super [s+1] ; /* last column in supernode is k2-1 */
119  psi = Lpi [s] ; /* first row index is L->s [psi] */
120  psend = Lpi [s+1] ; /* last row index is L->s [psend-1] */
121  psx = Lpx [s] ; /* first numeric entry is Lx [psx] */
122  nsrow = psend - psi ; /* supernode is nsrow-by-nscol */
123  nscol = k2 - k1 ;
124  for (jj = 0 ; jj < nscol ; jj++)
125  {
126  LMINMAX (Lx [e * (psx + jj + jj*nsrow)], lmin, lmax) ;
127  }
128  }
129  }
130  else
131  {
132  /* L is simplicial */
133  Lp = L->p ;
134  Lx = L->x ;
135  if (L->is_ll)
136  {
137  /* LL' factorization */
138  FIRST_LMINMAX (Lx [Lp [0]], lmin, lmax) ;
139  for (j = 1 ; j < n ; j++)
140  {
141  LMINMAX (Lx [e * Lp [j]], lmin, lmax) ;
142  }
143  }
144  else
145  {
146  /* LDL' factorization, the diagonal might be negative */
147  FIRST_LMINMAX (fabs (Lx [Lp [0]]), lmin, lmax) ;
148  for (j = 1 ; j < n ; j++)
149  {
150  LMINMAX (fabs (Lx [e * Lp [j]]), lmin, lmax) ;
151  }
152  }
153  }
154  rcond = lmin / lmax ;
155  if (L->is_ll)
156  {
157  rcond = rcond*rcond ;
158  }
159  return (rcond) ;
160 }
161 #endif
#define EMPTY
#define Int
#define CHOLMOD_COMPLEX
#define RETURN_IF_NULL_COMMON(result)
#define CHOLMOD_REAL
#define LMINMAX(Ljj, lmin, lmax)
#define FIRST_LMINMAX(Ljj, lmin, lmax)
double CHOLMOD(rcond)
#define CHOLMOD_OK
#define RETURN_IF_NULL(A, result)
int n
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX