Computes the interval index left and weights b such that the
ideriv-th derivative of the b-spline (t,a,n,k) at x is
sum(b(1:k)*a(left-k+1:left))
This gives the same result as dbvalu, but since the weights only
depend on the knots, they can be reused for every coefficient vector
with the same knots. This is used by the multidimensional db*val
routines so that the work in each direction is only done once.
The interval selection (including left limiting values at t(n+1)),
extrapolation behavior, and error codes are the same as dbvalu.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in), | dimension(:) | :: | t |
knot vector of length |
|
| integer(kind=ip), | intent(in) | :: | n |
number of b-spline coefficients. |
||
| integer(kind=ip), | intent(in) | :: | k |
order of the b-spline, |
||
| integer(kind=ip), | intent(in) | :: | ideriv |
order of the derivative, |
||
| real(kind=wp), | intent(in) | :: | x |
argument, |
||
| integer(kind=ip), | intent(inout) | :: | inbv |
an initialization parameter which must be set to 1 the first time this routine is called. (see dbvalu) |
||
| integer(kind=ip), | intent(out) | :: | left |
the interval index, |
||
| real(kind=wp), | intent(out), | dimension(k) | :: | b |
weights for coefficients |
|
| integer(kind=ip), | intent(out) | :: | iflag |
status flag (same codes as dbvalu) |
||
| logical, | intent(in), | optional | :: | extrap |
if extrapolation is allowed (if not present, default is False) |
pure subroutine dbvalu_weights(t,n,k,ideriv,x,inbv,left,b,iflag,extrap) implicit none real(wp),dimension(:),intent(in) :: t !! knot vector of length `n+k` integer(ip),intent(in) :: n !! number of b-spline coefficients. integer(ip),intent(in) :: k !! order of the b-spline, `k >= 1` integer(ip),intent(in) :: ideriv !! order of the derivative, `0 <= ideriv <= k-1`. real(wp),intent(in) :: x !! argument, `t(k) <= x <= t(n+1)` !! (unless extrapolation is allowed) integer(ip),intent(inout) :: inbv !! an initialization parameter which must be set !! to 1 the first time this routine is called. !! (see [[dbvalu]]) integer(ip),intent(out) :: left !! the interval index, `k <= left <= n` real(wp),dimension(k),intent(out) :: b !! weights for coefficients `left-k+1:left` integer(ip),intent(out) :: iflag !! status flag (same codes as [[dbvalu]]) logical,intent(in),optional :: extrap !! if extrapolation is allowed !! (if not present, default is False) integer(ip) :: i,j,jj,kmider,kmj,mflag real(wp) :: xt,saved,term,fac real(wp),dimension(k) :: dr !! `t(i+j) - x` real(wp),dimension(k) :: dl !! `x - t(i+1-j)` logical :: extrapolation_allowed !! if extrapolation is allowed b = 0.0_wp left = k if (k<1_ip) then iflag = 401_ip ! k does not satisfy k>=1 return end if if (n<k) then iflag = 402_ip ! n does not satisfy n>=k return end if if (ideriv<0_ip .or. ideriv>=k) then iflag = 403_ip ! ideriv does not satisfy 0<=ideriv<k return end if if (present(extrap)) then extrapolation_allowed = extrap else extrapolation_allowed = .false. end if ! temp copy of x for computing the interval ! (clamped if extrapolation is allowed) xt = x if (extrapolation_allowed) xt = min(max(x,t(k)),t(n+1_ip)) ! find *i* in (k,n) such that t(i) <= x < t(i+1) ! (or, <= t(i+1) if t(i) < t(i+1) = t(n+1)). call dintrv(t, n+1_ip, xt, inbv, i, mflag) if (xt<t(k)) then iflag = 404_ip ! x is not greater than or equal to t(k) return end if if (mflag/=0_ip) then if (xt>t(i)) then iflag = 405_ip ! x is not less than or equal to t(n+1) return end if do if (i==k) then iflag = 406_ip ! a left limiting value cannot be obtained at t(k) return end if i = i - 1_ip if (xt/=t(i)) exit end do end if ! values at x of the k-ideriv nonzero b-splines of order k-ideriv ! (the recurrence is a polynomial in x, so this also works when extrapolating) kmider = k - ideriv b(1_ip) = 1.0_wp do j=1_ip,kmider-1_ip dr(j) = t(i+j) - x dl(j) = x - t(i+1_ip-j) saved = 0.0_wp do jj=1_ip,j term = b(jj)/(dr(jj)+dl(j+1_ip-jj)) b(jj) = saved + dr(jj)*term saved = dl(j+1_ip-jj)*term end do b(j+1_ip) = saved end do ! apply the transpose of the coefficient differencing in [[dbvalu]] ! so the weights apply to the original coefficients do j=ideriv,1_ip,-1_ip kmj = k - j b(kmj+1_ip) = 0.0_wp do jj=kmj,1_ip,-1_ip fac = b(jj)*real(kmj,wp)/(t(i+jj)-t(i+jj-kmj)) b(jj+1_ip) = b(jj+1_ip) + fac b(jj) = -fac end do end do left = i iflag = 0_ip end subroutine dbvalu_weights