Public Sub funcd(value As Double, Byref result As double, Byref derivative As Double)
// funcd example matching the type funcdDelegate
// Do your math here receiving "value" and returning the result and the first derivative
result = cos(value) - value * value * value
derivative = -sin(value ) -3 * value * value
End Sub
Have in mind that I’m not validating the algorithm or your function, just translating them as is.
Public Sub main()
// Example passing the delegated function funcd above
Var root as double = rtsafe((New funcdDelegate(AddressOf funcd)), 0, 1) // bisection [0,1]
End Sub
It’s useful for passing different functions to be used by another functions, as:
Public Sub main()
// Example using different functions (of the funcdDelegate type) and calculating their roots
Var root1, root2, root3 as double
root1 = rtsafe((New funcdDelegate(AddressOf MyFuncd1)), 0, 1) // bisection [0,1]
root2 = rtsafe((New funcdDelegate(AddressOf MyFuncd2)), 0, 1) // bisection [0,1]
root3 = rtsafe((New funcdDelegate(AddressOf MyFuncd3)), 0, 1) // bisection [0,1]
End Sub
I learned today that besides Delegates in Xojo being Objects, they have an internal different treatment and auto instantiate themselves when sent as Pointers in parameters, so, this may work:
Public Sub main()
// Example using different functions (of the funcdDelegate type) and calculating their roots
Var root1, root2, root3 as double
root1 = rtsafe(AddressOf MyFuncd1, 0, 1) // bisection [0,1]
root2 = rtsafe(AddressOf MyFuncd2, 0, 1) // bisection [0,1]
root3 = rtsafe(AddressOf MyFuncd3, 0, 1) // bisection [0,1]
End Sub
Hi Rick,
I want to compare rtsafe() to NewtonRapson().
Both use same fx and fdx.
this is NewtonRaphson() where funcd must be invoked.
NewtRaphson(x1 as double, x2 as double, maxiter as integer=100, accuracy as double = 3E-6) as double
dim xi,xf,s,eps as double
dim i as integer
eps =accuracy
i=0
xi=(x1+x2)*.5
while (abs(s)>eps or i<maxiter)
i=i+1
xf=xi-fx(xi)/dfdx(xi) //this line must be reached by funcd instead of “dfdx, derivative” and "fx, function)
s=xf-xi
xi=xf
Hi Rick,
rtsafe() translate is running properly, so i need to know how many loops are done.
How to return the number of iteration, i mean root and iter.
Public Function rtsafei(funcDeriv As funcdDelegate, x1 As Double, x2 As Double, maxIter As Integer = 100, accuracy As Double = 3E-8) as Pair // root : num of iterations
Var j As Integer
Var df,dx,dxold,f,fh,fl As Double
Var temp,xh,xl, rts As Double
funcDeriv.Invoke(x1,fl,df)
funcDeriv.Invoke(x2,fh,df)
If ((fl > 0.0 And fh > 0.0) Or (fl < 0.0 And fh < 0.0)) Then
Var ex As New RuntimeException
ex.Message = "Root must be bracketed in rtsafe"
Raise ex
Return 0.0 : 0
End If
If (fl = 0.0) Then Return x1 : 1
If (fh = 0.0) Then Return x2 : 1
If (fl < 0.0) Then
xl = x1
xh = x2
Else
xh = x1
xl = x2
End If
rts = 0.5 *(x1 + x2)
dxold = abs(x2 - x1)
dx = dxold
funcDeriv.Invoke(rts,f,df)
For j = 1 To maxIter
If (((rts - xh) *df - f) *((rts - xl) *df - f) > 0.0) Or (abs(2.0 *f) > abs(dxold *df)) Then
dxold = dx
dx = 0.5 *(xh - xl)
rts = xl + dx
If (xl = rts) Then Return rts : j
Else
dxold = dx
dx = f / df
temp = rts
rts = rts - dx
If (temp = rts) Then Return rts : j
End If
If (abs(dx) < accuracy) Then Return rts : j
funcDeriv.Invoke(rts, f, df)
If (f < 0.0) Then
xl = rts
Else
xh = rts
End If
Next
Var ex As New RuntimeException
ex.Message = "Maximum number of iterations exceeded in rtsafe"
Raise ex
Return 0.0 : maxIter + 1
End Function
// rtsafei() returns a “Pair”, where the left is root, and right the number of iterations
// I typed directly here without testing. Check it.
Rick its running properly Rtsafe C code gives same root value with 3 loops.
Same under matlab, accuracy used = 1.0E-7
I don’t calculate execution time but so fast, less then 0.1 sec. under xojo with 6 iter.
attached screenshot NR brackted, NR xo=0, Combined NR/Bisect (brackted) , Rtsafe and Rtsa
The original C code uses a float, half of the current supported decimal accuracy of the Xojo code using Doubles, so probably this version goes a bit further looking for more precise matches dividing dx with “more decimals” and it takes the double if its iterations to find the exact roots or dx < accuracy.
Yes i agree xojo is running in 64bit environment.
Anyway xojo is so fast, of course less than low level C.
Big difference when code is interpreted running IDE and when compiled.
I do a test (benchmark) for floating; 4.5 sec (IDE) and 0.8 sec (compiled) on a Proc i7 (4th gen) under win 10.
Thank a lot, Rick .