Created
April 25, 2019 20:05
-
-
Save cshaa/a0199c4f40b43bb8116810daa46dd92d to your computer and use it in GitHub Desktop.
Lambert W function, or the product logarithm, for LibreOffice and OpenOffice. Original version for Excel from here: http://www.vbforums.com/showthread.php?683003-Lambert-W-function-for-Excel-work-on-real-and-complex-number
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Attribute VB_Name = "Module1" | |
Function Complex(a As Double, b As Double) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
Complex = svc.callFunction("COMPLEX",Array(a,b)) | |
End Function | |
Function ImProduct(a As Any, b As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImProduct = svc.callFunction("IMPRODUCT",Array(a,b)) | |
End Function | |
Function ImReal(a As Any) As Double | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImReal = svc.callFunction("IMREAL",Array(a)) | |
End Function | |
Function Imaginary(a As Any) As Double | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
Imaginary = svc.callFunction("IMAGINARY",Array(a)) | |
End Function | |
Function ImExp(a As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImExp = svc.callFunction("IMEXP",Array(a)) | |
End Function | |
Function ImSum(a As Any, b As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImSum = svc.callFunction("IMSUM",Array(a, b)) | |
End Function | |
Function ImSub(a As Any, b As Double) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImSub = svc.callFunction("IMSUB",Array(a, b)) | |
End Function | |
Function ImSqrt(a As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImSqrt = svc.callFunction("IMSQRT",Array(a)) | |
End Function | |
Function ImLn(a As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImLn = svc.callFunction("IMLN",Array(a)) | |
End Function | |
Function ImDiv(a As Any, b As Any) As Any | |
Dim svc As Object | |
svc = createUnoService("com.sun.star.sheet.FunctionAccess") | |
ImDiv = svc.callFunction("IMDIV",Array(a, b)) | |
End Function | |
Public Function LambertW(x As Double) | |
' Lambert W function for x (real number) | |
' real result, domain: [-1/e , infinity] | |
' complex result, domain: [infinity , infinity] | |
' return: Complex number (in the form a+bi) | |
LambertW = LambertWc(x, 0) | |
End Function | |
Public Function LambertWc(a As Double, b As Double) | |
' Lambert W function for a+bi | |
' real result, domain: [-1/e , infinity] | |
' complex result, domain: [infinity , infinity] | |
' return: Complex number (in the form a+bi) | |
Dim z, x, z1, z2, z3, q1 | |
If a = 0 And b = 0 Then | |
z = 0 | |
Else | |
' complex parameter | |
x = Complex(a, b) | |
' approx initial value = sqtr(2*(1+e*x))-1 | |
z = ImProduct(x, ImExp(1)) | |
z = ImProduct(2, ImSum(1, z)) | |
If ImReal(z) = 0 And Imaginary(z) = 0 Then | |
z = -1 | |
Else | |
z = ImSub(ImSqrt(z), 1) | |
For i = 1 To 100 | |
' the comments are right to left evaluation | |
' z1 = 0 sub z sub ln x div z | |
z1 = ImSub(z, ImLn(ImDiv(x, z))) | |
z1 = ImSub(0, z1) | |
' q1 = 2 mul (1 add z) mul 1 add z add 2 mul z1 div 3 | |
z2 = ImProduct(2, ImDiv(z1, 3)) | |
z2 = ImSum(1, ImSum(z, z2)) | |
z2 = ImProduct(ImSum(z, 1), z2) | |
q1 = ImProduct(2, z2) | |
' z1 = z mul 1 add (z1 div 1 add z) mul (q1 sub z1) div q1 sub 2 mul z1 | |
z2 = ImSub(q1, ImProduct(2, z1)) | |
z2 = ImDiv(ImSub(q1, z1), z2) | |
z3 = ImDiv(z1, ImSum(1, z)) | |
z2 = ImSum(1, ImProduct(z3, z2)) | |
z1 = ImProduct(z, z2) | |
If z = z1 Then | |
Exit For | |
Else | |
z = z1 | |
End If | |
Next | |
End If | |
End If | |
LambertWc = z | |
End Function | |
Sub Main | |
End Sub |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment