zbrent.pro

来自「basic median filter simulation」· PRO 代码 · 共 144 行

PRO
144
字号
function ZBRENT, x1, x2, FUNC_NAME=func_name,    $                         MAX_ITERATIONS=maxit, TOLERANCE=TOL;+; NAME:;     ZBRENT; PURPOSE:;     Find the zero of a 1-D function up to specified tolerance.; EXPLANTION:;     This routine assumes that the function is known to have a zero.;     Adapted from procedure of the same name in "Numerical Recipes" by;     Press et al. (1992), Section 9.3;; CALLING:;       x_zero = ZBRENT( x1, x2, FUNC_NAME="name", MaX_Iter=, Tolerance= );; INPUTS:;       x1, x2 = scalars, 2 points which bracket location of function zero,;                                               that is, F(x1) < 0 < F(x2).;       Note: computations are performed with;       same precision (single/double) as the inputs and user supplied function.;; REQUIRED INPUT KEYWORD:;       FUNC_NAME = function name (string);               Calling mechanism should be:  F = func_name( px );               where:  px = scalar independent variable, input.;                       F = scalar value of function at px,;                           should be same precision (single/double) as input.;; OPTIONAL INPUT KEYWORDS:;       MAX_ITER = maximum allowed number iterations, default=100.;       TOLERANCE = desired accuracy of minimum location, default = 1.e-3.;; OUTPUTS:;       Returns the location of zero, with accuracy of specified tolerance.;; PROCEDURE:;       Brent's method to find zero of a function by using bracketing,;       bisection, and inverse quadratic interpolation,;; EXAMPLE:;       Find the root of the COSINE function between 1. and 2.  radians;;        IDL> print, zbrent( 1, 2, FUNC = 'COS');;       and the result will be !PI/2 within the specified tolerance; MODIFICATION HISTORY:;       Written, Frank Varosi NASA/GSFC 1992.;       FV.1994, mod to check for single/double prec. and set zeps accordingly.;       Converted to IDL V5.0   W. Landsman   September 1997;       Use MACHAR() to define machine precision   W. Landsman September 2002;-        if N_params() LT 2 then begin             print,'Syntax - result = ZBRENT( x1, x2, FUNC_NAME = ,'             print,'                  [ MAX_ITER = , TOLERANCE = ])'             return, -1        endif        if N_elements( TOL ) NE 1 then TOL = 1.e-3        if N_elements( maxit ) NE 1 then maxit = 100        if size(x1,/TNAME) EQ 'DOUBLE' OR size(x2,/TNAME) EQ 'DOUBLE' then begin                xa = double( x1 )                xb = double( x2 )                zeps = (machar(/DOUBLE)).eps   ;machine epsilon in double.          endif else begin                xa = x1                xb = x2                zeps = (machar(/DOUBLE)).eps   ;machine epsilon, in single            endelse        fa = call_function( func_name, xa )        fb = call_function( func_name, xb )        fc = fb        if (fb*fa GT 0) then begin                message,"root must be bracketed by the 2 inputs",/INFO                return,xa           endif        for iter = 1,maxit do begin                if (fb*fc GT 0) then begin                        xc = xa                        fc = fa                        Din = xb - xa                        Dold = Din                   endif                if (abs( fc ) LT abs( fb )) then begin                        xa = xb   &   xb = xc   &   xc = xa                        fa = fb   &   fb = fc   &   fc = fa                   endif                TOL1 = 0.5*TOL + 2*abs( xb ) * zeps     ;Convergence check                xm = (xc - xb)/2.                if (abs( xm ) LE TOL1) OR (fb EQ 0) then return,xb                if (abs( Dold ) GE TOL1) AND (abs( fa ) GT abs( fb )) then begin                        S = fb/fa       ;attempt inverse quadratic interpolation                        if (xa EQ xc) then begin                                p = 2 * xm * S                                q = 1-S                          endif else begin                                T = fa/fc                                R = fb/fc                                p = S * (2*xm*T*(T-R) - (xb-xa)*(R-1) )                                q = (T-1)*(R-1)*(S-1)                           endelse                        if (p GT 0) then q = -q                        p = abs( p )                        test = ( 3*xm*q - abs( q*TOL1 ) ) < abs( Dold*q )                        if (2*p LT test)  then begin                                Dold = Din              ;accept interpolation                                Din = p/q                          endif else begin                                Din = xm                ;use bisection instead                                Dold = xm                           endelse                  endif else begin                        Din = xm    ;Bounds decreasing to slowly, use bisection                        Dold = xm                   endelse                xa = xb                fa = fb         ;evaluate new trial root.                if (abs( Din ) GT TOL1) then xb = xb + Din $                                        else xb = xb + TOL1 * (1-2*(xm LT 0))                fb = call_function( func_name, xb )          endfor        message,"exceeded maximum number of iterations: "+strtrim(iter,2),/INFOreturn, xbend

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?