Viewing contents of file '../idllib/astron/contrib/varosi/vlib/allpro/finterpol.pro'
;+
; NAME:
; FINTERPOL
; PURPOSE:
; Linear interpolation of a table of function values onto a new grid.
; Finterpol is faster than the old IDL lib routine interpol
; when the arrays (xold & xnew) have more than about 10 elements,
; and speedup factor increases to > 15 when number of elements > 100.
; This is acheived by first calling function InterLeave( xold, xnew ),
; which then allows subsequent computations to be vectorized.
; Intermediate computations are stored in a common block so that
; after the first call, further interpolations of different functions
; evaluated on the same grids can be performed even faster (10 X)
; by omitting the xold & xnew arguments in further calls. The array
; of points at which function is known must be strictly increasing,
; but the new interpolation points can be in any order. If the new
; grid points are beyond the range of old points extrapolation is
; performed, and a message is printed (unless /QUIET is set).
; See keywords for options to interpolate exponential or power-law
; functional behaviours.
;
; CALLING:
; fxnew = finterpol( fxold, xold, xnew )
;
; INPUTS:
; fxold = array of function values at the points xold.
;
; xold = array of points (strictly increasing) where func is evaluated.
;
; xnew = array of new points at which linear interpolations are desired.
;
; KEYWORDS:
; /QUIET : do not check or print any messages if extrapolation is done.
; Default is to give warning messages about # points extrapolated.
;
; /INITIALIZE : use only the xold & xnew arrays to compute arrays
; that are kept in the common block for use in fast repetitive
; interpolations of different functions from/to same grids.
; No interpolation is performed and just status (0/1) is returned.
;
; /EXPONENTIAL_INTERP: perform interpolation/extrapolation in Log-Linear
; space, thereby giving correct result for exponential function.
; (Function values are then assumed > 1e-37).
;
; /POWER_LAW_INTERP: perform interpolation/extrapolation in Log-Log space,
; thereby giving correct result for power-law function.
; (Function and X coordinate values are then assumed > 1e-37).
;
; OUTPUTS:
; Function returns array of linear interpolates at new grid points,
; or it returns just the number 1 if /INIT is set, or 0 if calling error.
; COMMON BLOCKS:
; common finterpol
; common finterpol2
; EXTERNAL CALLS:
; function InterLeave
; function scalar
; PROCEDURE:
; Call function InterLeave to find old grid points which bracket
; the new grid points, and then interpolate in vectorized form.
; Take natural log of function values for exponential interpolation,
; then exponentiating on return, take log of grid points and function
; for interpolation of power-law behaviour.
; HISTORY:
; Written: Frank Varosi, HSTX @ NASA/GSFC, 1997.
; F.V. 1998, added /EXPONENTIAL_INTERP and /POWER_LAW_INTERP options.
; F.V. 1999, /EXP and /POWER options are remebered for repeat calls,
; and scalar value is returned if result has just one element.
;-
function finterpol, fxold, xold, xnew, QUIET=quiet, INITIALIZE=init, $
POWER_LAW_INTERP=ipow, $
EXPONENTIAL_INTERP=iexp
common finterpol, Lw, Lw1, xfrac
common finterpol2, logflag, nextrap
Nxo2 = N_elements( xold )-2
if (Nxo2 ge 0) and (N_elements( xnew ) gt 0) then begin
Lw = InterLeave( xold, xnew )
wex = where( (Lw LT 0) or (Lw GT Nxo2), nextrap )
if nextrap GT 0 then begin
if Lw(wex(nextrap-1)) eq (Nxo2+1) then begin
w = wex(nextrap-1)
if xnew(w) eq xold(Lw(w)) then nextrap=nextrap-1
endif
Lw(wex) = ( Lw(wex) > 0 ) < Nxo2
endif
Lw1 = Lw+1
if keyword_set( ipow ) or keyword_set( iexp ) then logflag=1 $
else logflag=0
if keyword_set( ipow ) then begin
z = alog( xold > 1e-37 )
xfrac = ( alog(xnew>1e-37) - z(Lw) )/( z(Lw1) - z(Lw) )
endif else xfrac = ( xnew - xold(Lw) )/( xold(Lw1) - xold(Lw) )
endif else if (Nxo2 eq -1) and (N_elements( xnew ) gt 0) then begin
message,"need more than 1 point in the Xold grid",/INFO
return,0
endif
if keyword_set( init ) then return,1
if (N_elements( fxold ) LE 0) or (N_elements( xfrac ) LE 0) then begin
if N_elements( fxold ) LE 0 then $
message,"missing parameter fxold",/INFO
if N_elements( xfrac ) LE 0 then $
message,"missing parameters xold or xnew",/INFO
print,"syntax:
print," first call: fxnew = finterpol( fxold, xold, xnew )"
print," repeat calls: fxnew = finterpol( fxold )
return,0
endif
if (nextrap GT 0) and NOT keyword_set( quiet ) then $
message,"extrapolating at " + strtrim( nextrap, 2 ) + $
" out of the " + strtrim( N_elements( xfrac ), 2 ) $
+ " new points",/INFO
if keyword_set( logflag ) then begin
z = alog( fxold > 1e-37 )
result = exp( ( z(Lw1) - z(Lw) ) * xfrac + z(Lw) )
endif else result = ( fxold(Lw1) - fxold(Lw) ) * xfrac + fxold(Lw)
if N_elements( result ) eq 1 then return, scalar( result ) $
else return, result
end