aboutsummaryrefslogtreecommitdiff
path: root/math/deboor/banfac.f
blob: 56906927f9fc903faf5b48394de365d2dceaf779 (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
subroutine banfac ( w, nroww, nrow, nbandl, nbandu, iflag )
c  from  * a practical guide to splines *  by c. de boor
c  returns in  w  the lu-factorization (without pivoting) of the banded
c  matrix  a  of order	nrow  with  (nbandl + 1 + nbandu) bands or diag-
c  onals in the work array  w .
c
c******  i n p u t  ******
c  w.....work array of size  (nroww,nrow)  containing the interesting
c	 part of a banded matrix  a , with the diagonals or bands of  a
c	 stored in the rows of	w , while columns of  a  correspond to
c	 columns of  w . this is the storage mode used in  linpack  and
c	 results in efficient innermost loops.
c	    explicitly,  a  has  nbandl  bands below the diagonal
c			     +	   1	 (main) diagonal
c			     +	 nbandu  bands above the diagonal
c	 and thus, with    middle = nbandu + 1,
c	   a(i+j,j)  is in  w(i+middle,j)  for i=-nbandu,...,nbandl
c					       j=1,...,nrow .
c	 for example, the interesting entries of a (1,2)-banded matrix
c	 of order  9  would appear in the first  1+1+2 = 4  rows of  w
c	 as follows.
c			   13 24 35 46 57 68 79
c			12 23 34 45 56 67 78 89
c		     11 22 33 44 55 66 77 88 99
c		     21 32 43 54 65 76 87 98
c
c	 all other entries of  w  not identified in this way with an en-
c	 try of  a  are never referenced .
c  nroww.....row dimension of the work array  w .
c	 must be  .ge.	nbandl + 1 + nbandu  .
c  nbandl.....number of bands of  a  below the main diagonal
c  nbandu.....number of bands of  a  above the main diagonal .
c
c******  o u t p u t  ******
c  iflag.....integer indicating success( = 1) or failure ( = 2) .
c     if  iflag = 1, then
c  w.....contains the lu-factorization of  a  into a unit lower triangu-
c	 lar matrix  l	and an upper triangular matrix	u (both banded)
c	 and stored in customary fashion over the corresponding entries
c	 of  a . this makes it possible to solve any particular linear
c	 system  a*x = b  for  x  by a
c	       call banslv ( w, nroww, nrow, nbandl, nbandu, b )
c	 with the solution x  contained in  b  on return .
c     if  iflag = 2, then
c	 one of  nrow-1, nbandl,nbandu failed to be nonnegative, or else
c	 one of the potential pivots was found to be zero indicating
c	 that  a  does not have an lu-factorization. this implies that
c	 a  is singular in case it is totally positive .
c
c******  m e t h o d  ******
c     gauss elimination  w i t h o u t	pivoting is used. the routine is
c  intended for use with matrices  a  which do not require row inter-
c  changes during factorization, especially for the  t o t a l l y
c  p o s i t i v e  matrices which occur in spline calculations.
c     the routine should not be used for an arbitrary banded matrix.
c
      integer iflag,nbandl,nbandu,nrow,nroww,	i,ipk,j,jmax,k,kmax
     *					      ,middle,midmk,nrowm1
      real w(nroww,nrow),   factor,pivot
c
      iflag = 1
      middle = nbandu + 1
c			  w(middle,.) contains the main diagonal of  a .
      nrowm1 = nrow - 1
      if (nrowm1)			999,900,1
    1 if (nbandl .gt. 0)		go to 10
c		 a is upper triangular. check that diagonal is nonzero .
      do 5 i=1,nrowm1
	 if (w(middle,i) .eq. 0.)	go to 999
    5	 continue
					go to 900
   10 if (nbandu .gt. 0)		go to 20
c	       a is lower triangular. check that diagonal is nonzero and
c		  divide each column by its diagonal .
      do 15 i=1,nrowm1
	 pivot = w(middle,i)
	 if(pivot .eq. 0.)		go to 999
	 jmax = min0(nbandl, nrow - i)
	 do 15 j=1,jmax
   15	    w(middle+j,i) = w(middle+j,i)/pivot
					return
c
c	 a  is not just a triangular matrix. construct lu factorization
   20 do 50 i=1,nrowm1
c				   w(middle,i)	is pivot for i-th step .
	 pivot = w(middle,i)
	 if (pivot .eq. 0.)		go to 999
c		  jmax	is the number of (nonzero) entries in column  i
c		      below the diagonal .
	 jmax = min0(nbandl,nrow - i)
c	       divide each entry in column  i  below diagonal by pivot .
	 do 32 j=1,jmax
   32	    w(middle+j,i) = w(middle+j,i)/pivot
c		  kmax	is the number of (nonzero) entries in row  i  to
c		      the right of the diagonal .
	 kmax = min0(nbandu,nrow - i)
c		   subtract  a(i,i+k)*(i-th column) from (i+k)-th column
c		   (below row  i ) .
	 do 40 k=1,kmax
	    ipk = i + k
	    midmk = middle - k
	    factor = w(midmk,ipk)
	    do 40 j=1,jmax
   40	       w(midmk+j,ipk) = w(midmk+j,ipk) - w(middle+j,i)*factor
   50	 continue
c					check the last diagonal entry .
  900 if (w(middle,nrow) .ne. 0.)	return
  999 iflag = 2
					return
      end