Rev 1820 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/* ========================================================================== *//* === UMF_usolve =========================================================== *//* ========================================================================== *//* -------------------------------------------------------------------------- *//* UMFPACK Version 4.5, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, *//* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. *//* web: http://www.cise.ufl.edu/research/sparse/umfpack *//* -------------------------------------------------------------------------- *//* solves Ux = b, where U is the upper triangular factor of a matrix. *//* B is overwritten with the solution X. *//* Returns the floating point operation count */#include "umf_internal.h"GLOBAL double UMF_usolve(NumericType *Numeric,Entry X [ ], /* b on input, solution x on output */Int Pattern [ ] /* a work array of size n */){/* ---------------------------------------------------------------------- *//* local variables *//* ---------------------------------------------------------------------- */Entry xk ;Entry *xp, *D, *Uval ;Int k, deg, j, *ip, col, *Upos, *Uilen, pos,*Uip, n, ulen, up, newUchain, npiv, n1, *Ui ;/* ---------------------------------------------------------------------- *//* get parameters *//* ---------------------------------------------------------------------- */if (Numeric->n_row != Numeric->n_col) return (0.) ;n = Numeric->n_row ;npiv = Numeric->npiv ;Upos = Numeric->Upos ;Uilen = Numeric->Uilen ;Uip = Numeric->Uip ;D = Numeric->D ;n1 = Numeric->n1 ;#ifndef NDEBUGDEBUG4 (("Usolve start: npiv = "ID" n = "ID"\n", npiv, n)) ;for (j = 0 ; j < n ; j++){DEBUG4 (("Usolve start "ID": ", j)) ;EDEBUG4 (X [j]) ;DEBUG4 (("\n")) ;}#endif/* ---------------------------------------------------------------------- *//* singular case *//* ---------------------------------------------------------------------- */#ifndef NO_DIVIDE_BY_ZERO/* handle the singular part of D, up to just before the last pivot */for (k = n-1 ; k >= npiv ; k--){/* This is an *** intentional *** divide-by-zero, to get Inf or Nan,* as appropriate. It is not a bug. */ASSERT (IS_ZERO (D [k])) ;xk = X [k] ;/* X [k] = xk / D [k] ; */DIV (X [k], xk, D [k]) ;}#else/* Do not divide by zero */#endifdeg = Numeric->ulen ;if (deg > 0){/* :: make last pivot row of U (singular matrices only) :: */for (j = 0 ; j < deg ; j++){DEBUG1 (("Last row of U: j="ID"\n", j)) ;DEBUG1 (("Last row of U: Upattern[j]="ID"\n",Numeric->Upattern [j]) );Pattern [j] = Numeric->Upattern [j] ;}}/* ---------------------------------------------------------------------- *//* nonsingletons *//* ---------------------------------------------------------------------- */for (k = npiv-1 ; k >= n1 ; k--){/* ------------------------------------------------------------------ *//* use row k of U *//* ------------------------------------------------------------------ */up = Uip [k] ;ulen = Uilen [k] ;newUchain = (up < 0) ;if (newUchain){up = -up ;xp = (Entry *) (Numeric->Memory + up + UNITS (Int, ulen)) ;}else{xp = (Entry *) (Numeric->Memory + up) ;}xk = X [k] ;for (j = 0 ; j < deg ; j++){DEBUG4 ((" k "ID" col "ID" value", k, Pattern [j])) ;EDEBUG4 (*xp) ;DEBUG4 (("\n")) ;/* xk -= X [Pattern [j]] * (*xp) ; */MULT_SUB (xk, X [Pattern [j]], *xp) ;xp++ ;}#ifndef NO_DIVIDE_BY_ZERO/* Go ahead and divide by zero if D [k] is zero *//* X [k] = xk / D [k] ; */DIV (X [k], xk, D [k]) ;#else/* Do not divide by zero */if (IS_NONZERO (D [k])){/* X [k] = xk / D [k] ; */DIV (X [k], xk, D [k]) ;}#endif/* ------------------------------------------------------------------ *//* make row k-1 of U in Pattern [0..deg-1] *//* ------------------------------------------------------------------ */if (k == n1) break ;if (newUchain){/* next row is a new Uchain */deg = ulen ;ASSERT (IMPLIES (k == 0, deg == 0)) ;DEBUG4 (("end of chain for row of U "ID" deg "ID"\n", k-1, deg)) ;ip = (Int *) (Numeric->Memory + up) ;for (j = 0 ; j < deg ; j++){col = *ip++ ;DEBUG4 ((" k "ID" col "ID"\n", k-1, col)) ;ASSERT (k <= col) ;Pattern [j] = col ;}}else{deg -= ulen ;DEBUG4 (("middle of chain for row of U "ID" deg "ID"\n", k, deg)) ;ASSERT (deg >= 0) ;pos = Upos [k] ;if (pos != EMPTY){/* add the pivot column */DEBUG4 (("k "ID" add pivot entry at pos "ID"\n", k, pos)) ;ASSERT (pos >= 0 && pos <= deg) ;Pattern [deg++] = Pattern [pos] ;Pattern [pos] = k ;}}}/* ---------------------------------------------------------------------- *//* singletons *//* ---------------------------------------------------------------------- */for (k = n1 - 1 ; k >= 0 ; k--){deg = Uilen [k] ;xk = X [k] ;DEBUG4 (("Singleton k "ID"\n", k)) ;if (deg > 0){up = Uip [k] ;Ui = (Int *) (Numeric->Memory + up) ;up += UNITS (Int, deg) ;Uval = (Entry *) (Numeric->Memory + up) ;for (j = 0 ; j < deg ; j++){DEBUG4 ((" k "ID" col "ID" value", k, Ui [j])) ;EDEBUG4 (Uval [j]) ;DEBUG4 (("\n")) ;/* xk -= X [Ui [j]] * Uval [j] ; */ASSERT (Ui [j] >= 0 && Ui [j] < n) ;MULT_SUB (xk, X [Ui [j]], Uval [j]) ;}}#ifndef NO_DIVIDE_BY_ZERO/* Go ahead and divide by zero if D [k] is zero *//* X [k] = xk / D [k] ; */DIV (X [k], xk, D [k]) ;#else/* Do not divide by zero */if (IS_NONZERO (D [k])){/* X [k] = xk / D [k] ; */DIV (X [k], xk, D [k]) ;}#endif}#ifndef NDEBUGfor (j = 0 ; j < n ; j++){DEBUG4 (("Usolve done "ID": ", j)) ;EDEBUG4 (X [j]) ;DEBUG4 (("\n")) ;}DEBUG4 (("Usolve done.\n")) ;#endifreturn (DIV_FLOPS * ((double) n) + MULTSUB_FLOPS * ((double) Numeric->unz));}