diff options
Diffstat (limited to 'lib/pure/numeric.nim')
-rw-r--r-- | lib/pure/numeric.nim | 29 |
1 files changed, 12 insertions, 17 deletions
diff --git a/lib/pure/numeric.nim b/lib/pure/numeric.nim index 593370fbb..8ef5fabda 100644 --- a/lib/pure/numeric.nim +++ b/lib/pure/numeric.nim @@ -10,15 +10,16 @@ type TOneVarFunction* =proc (x:float):float -proc brent*(xmin,xmax:float ,function:TOneVarFunction, rootx,rooty:var float,tol:float,maxiter=1000):bool= +proc brent*(xmin,xmax:float ,function:TOneVarFunction, tol:float,maxiter=1000): + tuple[rootx, rooty: float, success: bool]= ## Searches `function` for a root between `xmin` and `xmax` ## using brents method. If the function value at `xmin`and `xmax` has the ## same sign, `rootx`/`rooty` is set too the extrema value closest to x-axis - ## and false is returned. - ## Otherwise there exists at least one root and true is always returned. + ## and succes is set to false. + ## Otherwise there exists at least one root and success is set to true. ## This root is searched for at most `maxiter` iterations. ## If `tol` tolerance is reached within `maxiter` iterations - ## the root refinement stops and true is returned. + ## the root refinement stops and success=true. # see http://en.wikipedia.org/wiki/Brent%27s_method var @@ -37,13 +38,9 @@ proc brent*(xmin,xmax:float ,function:TOneVarFunction, rootx,rooty:var float,tol if fa*fb>=0: if abs(fa)<abs(fb): - rootx=a - rooty=fa - return false + return (a,fa,false) else: - rootx=b - rooty=fb - return false + return (b,fb,false) if abs(fa)<abs(fb): swap(fa,fb) @@ -55,13 +52,13 @@ proc brent*(xmin,xmax:float ,function:TOneVarFunction, rootx,rooty:var float,tol else: #secant rule s = b - fb * (b - a) / (fb - fa) tmp2 = (3.0 * a + b) / 4.0 - if (not(((s > tmp2) and (s < b)) or ((s < tmp2) and (s > b)))) or - (mflag and (abs(s - b) >= (abs(b - c) / 2.0))) or - (not mflag and (abs(s - b) >= (abs(c - d) / 2.0))): + if not((s > tmp2 and s < b) or (s < tmp2 and s > b)) or + (mflag and abs(s - b) >= (abs(b - c) / 2.0)) or + (not mflag and abs(s - b) >= abs(c - d) / 2.0): s=(a+b)/2.0 mflag=true else: - if ((mflag and (abs(b - c) < tol)) or (not mflag and (abs(c - d) < tol))): + if (mflag and (abs(b - c) < tol)) or (not mflag and (abs(c - d) < tol)): s=(a+b)/2.0 mflag=true else: @@ -83,6 +80,4 @@ proc brent*(xmin,xmax:float ,function:TOneVarFunction, rootx,rooty:var float,tol if i>maxiter: break - rootx=b - rooty=fb - return true + return (b,fb,true) |