Special Functions

This tutorial shows interfaces and examples of special_functions package.

Python Interface

Syntax

Return type

Symbol

Description

besselj(nu, z, n)

double, double complex

\[\partial^n J_{\nu}/\partial z^n\]

Bessel function of the first kind

bessely(nu, z, n)

double, double complex

\[\partial^n Y_{\nu}/\partial z^n\]

Bessel function of the second kind (Weber function)

besseli(nu, z, n)

double, double complex

\[\partial^n I_{\nu}/\partial z^n\]

Modified Bessel function of the first kind

besselk(nu, z, n)

double, double complex

\[\partial^n I_{\nu}/\partial z^n\]

Modified Bessel function of the second kind

besselh(nu, k, z, n)

double complex

\[\partial^n H^{(k)}_{\nu}/\partial z^n\]

Bessel function of the third kind (Hankel function)

loggamma(nu, x, n)

double

\[\log \Gamma(x)\]

Natural logarithm of Gamma function

Input Arguments

Variable

Type(s)

Symbol

Description

nu

double

\[\nu\]

The parameter of the Bessel functions.

k

int

\[k\]

Canbe either 1 and 2 and determines the type of Hankel function.

z

double, double complex

\[z\]

The real or complex input argument of the Bessel functions.

x

double

\[x\]

The real input argument of functions.

Examples in Python

In the example below, we compute the modified Bessel function of the second kind $ \partial`^n K_{:nbsphinx-math:nu`}(z) / \partial `z^n$ where :math:nu` is the parameter of the Bessel function, \(z\) can be real or complex, and \(n\) is the order of the derivative of the function. \(n = 0\) means no derivative.

[3]:
import special_functions as sf
nu = 1.5
z = 2.0
n = 0
sf.besselk(nu, z, n)
[3]:
0.17990665795209218

Now, we try a complex argument \(z = 2 + j\) (where \(j^2 = -1\)) and the first derivative of the function:

[12]:
z = 2.0 + 1.0j
n = 1
sf.besselk(nu, z, n)
[12]:
(-0.00937048840778705+0.21078407796464216j)

Cython Interface

In Cython, there are two syntaxes for each function depending on whether the input argument is real or complex.

  • For real arguments, the syntaxes are the same as the Python interface. For example: besselk.

  • For complex arguments, add the letter c to the begining of the function, for example: cbesselk.

The table below shows the function signatures for real and complex cases:

Real functions

Complex functions

double besselj(double nu, double x, int n)

double complex cbesselj(double nu, double complex z, int n)

double bessely(double nu, double x, int n)

double complex cbessely(double nu, double complex z, int n)

double besseli(double nu, double x, int n)

double complex cbesseli(double nu, double complex z, int n)

double besselk(double nu, double x, int n)

double complex cbesselk(double nu, double complex z, int n)

double complex besselh(double nu, int k, double x, int n)

double complex cbesselh(double nu, int k, double complex z, int n)

double loggamma(double x)

N/A

Examples in Cython

[19]:
%load_ext Cython
The Cython extension is already loaded. To reload it, use:
  %reload_ext Cython
[17]:
%%cython

# Use this in a *.pyx file
cimport special_functions as sf

# Declare typed input variables
cdef double nu = 1.5
cdef double x = 2.0
cdef int n = 0

# Declare typed output variable
cdef double K_real

# The 'nogil' statement below is optional.
with nogil:
    K_real = sf.besselk(nu, x, n)

# Print the output
print(K_real)
0.17990665795209218

Now, we try the same code in the above, but for the complex argument \(z = 2.0 + j\).

[18]:
%%cython

# Use this in a *.pyx file
cimport special_functions as sf

# Declare typed input variables
cdef double nu = 1.5
cdef double complex z = 2.0 + 1.0j
cdef int n = 0

# Declare typed output variable
cdef double complex K_complex

# The 'nogil' statement below is optional.
with nogil:
    K_complex = sf.cbesselk(nu, z, n)

print(K_complex)
(0.031409508972862196-0.157309366284669j)