aboutsummaryrefslogtreecommitdiff
path: root/math/deboor/splsqv.x
blob: 1b4db24816f85f4a2e1b865392987d20e10616e4 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.


include	"bspln.h"
define	ILLEGAL_ORDER	2	#error returns
define	NO_DEG_FREEDOM	3


.help splsqv 2 "IRAF Math Library"

Adapted from L2APPR, * A Practical Guide To Splines *  by C. DeBoor.
Eliminated data entry via the common /data/ (D.Tody, 4-july-82).  Calls
subprograms  BSPLVB, BCHFAC, BCHSLV.

SPLSQV constructs the (weighted discrete) l2-approximation by splines of
order K with knot sequence  T[1], ..., t[nt+k]  to given data points
(TAU[i], GTAU[i]), i=1,...,ntau.  The b-spline coefficients BCOEF of the
approximating spline are determined from the normal equations using
Cholesky'smethod.

SPLSQV (tau, gtau, weight, ntau, t, nt, k, work, diag, bcoef, ier)


INPUT -----

ntau		Number of data points
tau[ntau]	x-value of the data points.
gtau[ntau]	y-value of the data points.
weight[ntau]	The corresponding weights.
t[nt]		The knot sequence
nt		The dimension of the space of splines of order k with knots t.
k		The order of the b-spline to be fitted.


WORK ARRAYS -----

work[k,nt]	A work array of size (at least) K*NT. its first K rows are used
		for the K lower diagonals of the gramian matrix C.
diag[nt]	A work array of length NT used in BCHFAC.


OUTPUT -----

bcoef[nt]	The b-spline coefficients of the l2-approximation.
ier		Error code: zero if ok, else small integer error code.


METHOD -----

The b-spline coefficients of the l2-appr. are determined as the solution
of the normal equations

	sum ((B[i],B[j]) * BCOEF[j] : j=1:nt) = (B[i],G), 	i = 1 to nt.

where, B[i] denotes the i-th b-spline, G denotes the function to be
approximated, and the INNER PRODUCT of two functions F and G is given by

	(F,G)  :=  sum (F(TAU[i]) * G(TAU[i]) * WEIGHT[i] : i=1:ntau).

The relevant function values of the b-splines  B[i], i=1:nt, are supplied
by the subprogram BSPLVB.  The coeff. matrix C, with

	C(i,j) :=  (B[i], B[j]), i,j=1:n,

of the normal equations is symmetric and (2*k-1)-banded, therefore can be
specified by giving its k bands at or below the diagonal. for i=1,...,n,
we store

	(B[i],B[j])  =  B[i,j]  in  WORK[i-j+1,j], j=i,...,min0(i+k-1,nt)

and the right side

	(B[i], G)  in  BCOEF[i].

since b-spline values are most efficiently generated by finding simultaneously
the value of EVERY nonzero b-spline at one point, the entries of C (i.e., of
WORK), are generated by computing, for each ll, all the terms involving
TAU(ll) simultaneously and adding them to all relevant entries.
.endhelp _______________________________________________________________


procedure splsqv (tau, gtau, weight, ntau, t, nt, k, work, diag, bcoef, ier)

real	tau[ntau], gtau[ntau], weight[ntau]
real	t[nt], work[k,nt], diag[nt], bcoef[nt]
int	ntau, nt, k, ier
int	i, j, jj, left, leftmk, ll, mm
real	biatx[KMAX], dw

begin
	ier = 0
	if (k < 1 || k > KMAX) {
	    ier = ILLEGAL_ORDER
	    return
	}
	if (nt <= k || nt >= ntau+k) {
	    ier = NO_DEG_FREEDOM
	    return
	}

	do j = 1, nt {
	    bcoef[j] = 0.
	    do i = 1, k
		work[i,j] = 0.
	}

	left = k
	leftmk = 0

	do ll = 1, ntau {
	    while (left != nt) {
		if (tau[ll] < t[left+1])
		    break
		left = left + 1
		leftmk = leftmk + 1
	    }

	    call bsplvb (t, k, 1, tau[ll], left, biatx)

#   BIATX[mm] contains the value of B[left-k+mm] at TAU[ll].
#   hence, with DW := BIATX[mm] * WEIGHT[ll], the number DW * GTAU[ll]
#   is a summand in the inner product
#      (B[left-k+mm],G)  which goes into  BCOEF[left-k+mm]
#   and the number BIATX[jj] * dw is a summand in the inner product
#      (B[left-k+jj],  B[left-k+mm]),  into  WORK[jj-mm+1,left-k+mm]
#   since (left-k+jj) - (left-k+mm) + 1 = jj - mm + 1.

	    do mm = 1, k {
		dw = biatx[mm] * weight[ll]
		j = leftmk + mm
		bcoef[j] = dw * gtau[ll] + bcoef[j]
		i = 1

		do jj = mm, k {
		    work[i,j] = biatx[jj] * dw + work[i,j]
		    i = i + 1
		}
	    }
	}

#  construct cholesky factorization for C in WORK,  then use it to solve
#  the normal equations
#       c * x = bcoef
#  for X, and store X in BCOEF.

	call bchfac (work, k, nt, diag)
	call bchslv (work, k, nt, bcoef)
	return
end