Blender V2.61 - r43446

spivotL.c

Go to the documentation of this file.
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