Blender V2.61 - r43446
|
00001 00005 /* 00006 * -- SuperLU routine (version 3.0) -- 00007 * Univ. of California Berkeley, Xerox Palo Alto Research Center, 00008 * and Lawrence Berkeley National Lab. 00009 * October 15, 2003 00010 * 00011 */ 00012 /* 00013 Copyright (c) 1994 by Xerox Corporation. All rights reserved. 00014 00015 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY 00016 EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 00017 00018 Permission is hereby granted to use or copy this program for any 00019 purpose, provided the above notices are retained on all copies. 00020 Permission to modify the code and to distribute modified code is 00021 granted, provided the above notices are retained, and a notice that 00022 the code was modified is included with the above copyright notice. 00023 */ 00024 00025 #include <math.h> 00026 #include <stdlib.h> 00027 #include "ssp_defs.h" 00028 00029 #undef DEBUG 00030 00031 int 00032 spivotL( 00033 const int jcol, /* in */ 00034 const float u, /* in - diagonal pivoting threshold */ 00035 int *usepr, /* re-use the pivot sequence given by perm_r/iperm_r */ 00036 int *perm_r, /* may be modified */ 00037 int *iperm_r, /* in - inverse of perm_r */ 00038 int *iperm_c, /* in - used to find diagonal of Pc*A*Pc' */ 00039 int *pivrow, /* out */ 00040 GlobalLU_t *Glu, /* modified - global LU data structures */ 00041 SuperLUStat_t *stat /* output */ 00042 ) 00043 { 00044 /* 00045 * Purpose 00046 * ======= 00047 * Performs the numerical pivoting on the current column of L, 00048 * and the CDIV operation. 00049 * 00050 * Pivot policy: 00051 * (1) Compute thresh = u * max_(i>=j) abs(A_ij); 00052 * (2) IF user specifies pivot row k and abs(A_kj) >= thresh THEN 00053 * pivot row = k; 00054 * ELSE IF abs(A_jj) >= thresh THEN 00055 * pivot row = j; 00056 * ELSE 00057 * pivot row = m; 00058 * 00059 * Note: If you absolutely want to use a given pivot order, then set u=0.0. 00060 * 00061 * Return value: 0 success; 00062 * i > 0 U(i,i) is exactly zero. 00063 * 00064 */ 00065 int fsupc; /* first column in the supernode */ 00066 int nsupc; /* no of columns in the supernode */ 00067 int nsupr; /* no of rows in the supernode */ 00068 int lptr; /* points to the starting subscript of the supernode */ 00069 int pivptr, old_pivptr, diag, diagind; 00070 float pivmax, rtemp, thresh; 00071 float temp; 00072 float *lu_sup_ptr; 00073 float *lu_col_ptr; 00074 int *lsub_ptr; 00075 int isub, icol, k, itemp; 00076 int *lsub, *xlsub; 00077 float *lusup; 00078 int *xlusup; 00079 flops_t *ops = stat->ops; 00080 00081 /* Initialize pointers */ 00082 lsub = Glu->lsub; 00083 xlsub = Glu->xlsub; 00084 lusup = Glu->lusup; 00085 xlusup = Glu->xlusup; 00086 fsupc = (Glu->xsup)[(Glu->supno)[jcol]]; 00087 nsupc = jcol - fsupc; /* excluding jcol; nsupc >= 0 */ 00088 lptr = xlsub[fsupc]; 00089 nsupr = xlsub[fsupc+1] - lptr; 00090 lu_sup_ptr = &lusup[xlusup[fsupc]]; /* start of the current supernode */ 00091 lu_col_ptr = &lusup[xlusup[jcol]]; /* start of jcol in the supernode */ 00092 lsub_ptr = &lsub[lptr]; /* start of row indices of the supernode */ 00093 00094 #ifdef DEBUG 00095 if ( jcol == MIN_COL ) { 00096 printf("Before cdiv: col %d\n", jcol); 00097 for (k = nsupc; k < nsupr; k++) 00098 printf(" lu[%d] %f\n", lsub_ptr[k], lu_col_ptr[k]); 00099 } 00100 #endif 00101 00102 /* Determine the largest abs numerical value for partial pivoting; 00103 Also search for user-specified pivot, and diagonal element. */ 00104 if ( *usepr ) *pivrow = iperm_r[jcol]; 00105 diagind = iperm_c[jcol]; 00106 pivmax = 0.0; 00107 pivptr = nsupc; 00108 diag = EMPTY; 00109 old_pivptr = nsupc; 00110 for (isub = nsupc; isub < nsupr; ++isub) { 00111 rtemp = fabs (lu_col_ptr[isub]); 00112 if ( rtemp > pivmax ) { 00113 pivmax = rtemp; 00114 pivptr = isub; 00115 } 00116 if ( *usepr && lsub_ptr[isub] == *pivrow ) old_pivptr = isub; 00117 if ( lsub_ptr[isub] == diagind ) diag = isub; 00118 } 00119 00120 /* Test for singularity */ 00121 if ( pivmax == 0.0 ) { 00122 *pivrow = lsub_ptr[pivptr]; 00123 perm_r[*pivrow] = jcol; 00124 *usepr = 0; 00125 return (jcol+1); 00126 } 00127 00128 thresh = u * pivmax; 00129 00130 /* Choose appropriate pivotal element by our policy. */ 00131 if ( *usepr ) { 00132 rtemp = fabs (lu_col_ptr[old_pivptr]); 00133 if ( rtemp != 0.0 && rtemp >= thresh ) 00134 pivptr = old_pivptr; 00135 else 00136 *usepr = 0; 00137 } 00138 if ( *usepr == 0 ) { 00139 /* Use diagonal pivot? */ 00140 if ( diag >= 0 ) { /* diagonal exists */ 00141 rtemp = fabs (lu_col_ptr[diag]); 00142 if ( rtemp != 0.0 && rtemp >= thresh ) pivptr = diag; 00143 } 00144 *pivrow = lsub_ptr[pivptr]; 00145 } 00146 00147 /* Record pivot row */ 00148 perm_r[*pivrow] = jcol; 00149 00150 /* Interchange row subscripts */ 00151 if ( pivptr != nsupc ) { 00152 itemp = lsub_ptr[pivptr]; 00153 lsub_ptr[pivptr] = lsub_ptr[nsupc]; 00154 lsub_ptr[nsupc] = itemp; 00155 00156 /* Interchange numerical values as well, for the whole snode, such 00157 * that L is indexed the same way as A. 00158 */ 00159 for (icol = 0; icol <= nsupc; icol++) { 00160 itemp = pivptr + icol * nsupr; 00161 temp = lu_sup_ptr[itemp]; 00162 lu_sup_ptr[itemp] = lu_sup_ptr[nsupc + icol*nsupr]; 00163 lu_sup_ptr[nsupc + icol*nsupr] = temp; 00164 } 00165 } /* if */ 00166 00167 /* cdiv operation */ 00168 ops[FACT] += nsupr - nsupc; 00169 00170 temp = 1.0 / lu_col_ptr[nsupc]; 00171 for (k = nsupc+1; k < nsupr; k++) 00172 lu_col_ptr[k] *= temp; 00173 00174 return 0; 00175 } 00176