Mercurial > forge
comparison main/sparse/SuperLU/SRC/dpivotL.c @ 0:6b33357c7561 octave-forge
Initial revision
author | pkienzle |
---|---|
date | Wed, 10 Oct 2001 19:54:49 +0000 |
parents | |
children | 785c84b30f53 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6b33357c7561 |
---|---|
1 | |
2 | |
3 /* | |
4 * -- SuperLU routine (version 2.0) -- | |
5 * Univ. of California Berkeley, Xerox Palo Alto Research Center, | |
6 * and Lawrence Berkeley National Lab. | |
7 * November 15, 1997 | |
8 * | |
9 */ | |
10 /* | |
11 Copyright (c) 1994 by Xerox Corporation. All rights reserved. | |
12 | |
13 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY | |
14 EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. | |
15 | |
16 Permission is hereby granted to use or copy this program for any | |
17 purpose, provided the above notices are retained on all copies. | |
18 Permission to modify the code and to distribute modified code is | |
19 granted, provided the above notices are retained, and a notice that | |
20 the code was modified is included with the above copyright notice. | |
21 */ | |
22 | |
23 #include <math.h> | |
24 #include <stdlib.h> | |
25 #include "dsp_defs.h" | |
26 #include "util.h" | |
27 | |
28 #undef DEBUG | |
29 | |
30 int | |
31 dpivotL( | |
32 const int jcol, /* in */ | |
33 const double u, /* in - diagonal pivoting threshold */ | |
34 int *usepr, /* re-use the pivot sequence given by perm_r/iperm_r */ | |
35 int *perm_r, /* may be modified */ | |
36 int *iperm_r, /* in - inverse of perm_r */ | |
37 int *iperm_c, /* in - used to find diagonal of Pc*A*Pc' */ | |
38 int *pivrow, /* out */ | |
39 GlobalLU_t *Glu /* modified - global LU data structures */ | |
40 ) | |
41 { | |
42 /* | |
43 * Purpose | |
44 * ======= | |
45 * Performs the numerical pivoting on the current column of L, | |
46 * and the CDIV operation. | |
47 * | |
48 * Pivot policy: | |
49 * (1) Compute thresh = u * max_(i>=j) abs(A_ij); | |
50 * (2) IF user specifies pivot row k and abs(A_kj) >= thresh THEN | |
51 * pivot row = k; | |
52 * ELSE IF abs(A_jj) >= thresh THEN | |
53 * pivot row = j; | |
54 * ELSE | |
55 * pivot row = m; | |
56 * | |
57 * Note: If you absolutely want to use a given pivot order, then set u=0.0. | |
58 * | |
59 * Return value: 0 success; | |
60 * i > 0 U(i,i) is exactly zero. | |
61 * | |
62 */ | |
63 int fsupc; /* first column in the supernode */ | |
64 int nsupc; /* no of columns in the supernode */ | |
65 int nsupr; /* no of rows in the supernode */ | |
66 int lptr; /* points to the starting subscript of the supernode */ | |
67 int pivptr, old_pivptr, diag, diagind; | |
68 double pivmax, rtemp, thresh; | |
69 double temp; | |
70 double *lu_sup_ptr; | |
71 double *lu_col_ptr; | |
72 int *lsub_ptr; | |
73 int isub, icol, k, itemp; | |
74 int *lsub, *xlsub; | |
75 double *lusup; | |
76 int *xlusup; | |
77 extern SuperLUStat_t SuperLUStat; | |
78 flops_t *ops = SuperLUStat.ops; | |
79 | |
80 /* Initialize pointers */ | |
81 lsub = Glu->lsub; | |
82 xlsub = Glu->xlsub; | |
83 lusup = Glu->lusup; | |
84 xlusup = Glu->xlusup; | |
85 fsupc = (Glu->xsup)[(Glu->supno)[jcol]]; | |
86 nsupc = jcol - fsupc; /* excluding jcol; nsupc >= 0 */ | |
87 lptr = xlsub[fsupc]; | |
88 nsupr = xlsub[fsupc+1] - lptr; | |
89 lu_sup_ptr = &lusup[xlusup[fsupc]]; /* start of the current supernode */ | |
90 lu_col_ptr = &lusup[xlusup[jcol]]; /* start of jcol in the supernode */ | |
91 lsub_ptr = &lsub[lptr]; /* start of row indices of the supernode */ | |
92 | |
93 #ifdef DEBUG | |
94 if ( jcol == MIN_COL ) { | |
95 printf("Before cdiv: col %d\n", jcol); | |
96 for (k = nsupc; k < nsupr; k++) | |
97 printf(" lu[%d] %f\n", lsub_ptr[k], lu_col_ptr[k]); | |
98 } | |
99 #endif | |
100 | |
101 /* Determine the largest abs numerical value for partial pivoting; | |
102 Also search for user-specified pivot, and diagonal element. */ | |
103 if ( *usepr ) *pivrow = iperm_r[jcol]; | |
104 diagind = iperm_c[jcol]; | |
105 pivmax = 0.0; | |
106 pivptr = nsupc; | |
107 diag = EMPTY; | |
108 old_pivptr = nsupc; | |
109 for (isub = nsupc; isub < nsupr; ++isub) { | |
110 rtemp = fabs (lu_col_ptr[isub]); | |
111 if ( rtemp > pivmax ) { | |
112 pivmax = rtemp; | |
113 pivptr = isub; | |
114 } | |
115 if ( *usepr && lsub_ptr[isub] == *pivrow ) old_pivptr = isub; | |
116 if ( lsub_ptr[isub] == diagind ) diag = isub; | |
117 } | |
118 | |
119 /* Test for singularity */ | |
120 if ( pivmax == 0.0 ) { | |
121 *pivrow = lsub_ptr[pivptr]; | |
122 perm_r[*pivrow] = jcol; | |
123 *usepr = 0; | |
124 return (jcol+1); | |
125 } | |
126 | |
127 thresh = u * pivmax; | |
128 | |
129 /* Choose appropriate pivotal element by our policy. */ | |
130 if ( *usepr ) { | |
131 rtemp = fabs (lu_col_ptr[old_pivptr]); | |
132 if ( rtemp != 0.0 && rtemp >= thresh ) | |
133 pivptr = old_pivptr; | |
134 else | |
135 *usepr = 0; | |
136 } | |
137 if ( *usepr == 0 ) { | |
138 /* Use diagonal pivot? */ | |
139 if ( diag >= 0 ) { /* diagonal exists */ | |
140 rtemp = fabs (lu_col_ptr[diag]); | |
141 if ( rtemp != 0.0 && rtemp >= thresh ) pivptr = diag; | |
142 } | |
143 *pivrow = lsub_ptr[pivptr]; | |
144 } | |
145 | |
146 /* Record pivot row */ | |
147 perm_r[*pivrow] = jcol; | |
148 | |
149 /* Interchange row subscripts */ | |
150 if ( pivptr != nsupc ) { | |
151 itemp = lsub_ptr[pivptr]; | |
152 lsub_ptr[pivptr] = lsub_ptr[nsupc]; | |
153 lsub_ptr[nsupc] = itemp; | |
154 | |
155 /* Interchange numerical values as well, for the whole snode, such | |
156 * that L is indexed the same way as A. | |
157 */ | |
158 for (icol = 0; icol <= nsupc; icol++) { | |
159 itemp = pivptr + icol * nsupr; | |
160 temp = lu_sup_ptr[itemp]; | |
161 lu_sup_ptr[itemp] = lu_sup_ptr[nsupc + icol*nsupr]; | |
162 lu_sup_ptr[nsupc + icol*nsupr] = temp; | |
163 } | |
164 } /* if */ | |
165 | |
166 /* cdiv operation */ | |
167 ops[FACT] += nsupr - nsupc; | |
168 | |
169 temp = 1.0 / lu_col_ptr[nsupc]; | |
170 for (k = nsupc+1; k < nsupr; k++) | |
171 lu_col_ptr[k] *= temp; | |
172 | |
173 return 0; | |
174 } | |
175 |