-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathinprod.bspline.R
151 lines (126 loc) · 5.03 KB
/
inprod.bspline.R
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
150
151
inprod.bspline <- function(fdobj1, fdobj2=fdobj1, nderiv1=0, nderiv2=0) {
#INPROD_BSPLINE computes matrix of inner products of the derivatives
# of order DERIV1 and DERIV2 of two functional data objects
# FD1 and FD2, respectively.
# These must both have Bspline bases, and these bases must have
# a common break point sequence. However, the orders can differ.
# If only the first argument is present, the inner products of
# FD1 with itself is taken. If argument DERIV is not supplied,
# it is taken to be 0.
#
# Last modified 26 October 2005
if(!inherits(fdobj1,"fd")) stop("FD1 is not a functional data object.")
if(!inherits(fdobj2,"fd")) stop("FD2 is not a functional data object.")
basis1 <- fdobj1$basis
type1 <- basis1$type
if(type1!="bspline") stop("FDOBJ1 does not have a B-spline basis.")
range1 <- basis1$rangeval
breaks1 <- c(range1[1], basis1$params, range1[2])
nbasis1 <- basis1$nbasis
norder1 <- nbasis1 - length(breaks1) + 2
basis2 <- fdobj2$basis
type2 <- basis2$type
if(type2!="bspline") stop("FDOBJ2 does not have a B-spline basis.")
range2 <- basis2$rangeval
breaks2 <- c(range2[1], basis2$params, range2[2])
nbasis2 <- basis2$nbasis
norder2 <- nbasis2 - length(breaks2) + 2
if(any((range1 - range2) != 0)) stop(
"The argument ranges for FDOBJ1 and FDOBJ2 are not identical.")
# check that break values are equal and set up common array
if(length(breaks1) != length(breaks2)) stop(
"The numbers of knots for FDOBJ1 and FDOBJ2 are not identical")
if(any((breaks1 - breaks2) != 0)) stop(
"The knots for FDOBJ1 and FDOBJ2 are not identical.")
else breaks <- breaks1
if(length(breaks) < 2) stop(
"The length of argument BREAKS is less than 2.")
breakdiff <- diff(breaks)
if(min(breakdiff) <= 0) stop(
"Argument BREAKS is not strictly increasing.")
# set up the two coefficient matrices
coef1 <- as.matrix(fdobj1$coefs)
coef2 <- as.matrix(fdobj2$coefs)
if(length(dim(coef1)) > 2) stop("FDOBJ1 is not univariate.")
if(length(dim(coef2)) > 2) stop("FDOBJ2 is not univariate.")
nbreaks <- length(breaks)
ninterval <- nbreaks - 1
nbasis1 <- ninterval + norder1 - 1
nbasis2 <- ninterval + norder2 - 1
if (dim(coef1)[1] != nbasis1 || dim(coef2)[1] != nbasis2)
stop(paste("Error: coef1 should have length no. breaks1+norder1-2",
"and coef2 no. breaks2+norder2-2."))
breaks1 <- breaks[1]
breaksn <- breaks[nbreaks]
# The knot sequences are built so that there are no continuity conditions
# at the first and last breaks. There are k-1 continuity conditions at
# the other breaks.
temp <- breaks[2:(nbreaks-1)]
knots1 <- c(breaks1*rep(1,norder1),temp,breaksn*rep(1,norder1))
knots2 <- c(breaks1*rep(1,norder2),temp,breaksn*rep(1,norder2))
# Construct the piecewise polynomial representation of
# f^(DERIV1) and g^(DERIV2)
nrep1 <- dim(coef1)[2]
polycoef1 <- array(0,c(ninterval,norder1-nderiv1,nrep1))
for (i in 1:nbasis1) {
# compute polynomial representation of B(i,norder1,knots1)(x)
ppBlist <- ppBspline(knots1[i:(i+norder1)])
Coeff <- ppBlist[[1]]
index <- ppBlist[[2]]
# convert the index of the breaks in knots1 to the index in the
# variable "breaks"
index <- index + i - norder1
CoeffD <- ppderiv(Coeff,nderiv1) # differentiate B(i,norder1,knots1)(x)
# add the polynomial representation of B(i,norder1,knots1)(x) to f
if (nrep1 == 1)
polycoef1[index,,1] <- coef1[i]*CoeffD +
polycoef1[index,,1]
else {
for (j in 1:length(index)){
temp <- outer(CoeffD[j,],coef1[i,])
polycoef1[index[j],,] <- temp + polycoef1[index[j],,]
}
}
}
nrep2 <- dim(coef2)[2]
polycoef2 <- array(0,c(ninterval,norder2-nderiv2,nrep2))
for(i in 1:nbasis2){
# compute polynomial representation of B(i,norder2,knots2)(x)
ppBlist <- ppBspline(knots2[i:(i+norder2)])
Coeff <- ppBlist[[1]]
index <- ppBlist[[2]]
# convert the index of the breaks in knots2 to the index in the
# variable "breaks"
index <- index + i - norder2
CoeffD <- ppderiv(Coeff, nderiv2) # differentiate B(i,norder2,knots2)(x)
# add the polynomial representation of B(i,norder2,knots2)(x) to g
if (nrep2 == 1) polycoef2[index,,1] <- coef2[i]*CoeffD +
polycoef2[index,,1]
else{
for(j in 1:length(index)){
polycoef2[index[j],,] <- outer(CoeffD[j,],coef2[i,]) +
polycoef2[index[j],,]
}
}
}
# Compute the scalar product between f and g
prodmat <- matrix(0,nrep1,nrep2)
for (j in 1:ninterval){
# multiply f(i1) and g(i2) piecewise and integrate
c1 <- as.matrix(polycoef1[j,,])
c2 <- as.matrix(polycoef2[j,,])
polyprodmat <- polyprod(c1,c2)
# compute the coefficients of the anti-derivative
N <- dim(polyprodmat)[3]
delta <- breaks[j+1] - breaks[j]
power <- delta
prodmati <- matrix(0,nrep1,nrep2)
for (i in 1:N){
prodmati <- prodmati + power*polyprodmat[,,N-i+1]/i
power <- power*delta
}
# add the integral to s
prodmat <- prodmat + prodmati
}
prodmat
}