comparison scripts/polynomial/ppval.m @ 12608:59e2460acae1

make piecewise polynomial (pp) functions more compatible
author Kai Habel <kai.habel@gmx.de>
date Wed, 23 Feb 2011 08:11:40 +0100
parents c792872f8942
children e81ddf9cacd5
comparison
equal deleted inserted replaced
12606:3047363c376d 12608:59e2460acae1
16 ## along with Octave; see the file COPYING. If not, see 16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>. 17 ## <http://www.gnu.org/licenses/>.
18 18
19 ## -*- texinfo -*- 19 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {@var{yi} =} ppval (@var{pp}, @var{xi}) 20 ## @deftypefn {Function File} {@var{yi} =} ppval (@var{pp}, @var{xi})
21 ## Evaluate piecewise polynomial @var{pp} at the points @var{xi}. 21 ## Evaluate piece-wise polynomial structure @var{pp} at the points @var{xi}.
22 ## If @var{pp} is scalar-valued, the result is an array of the same shape as 22 ## If @var{pp} describes a scalar polynomial function, the result is an
23 ## @var{xi}. 23 ## array of the same shape as @var{xi}.
24 ## Otherwise, the size of the result is @code{[pp.d, length(@var{xi})]} if 24 ## Otherwise, the size of the result is @code{[pp.dim, length(@var{xi})]} if
25 ## @var{xi} is a vector, or @code{[pp.d, size(@var{xi})]} if it is a 25 ## @var{xi} is a vector, or @code{[pp.dim, size(@var{xi})]} if it is a
26 ## multi-dimensional array. If pp.orient is 1, the dimensions are permuted as 26 ## multi-dimensional array.
27 ##
28 ##, the dimensions are permuted as
27 ## in interp1, to 29 ## in interp1, to
28 ## @code{[pp.d, length(@var{xi})]} and @code{[pp.d, size(@var{xi})]} 30 ## @code{[pp.d, length(@var{xi})]} and @code{[pp.d, size(@var{xi})]}
29 ## respectively. 31 ## respectively.
30 ## @seealso{mkpp, unmkpp, spline} 32 ## @seealso{mkpp, unmkpp, spline, pchip, interp1}
31 ## @end deftypefn 33 ## @end deftypefn
32 34
33 function yi = ppval (pp, xi) 35 function yi = ppval (pp, xi)
34 36
35 if (nargin != 2) 37 if (nargin != 2)
36 print_usage (); 38 print_usage ();
37 endif 39 endif
38 if (! isstruct (pp)) 40 if (! isstruct (pp) && strcmp (pp.form, "pp"))
39 error ("ppval: PP must be a structure"); 41 error ("ppval: expects a pp-form structure");
40 endif 42 endif
41 43
42 ## Extract info. 44 ## Extract info.
43 x = pp.x; 45 [x, P, n, k, d] = unmkpp (pp);
44 P = pp.P; 46
45 d = pp.d; 47 ## dimension checks
46 k = size (P, 3); 48 sxi = size (xi);
47 nd = size (P, 1); 49 if (isvector (xi))
50 xi = xi(:).';
51 endif
52
53 nd = length (d);
48 54
49 ## Determine resulting shape. 55 ## Determine intervals.
50 if (d == 1) # scalar case 56 xn = numel (xi);
51 yisz = size (xi); 57 idx = lookup (x, xi, "lr");
52 elseif (isvector (xi)) # this is special 58
53 yisz = [d, length(xi)]; 59 P = reshape (P, [d, n * k]);
54 else # general 60 P = shiftdim (P, nd);
55 yisz = [d, size(xi)]; 61 P = reshape (P, [n, k, d]);
62 Pidx = P(idx(:), :);#2d matrix size x: coefs*prod(d) y: prod(sxi)
63
64 if (isvector(xi))
65 Pidx = reshape (Pidx, [xn, k, d]);
66 Pidx = shiftdim (Pidx, 1);
67 dimvec = [d, xn];
68 else
69 Pidx = reshape (Pidx, [sxi, k, d]);
70 Pidx = shiftdim (Pidx, length (sxi));
71 dimvec = [d, sxi];
72 end
73 ndv = length (dimvec);
74
75 ## Offsets.
76 dx = (xi - x(idx));
77 dx = repmat (dx, [prod(d), 1]);
78 dx = reshape (dx, dimvec);
79 dx = shiftdim (dx, ndv - 1);
80
81 ## Use Horner scheme.
82 yi = Pidx;
83 if (k > 1)
84 yi = shiftdim (reshape (Pidx(1,:), dimvec), ndv - 1);
85 endif
86
87 for i = 2 : k;
88 yi .*= dx;
89 yi += shiftdim (reshape (Pidx(i,:), dimvec), ndv - 1);
90 endfor
91
92 ## Adjust shape.
93 if ((numel (xi) > 1) || (length (d) == 1))
94 yi = reshape (shiftdim (yi, 1), dimvec);
56 endif 95 endif
57 96
58 ## Determine intervals. 97 if (isvector (xi) && (d == 1))
59 xi = xi(:); 98 yi = reshape (yi, sxi);
60 xn = numel (xi); 99 elseif (isfield (pp, "orient") && strcmp (pp.orient, "first"))
61 100 yi = shiftdim(yi, nd);
62 idx = lookup (x, xi, "lr");
63
64 ## Offsets.
65 dx = (xi - x(idx)).';
66 dx = dx(ones (1, nd), :); # spread (do nothing in 1D)
67
68 ## Use Horner scheme.
69 yi = P(:,idx,1);
70 for i = 2:k;
71 yi .*= dx;
72 yi += P(:,idx,i);
73 endfor
74
75 ## Adjust shape.
76 yi = reshape (yi, yisz);
77 if (d != 1 && pp.orient == 1)
78 ## Switch dimensions to match interp1 order.
79 yi = shiftdim (yi, length (d));
80 endif 101 endif
81 102
103 ##
104 #if (d == 1)
105 # yi = reshape (yi, sxi);
106 #endif
107
82 endfunction 108 endfunction
109
110 %!shared b,c,pp,pp2,xi,abserr
111 %! b = 1:3; c = ones(2); pp=mkpp(b,c);abserr = 1e-14;pp2=mkpp(b,[c;c],2);
112 %! xi = [1.1 1.3 1.9 2.1];
113 %!assert (ppval(pp,1.1), 1.1, abserr);
114 %!assert (ppval(pp,2.1), 1.1, abserr);
115 %!assert (ppval(pp,xi), [1.1 1.3 1.9 1.1], abserr);
116 %!assert (ppval(pp,xi.'), [1.1 1.3 1.9 1.1].', abserr);
117 %!assert (ppval(pp2,1.1), [1.1;1.1], abserr);
118 %!assert (ppval(pp2,2.1), [1.1;1.1], abserr);
119 %!assert (ppval(pp2,xi), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
120 %!assert (ppval(pp2,xi'), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
121 %!assert (size(ppval(pp2,[xi;xi])), [2 2 4]);