12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- #
- #
- # Nim's Runtime Library
- # (c) Copyright 2013 Robert Persson
- #
- # See the file "copying.txt", included in this
- # distribution, for details about the copyright.
- #
- ## **Warning:** This module will be moved out of the stdlib and into a
- ## Nimble package, don't use it.
- type OneVarFunction* = proc (x: float): float
- {.deprecated: [TOneVarFunction: OneVarFunction].}
- proc brent*(xmin,xmax:float, function:OneVarFunction, 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 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 success=true.
- # see http://en.wikipedia.org/wiki/Brent%27s_method
- var
- a=xmin
- b=xmax
- c=a
- d=1.0e308
- fa=function(a)
- fb=function(b)
- fc=fa
- s=0.0
- fs=0.0
- mflag:bool
- i=0
- tmp2:float
- if fa*fb>=0:
- if abs(fa)<abs(fb):
- return (a,fa,false)
- else:
- return (b,fb,false)
- if abs(fa)<abs(fb):
- swap(fa,fb)
- swap(a,b)
- while fb!=0.0 and abs(a-b)>tol:
- if fa!=fc and fb!=fc: # inverse quadratic interpolation
- s = a * fb * fc / (fa - fb) / (fa - fc) + b * fa * fc / (fb - fa) / (fb - fc) + c * fa * fb / (fc - fa) / (fc - fb)
- 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):
- s=(a+b)/2.0
- mflag=true
- else:
- if (mflag and (abs(b - c) < tol)) or (not mflag and (abs(c - d) < tol)):
- s=(a+b)/2.0
- mflag=true
- else:
- mflag=false
- fs = function(s)
- d = c
- c = b
- fc = fb
- if fa * fs<0.0:
- b=s
- fb=fs
- else:
- a=s
- fa=fs
- if abs(fa)<abs(fb):
- swap(a,b)
- swap(fa,fb)
- inc i
- if i>maxiter:
- break
- return (b,fb,true)
|