Blender  V2.59
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