Skip to content

Instantly share code, notes, and snippets.

@cshaa
Created April 25, 2019 20:05
Show Gist options
  • Save cshaa/a0199c4f40b43bb8116810daa46dd92d to your computer and use it in GitHub Desktop.
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
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