aboutsummaryrefslogtreecommitdiff
path: root/math/nlfit/nlchomat.gx
blob: 5a36c63c75a73b7c5b0b37d050cf0e836e1bb62d (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
include <mach.h>
include <math/nlfit.h>
$if (datatype == r)
include "nlfitdefr.h"
$else
include "nlfitdefd.h"
$endif


# NL_CHFAC -- Routine to calculate the Cholesky factorization of a
# symmetric, positive semi-definite banded matrix. This routines was
# adapted from the bchfac.f routine described in "A Practical Guide
# to Splines", Carl de Boor (1978).

procedure nl_chfac$t (matrix, nbands, nrows, matfac, ier)

PIXEL   matrix[nbands, nrows]	# data matrix
int	nbands			# number of bands
int	nrows			# number of rows
PIXEL   matfac[nbands, nrows]	# Cholesky factorization
int	ier			# error code

int	i, n, j, imax, jmax
PIXEL   ratio

begin
	# Test for a single element matrix.
	if (nrows == 1) {
	    if (matrix[1,1] > PIXEL (0.0))
	        matfac[1,1] = 1. / matrix[1,1]
	    return
	}
		
	# Copy the original matrix into matfac.
	do n = 1, nrows {
	    do j = 1, nbands
		matfac[j,n] = matrix[j,n]
	}

	# Compute the factorization of the matrix.
	do n = 1, nrows {

	    # Test to see if matrix is singular.
	    if (((matfac[1,n] + matrix[1,n]) - matrix[1,n]) <= EPSILON$T) {
	    #if (((matfac[1,n] + matrix[1,n]) - matrix[1,n]) <= PIXEL(0.0)) {
		do j = 1, nbands
		    matfac[j,n] = PIXEL (0.0)
		ier = SINGULAR
		next
	    }

	    matfac[1,n] = PIXEL (1.0) / matfac[1,n]
	    imax = min (nbands - 1, nrows - n)
	    if (imax < 1)
		next

	    jmax = imax
	    do i = 1, imax {
		ratio = matfac[i+1,n] * matfac[1,n]
		do j = 1, jmax
		    matfac[j,n+i] = matfac[j,n+i] - matfac[j+i,n] * ratio
		jmax = jmax - 1
		matfac[i+1,n] = ratio
	    }
	}
end


# NL_CHSLV -- Solve the matrix whose Cholesky factorization was calculated in
# NL_CHFAC for the coefficients. This routine was adapted from bchslv.f
# described in "A Practical Guide to Splines", by Carl de Boor (1978).

procedure nl_chslv$t (matfac, nbands, nrows, vector, coeff)

PIXEL	matfac[nbands,nrows] 		# Cholesky factorization
int	nbands				# number of bands
int	nrows				# number of rows
PIXEL	vector[nrows]			# right side of matrix equation
PIXEL	coeff[nrows]			# coefficients

int	i, n, j, jmax, nbndm1

begin
	# Test for a single element matrix.
	if (nrows == 1) {
	    coeff[1] = vector[1] * matfac[1,1]
	    return
	}

	# Copy input vector to coefficients vector.
	do i = 1, nrows
	    coeff[i] = vector[i]

	# Perform forward substitution.
	nbndm1 = nbands - 1
	do n = 1, nrows {
	    jmax = min (nbndm1, nrows - n)
	    if (jmax >= 1) {
	        do j = 1, jmax
		    coeff[j+n] = coeff[j+n] - matfac[j+1,n] * coeff[n]
	    }
	}

	# Perform backward substitution.
	for (n = nrows; n >= 1; n = n - 1) {
	    coeff[n] = coeff[n] * matfac[1,n]
	    jmax = min (nbndm1, nrows - n)
	    if (jmax >= 1) {
		do j = 1, jmax
		    coeff[n] = coeff[n] - matfac[j+1,n] * coeff[j+n]
	    }
	}
end


# NL_DAMP -- Procedure to add damping to matrix

procedure nl_damp$t (inmatrix, outmatrix, constant, nbands, nrows)

PIXEL	inmatrix[nbands,ARB]		# input matrix
PIXEL	outmatrix[nbands,ARB]		# output matrix
PIXEL	constant			# damping constant
int	nbands, nrows			# dimensions of matrix

int	i

begin
	do i = 1, nrows
	    outmatrix[1,i] = inmatrix[1,i] * constant
end