Fixed a mixed bag of stuff poly and numeric

This commit is contained in:
Robert Persson 2013-07-03 01:15:31 +02:00
commit 2cae55ae04
2 changed files with 42 additions and 51 deletions

View file

@ -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)