aboutsummaryrefslogtreecommitdiff
path: root/math/deboor/factrb.f
blob: 4bb88e1306fc449673180645e58bd16faff84440 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
subroutine factrb ( w, ipivot, d, nrow, ncol, last, iflag )
c  adapted from p.132 of 'element.numer.analysis' by conte-de boor
c
c  constructs a partial plu factorization, corresponding to steps 1,...,
c   l a s t   in gauss elimination, for the matrix  w  of order
c   ( n r o w ,  n c o l ), using pivoting of scaled rows.
c
c  parameters
c    w	     contains the (nrow,ncol) matrix to be partially factored
c	     on input, and the partial factorization on output.
c    ipivot  an integer array of length nrow containing a record of the
c	     pivoting strategy used; row ipivot(i) is used during the
c	     i-th elimination step, i=1,...,last.
c    d	     a work array of length nrow used to store row sizes
c	     temporarily.
c    nrow    number of rows of w.
c    ncol    number of columns of w.
c    last    number of elimination steps to be carried out.
c    iflag   on output, equals iflag on input times (-1)**(number of
c	     row interchanges during the factorization process), in
c	     case no zero pivot was encountered.
c	     otherwise, iflag = 0 on output.
c
      integer nrow
      integer ipivot(nrow),ncol,last,iflag, i,ipivi,ipivk,j,k,kp1
      real w(nrow,ncol),d(nrow), awikdi,colmax,ratio,rowmax
c  initialize ipivot, d
      do 10 i=1,nrow
	 ipivot(i) = i
	 rowmax = 0.
	 do 9 j=1,ncol
    9	    rowmax = amax1(rowmax, abs(w(i,j)))
	 if (rowmax .eq. 0.)		go to 999
   10	 d(i) = rowmax
c gauss elimination with pivoting of scaled rows, loop over k=1,.,last
      k = 1
c	 as pivot row for k-th step, pick among the rows not yet used,
c	 i.e., from rows ipivot(k),...,ipivot(nrow), the one whose k-th
c	 entry (compared to the row size) is largest. then, if this row
c	 does not turn out to be row ipivot(k), redefine ipivot(k) ap-
c	 propriately and record this interchange by changing the sign
c	 of  i f l a g .
   11	 ipivk = ipivot(k)
	 if (k .eq. nrow)		go to 21
	 j = k
	 kp1 = k+1
	 colmax = abs(w(ipivk,k))/d(ipivk)
c	       find the (relatively) largest pivot
	 do 15 i=kp1,nrow
	    ipivi = ipivot(i)
	    awikdi = abs(w(ipivi,k))/d(ipivi)
	    if (awikdi .le. colmax)	go to 15
	       colmax = awikdi
	       j = i
   15	    continue
	 if (j .eq. k)			go to 16
	 ipivk = ipivot(j)
	 ipivot(j) = ipivot(k)
	 ipivot(k) = ipivk
	 iflag = -iflag
   16	 continue
c	 if pivot element is too small in absolute value, declare
c	 matrix to be noninvertible and quit.
	 if (abs(w(ipivk,k))+d(ipivk) .le. d(ipivk))
     *					go to 999
c	 otherwise, subtract the appropriate multiple of the pivot
c	 row from remaining rows, i.e., the rows ipivot(k+1),...,
c	 ipivot(nrow), to make k-th entry zero. save the multiplier in
c	 its place.
	 do 20 i=kp1,nrow
	    ipivi = ipivot(i)
	    w(ipivi,k) = w(ipivi,k)/w(ipivk,k)
	    ratio = -w(ipivi,k)
	    do 20 j=kp1,ncol
   20	       w(ipivi,j) = ratio*w(ipivk,j) + w(ipivi,j)
	 k = kp1
c	 check for having reached the next block.
	 if (k .le. last)		go to 11
					return
c     if  last	.eq. nrow , check now that pivot element in last row
c     is nonzero.
   21 if( abs(w(ipivk,nrow))+d(ipivk) .gt. d(ipivk) )
     *					return
c		    singularity flag set
  999 iflag = 0
					return
      end