Viewing contents of file '../idllib/contrib/meron/confrac.pro'
Function Confrac, a, b, x, afunction = afun, bfunction = bfun, $
    epsilon = eps, relative = rel, error = erv, status = stat

;+
; NAME:
;    CONFRAC
; VERSION:
;	3.0
; PURPOSE:
;	Performs continued fraction evaluation.
; CATEGORY:
;	Mathematical function (general).
; CALLING SEQUENCE:
;	Result = CONFRAC( A, B [,X [, keywords]])
; INPUTS:
;    A
;	A numeric scalar, vector or a 2-D array.  A(i,*) contains the i-th
;	A coefficient(s) of the continued fraction.
;    B
;	Same as A for the B coefficient(s).  A and B must agree in their first
;	dimension, i.e. if A is an (N,M) array (including the possibility of
;	M = 1) then B must be an (N,M') array, with an arbitrary M'.
; OPTIONAL INPUT PARAMETERS:
;    X
;	Numeric, otherwise arbitrary.  When provided, X is used together with
;	A and B to determine the continued fraction coefficients.
; KEYWORD PARAMETERS:
;    AFUNCTION
;	Name of a function to be used (with the CALL_FUNCTION routine) to 
;	determine the A coefficients.  Optional.
;    BFUNCTION
;	Same as AFUNCTION for the B coefficients.  Optional.
;    EPSILON
;	Smallness parameter, determining the allowed evaluation error.  
;	Optional.  Default values are machine dependent, established through
;	TOLER which calls MACHAR().
;    /RELATIVE
;	Switch.  If set, EPS represent the allowed relative evaluation error.
;    ERROR
;	Optional output, see below.
;    STATUS
;	Optional output, see below.
; OUTPUTS:
;	Returns the value(s) of the continued fraction.  The result is of the
;	same format as X (a scalar if X is not given).  The type of the result 
;	is the highest of the types of A, B, and X, but no lower than 4 (float).
; OPTIONAL OUTPUT PARAMETERS:
;    ERROR
;	The name of the variable to receive the estimated evaluation error.
;	Given in the same format as X (scalar if X isn't provided).  If 
;	RELATIVE is set the error returned is relative.  
;    STATUS
;	The name of the variable to receive evaluation status information.  
;	Same format as ERROR.  Possible values are:
;	    0 - evaluation didn't converge.
;	    1 - OK.
; COMMON BLOCKS:
;	None.
; SIDE EFFECTS:
;	None.
; RESTRICTIONS:
;	None other then the restrictions on A, B, as mentioned above.
; PROCEDURE:
;	CONFRAC evaluates continued fractions of the form
;	
;		res = a(0)/(b(0) + a(1)/(b(1) + a(2)/(b(2) + ......
;	
;	Using the recurrence relation from Numerical Recipies, Sec 5.2.  The
;	designation of the coefficients a(i), b(i) depends on the data 
;	provided, as follows:
;	
;	1)  If X isn't provided then a(i) = A(i) (or A(i,0) if A is a 2-dim 
;	    array) and same is true for b(i) (using B)
;	2)  If X is provided then a(i) = Sum_j(A(i,j)*X^j) and the same for b(i)
;	    using B.  In other words the fraction coefficients are polynomials
;	    in X, using columns of A, B, as polynomial coefficients.  Note that
;	    if A and/or B are one dimensional arrays then only X^0 is used i.e.
;	    we are back to case 1.
;	3)  If AFUN and/or BFUN are provided then a(i) = afun(x,A(i,*),i) and
;	    same for b(i) with BFUN and B.  The functions can be arbitrary but
;	    they must accept at least three parameters.
;
;	CONFRAC uses CAST, DEFAULT, FPU_FIX, POLEVAL, TOLER and TYPE from MIDL.
; MODIFICATION HISTORY:
;	Created 20-DEC-1994 by Mati Meron.
;	Modified 10-SEP-1998 by Mati Meron.  Underflow filtering added.
;-

    on_error, 1

    if n_params() lt 2 then message, 'both A and B are needed!'
    sia = size(a)
    sib = size(b)
    flen = (sia)(sia(0)<1)
    if (sib)(sib(0)<1) ne flen then message, "Unequal arrays' lengths!"
    afl = n_elements(afun) gt 0
    bfl = n_elements(bfun) gt 0

    dtyp = max([Type(a),Type(b),Type(x),4])
    weps = Default(eps,Toler(type=dtyp))
    relfl = keyword_set(rel)

    wx = Default(x,1.,low = dtyp)
    nox = 1. + 0.*wx
    erv = (machar(double = dtyp eq 5 or dtyp eq 9)).xmax*Cast(nox,4,5)
    stat = 0*fix(nox)
    norfl = 0

    ap = 1.
    bp = 0.
    al = 0.
    bl = 1.
    i = 0l

    repeat begin
	if norfl then begin
	    ap = ap*norm
	    bp = bp*norm
	    norfl = 0
	endif

	if afl then ai = call_function(afun,wx,i,a(i,*)) $
	else ai = Poleval(wx,a(i,*))
	if bfl then bi = call_function(bfun,wx,i,b(i,*)) $
	else bi = Poleval(wx,b(i,*))

	an = al*bi + ap*ai
	bn = bl*bi + bp*ai
	ap = al
	bp = bl
	al = an
	bl = bn

	binz = where(bn ne 0, noz)
	if noz gt 0 then begin
	    norfl = 1
	    norm = nox
	    norm(binz) = 1./bn(binz)
	    al = al*norm
	    bl = bl*norm
	    erv(binz) = (abs(al - ap))(binz)
	    if relfl then erv(binz) = erv(binz)/(abs(al) > weps)(binz)
	    stat(binz) = fix(erv(binz) le weps)
	endif
	i = i + 1l
    endrep until i eq flen or min(stat) eq 1

    return, FPU_fix(al)
end