PRO TABINV, XARR, X, IEFF, FAST = fast
;+
; NAME:
; TABINV
; PURPOSE:
; To find the effective index of a function value in an ordered vector.
;
; CALLING SEQUENCE:
; TABINV, XARR, X, IEFF, [/FAST]
; INPUTS:
; XARR - the vector array to be searched, must be monotonic
; increasing or decreasing
; X - the function value(s) whose effective
; index is sought (scalar or vector)
;
; OUTPUT:
; IEFF - the effective index or indices of X in XARR
; always floating point, same # of elements as X
;
; OPTIONAL KEYWORD INPUT:
; /FAST - If this keyword is set, then the input vector is not checked
; for monotonicity, in order to improve the program speed.
; RESTRICTIONS:
; TABINV will abort if XARR is not monotonic. (Equality of
; neighboring values in XARR is allowed but results may not be
; unique.) This requirement may mean that input vectors with padded
; zeroes could cause routine to abort.
;
; PROCEDURE:
; VALUE_LOCATE() is used to find the values XARR[I]
; and XARR[I+1] where XARR[I] < X < XARR[I+1].
; IEFF is then computed using linear interpolation
; between I and I+1.
; IEFF = I + (X-XARR[I]) / (XARR[I+1]-XARR[I])
; Let N = number of elements in XARR
; if x < XARR[0] then IEFF is set to 0
; if x > XARR[N-1] then IEFF is set to N-1
;
; EXAMPLE:
; Set all flux values of a spectrum (WAVE vs FLUX) to zero
; for wavelengths less than 1150 Angstroms.
;
; IDL> tabinv, wave, 1150.0, I
; IDL> flux[ 0:fix(I) ] = 0.
;
; FUNCTIONS CALLED:
; None
; REVISION HISTORY:
; Adapted from the IUE RDAF January, 1988
; More elegant code W. Landsman August, 1989
; Mod to work on 2 element decreasing vector August, 1992
; Updated for V5.3 to use VALUE_LOCATE() W. Landsman January 2000
; Work when both X and Xarr are integers W. Landsman August 2001
; Use ARRAY_EQUAL, always internal double precision W.L. July 2009
; Allow Double precision output, faster test for monotonicity.
; WL, January 2012
;-
On_error,2
compile_opt idl2
if N_params() LT 3 then begin
print,'Syntax- TABINV, XARR, X, I, [/FAST]'
return
endif
Npoints = N_elements(xarr) & npt= npoints - 1
if ( Npoints LE 1 ) then message, /TRACE, $
'Search vector (first parameter) must contain at least 2 elements'
do_double= (size(xarr,/tname) EQ 'DOUBLE') || (size(x,/TNAME) EQ 'DOUBLE')
if ~keyword_set(fast) then begin
; Test for monotonicity (everywhere increasing or decreasing vector)
i = xarr[1:*] GE xarr
test = array_equal( i, 1b) || array_equal(i, 0b)
if ~test then message, $
'ERROR - First parameter must be a monotonic vector'
endif
if do_double then ieff = double( VALUE_LOCATE(xarr,x)) else $
ieff = float( VALUE_LOCATE(xarr,x))
g = where( (ieff LT npt) and (ieff GE 0), Ngood)
if Ngood GT 0 then begin
neff = ieff[g]
x0 = double(xarr[neff])
diff = x[g] - x0
ieff[g] = neff + diff / (xarr[neff+1] - x0 )
endif
ieff = ieff > 0.0
return
end