function fe = spline_pchip_val ( n, x, f, d, ne, xe ) %*****************************************************************************80 % %% SPLINE_PCHIP_VAL evaluates a piecewise cubic Hermite function. % % Description: % % This routine may be used by itself for Hermite interpolation, or as an % evaluator for SPLINE_PCHIP_SET. % % This routine evaluates the cubic Hermite function at the points XE. % % Most of the coding between the call to CHFEV and the end of % the IR loop could be eliminated if it were permissible to % assume that XE is ordered relative to X. % % CHFEV does not assume that X1 is less than X2. Thus, it would % be possible to write a version of SPLINE_PCHIP_VAL that assumes a strictly % decreasing X array by simply running the IR loop backwards % and reversing the order of appropriate tests. % % The present code has a minor bug, which I have decided is not % worth the effort that would be required to fix it. % If XE contains points in [X(N-1),X(N)], followed by points less than % X(N-1), followed by points greater than X(N), the extrapolation points % will be counted (at least) twice in the total returned in IERR. % % The evaluation will be most efficient if the elements of XE are % increasing relative to X; that is, for all J <= K, % X(I) <= XE(J) % implies % X(I) <= XE(K). % % If any of the XE are outside the interval [X(1),X(N)], % values are extrapolated from the nearest extreme cubic, % and a warning error is returned. % % This routine was originally named "PCHFE". % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 14 August 2005 % % Author: % % Original FORTRAN77 version by Fred Fritsch. % MATLAB version by John Burkardt. % % Reference: % % Fred Fritsch, Ralph Carlson, % Monotone Piecewise Cubic Interpolation, % SIAM Journal on Numerical Analysis, % Volume 17, Number 2, April 1980, pages 238-246. % % Parameters: % % Input, integer N, the number of data points. N must be at least 2. % % Input, real X(N), the strictly increasing independent % variable values. % % Input, real F(N), the function values. % % Input, real D(N), the derivative values. % % Input, integer NE, the number of evaluation points. % % Input, real XE(NE), points at which the function is to % be evaluated. % % Output, real FE(NE), the values of the cubic Hermite % function at XE. % % % Check arguments. % if ( n < 2 ) ierr = -1; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' Number of data points less than 2.\n' ); error ( 'SPLINE_PCHIP_VAL - Fatal error!' ); end for i = 2 : n if ( x(i) <= x(i-1) ) ierr = -3; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' X array not strictly increasing.\n' ); error ( 'SPLINE_PCHIP_VAL - Fatal error!' ); end end if ( ne < 1 ) ierr = -4; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' Number of evaluation points less than 1.\n' ); fe = []; return end ierr = 0; % % Loop over intervals. % The interval index is IL = IR-1. % The interval is X(IL) <= X < X(IR). % j_first = 1; ir = 2; while ( 1 ) % % Skip out of the loop if have processed all evaluation points. % if ( ne < j_first ) break end % % Locate all points in the interval. % j_save = ne + 1; for j = j_first : ne if ( x(ir) <= xe(j) ) j_save = j; if ( ir == n ) j_save = ne + 1; end break end end % % Have located first point beyond interval. % j = j_save; nj = j - j_first; % % Skip evaluation if no points in interval. % if ( nj ~= 0 ) % % Evaluate cubic at XE(J_FIRST:J-1). % [ fe(j_first:j-1), next, ierc ] = chfev ( x(ir-1), x(ir), f(ir-1), ... f(ir), d(ir-1), d(ir), nj, xe(j_first:j-1) ); if ( ierc < 0 ) ierr = -5; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' Error return from CHFEV.\n' ); error ( 'SPLINE_PCHIP_VAL - Fatal error!' ); end % % In the current set of XE points, there are NEXT(2) to the right of X(IR). % if ( next(2) ~= 0 ) if ( ir < n ) ierr = -5; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' IR < N.\n' ); error ( 'SPLINE_PCHIP_VAL - Fatal error!' ); end % % These are actually extrapolation points. % ierr = ierr + next(2); end % % In the current set of XE points, there are NEXT(1) to the left of X(IR-1). % if ( next(1) ~= 0 ) % % These are actually extrapolation points. % if ( ir <= 2 ) ierr = ierr + next(1); else j_new = -1; for i = j_first : j-1 if ( xe(i) < x(ir-1) ) j_new = i; break end end if ( j_new == -1 ) ierr = -5; fprintf ( 1, '\n' ); fprintf ( 1, 'SPLINE_PCHIP_VAL - Fatal error!\n' ); fprintf ( 1, ' Could not bracket the data point.\n' ); error ( 'SPLINE_PCHIP_VAL - Fatal error!' ); end % % Reset J. This will be the new J_FIRST. % j = j_new; % % Now find out how far to back up in the X array. % for i = 1 : ir-1 if ( xe(j) < x(i) ) break end end % % At this point, either XE(J) < X(1) or X(i-1) <= XE(J) < X(I) . % % Reset IR, recognizing that it will be incremented before cycling. % ir = max ( 1, i-1 ); end end j_first = j; end ir = ir + 1; if ( n < ir ) break end end return end