To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit 2d3b4974 authored by Christoph Goering's avatar Christoph Goering
Browse files

Merge branch 'patch/Updating_Special_Functions' into 'developer'

reworked special functions (tackling issue #34)

See merge request !64
parents d098288b a0b34a82
Pipeline #89219 passed with stages
in 4 minutes and 20 seconds
......@@ -4,14 +4,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.6] - 2021-03-01
### Added - Cyrill Mast
- Spherical Hankel function of the second kind
### Changed
- changed names of special functions
- updated tests for special funcitons
## [Unreleased]
### Added - Jonas Fankhauser
- Streaming, Scattering, and ARF for Doinikov's Theory of viscoelastic fluids
of 2021
## [0.2.4] - 2021-03-01
## [0.2.5] - 2021-03-01
### Added - Cyrill Mast
- Spherical Neumann Functions
......
......@@ -2,7 +2,7 @@ from typing import Callable, Optional, Tuple, Iterable
import numpy as np
from scipy.integrate import romb, quad
from scipy.special import hankel1, lpmv, jv, yv, factorial
from scipy.special import hankel1, hankel2, lpmv, jv, yv, factorial
from gorkov import log
......@@ -203,7 +203,7 @@ class SpecialFunctions(object):
- 20 * (-6 + z**2)) / z**4)
@staticmethod
def jn(n: int, z: complex) -> complex:
def besselj(n: int, z: complex) -> complex:
"""Order :attr:`n` Spherical Bessel function of the first kind
:param n: Order
......@@ -215,7 +215,7 @@ class SpecialFunctions(object):
return sqrt(pi / (2 * z)) * jv(n + 0.5, z)
@classmethod
def d_jn(cls, n: int, z: complex) -> complex:
def d1_besselj(cls, n: int, z: complex) -> complex:
"""First derivative of order :attr:`n` Spherical Bessel function of the
first
kind
......@@ -226,10 +226,10 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return -cls.jn(n + 1, z) + (n / z) * cls.jn(n, z)
return -cls.besselj(n + 1, z) + (n / z) * cls.besselj(n, z)
@classmethod
def d2_jn(cls, n: int, z: complex) -> complex:
def d2_besselj(cls, n: int, z: complex) -> complex:
"""Second derivative of order :attr:`n` Spherical Bessel function of
the first kind
......@@ -239,11 +239,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d2(n, z) * cls.jn(n, z)
+ cls._a1_d2(n, z) * cls.jn(n + 1, z))
return (cls._a0_d2(n, z) * cls.besselj(n, z)
+ cls._a1_d2(n, z) * cls.besselj(n + 1, z))
@classmethod
def d3_jn(cls, n: int, z: complex) -> complex:
def d3_besselj(cls, n: int, z: complex) -> complex:
"""Third derivative of order :attr:`n` Spherical Bessel function of the
first
kind
......@@ -254,11 +254,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d3(n, z) * cls.jn(n, z)
+ cls._a1_d3(n, z) * cls.jn(n + 1, z))
return (cls._a0_d3(n, z) * cls.besselj(n, z)
+ cls._a1_d3(n, z) * cls.besselj(n + 1, z))
@classmethod
def d4_jn(cls, n: int, z: complex) -> complex:
def d4_besselj(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Bessel function of
the first kind
......@@ -268,11 +268,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d4(n, z) * cls.jn(n, z)
+ cls._a1_d4(n, z) * cls.jn(n + 1, z))
return (cls._a0_d4(n, z) * cls.besselj(n, z)
+ cls._a1_d4(n, z) * cls.besselj(n + 1, z))
@staticmethod
def yn(n: int, z: complex) -> complex:
def bessely(n: int, z: complex) -> complex:
"""Order :attr:`n` Spherical Bessel function of the second kind
:param n: Order
......@@ -284,7 +284,7 @@ class SpecialFunctions(object):
return sqrt(pi / (2 * z)) * yv(n + 0.5, z)
@classmethod
def d_yn(cls, n: int, z: complex) -> complex:
def d1_bessely(cls, n: int, z: complex) -> complex:
"""First derivative of order :attr:`n` Spherical Bessel function of
the second kind
......@@ -294,10 +294,10 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return -cls.yn(n + 1, z) + (n / z) * cls.yn(n, z)
return -cls.bessely(n + 1, z) + (n / z) * cls.bessely(n, z)
@classmethod
def d2_yn(cls, n: int, z: complex) -> complex:
def d2_bessely(cls, n: int, z: complex) -> complex:
"""Second derivative of order :attr:`n` Spherical Bessel function of
the second kind
......@@ -307,11 +307,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d2(n, z) * cls.yn(n, z)
+ cls._a1_d2(n, z) * cls.yn(n + 1, z))
return (cls._a0_d2(n, z) * cls.bessely(n, z)
+ cls._a1_d2(n, z) * cls.bessely(n + 1, z))
@classmethod
def d3_yn(cls, n: int, z: complex) -> complex:
def d3_bessely(cls, n: int, z: complex) -> complex:
"""Third derivative of order :attr:`n` Spherical Bessel function of
the second kind
......@@ -321,11 +321,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d3(n, z) * cls.yn(n, z)
+ cls._a1_d3(n, z) * cls.yn(n + 1, z))
return (cls._a0_d3(n, z) * cls.bessely(n, z)
+ cls._a1_d3(n, z) * cls.bessely(n + 1, z))
@classmethod
def d4_yn(cls, n: int, z: complex) -> complex:
def d4_bessely(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Bessel function of
the second kind
......@@ -335,11 +335,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d4(n, z) * cls.yn(n, z)
+ cls._a1_d4(n, z) * cls.yn(n + 1, z))
return (cls._a0_d4(n, z) * cls.bessely(n, z)
+ cls._a1_d4(n, z) * cls.bessely(n + 1, z))
@staticmethod
def hn(n: int, z: complex) -> complex:
def hankelh1(n: int, z: complex) -> complex:
"""Order :attr:`n` Spherical Hankel function of the first kind
:param n: order
......@@ -351,7 +351,7 @@ class SpecialFunctions(object):
return sqrt(pi / (2 * z)) * hankel1(n + 0.5, z)
@classmethod
def d_hn(cls, n: int, z: complex) -> complex:
def d1_hankelh1(cls, n: int, z: complex) -> complex:
"""First derivative of order :attr:`n` Spherical Hankel function of the
first
kind
......@@ -362,10 +362,10 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return -cls.hn(n + 1, z) + (n / z) * cls.hn(n, z)
return -cls.hankelh1(n + 1, z) + (n / z) * cls.hankelh1(n, z)
@classmethod
def d2_hn(cls, n: int, z: complex) -> complex:
def d2_hankelh1(cls, n: int, z: complex) -> complex:
"""Second derivative of order :attr:`n` Spherical Hankel function of
the first kind
......@@ -375,11 +375,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d2(n, z) * cls.hn(n, z)
+ cls._a1_d2(n, z) * cls.hn(n + 1, z))
return (cls._a0_d2(n, z) * cls.hankelh1(n, z)
+ cls._a1_d2(n, z) * cls.hankelh1(n + 1, z))
@classmethod
def d3_hn(cls, n: int, z: complex) -> complex:
def d3_hankelh1(cls, n: int, z: complex) -> complex:
"""Third derivative of order :attr:`n` Spherical Hankel function of
the first kind
......@@ -389,11 +389,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d3(n, z) * cls.hn(n, z)
+ cls._a1_d3(n, z) * cls.hn(n + 1, z))
return (cls._a0_d3(n, z) * cls.hankelh1(n, z)
+ cls._a1_d3(n, z) * cls.hankelh1(n + 1, z))
@classmethod
def d4_hn(cls, n: int, z: complex) -> complex:
def d4_hankelh1(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Hankel function of
the first kind
......@@ -403,11 +403,11 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d4(n, z) * cls.hn(n, z)
+ cls._a1_d4(n, z) * cls.hn(n + 1, z))
return (cls._a0_d4(n, z) * cls.hankelh1(n, z)
+ cls._a1_d4(n, z) * cls.hankelh1(n + 1, z))
@classmethod
def d5_hn(cls, n: int, z: complex) -> complex:
def d5_hankelh1(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Hankel function of
the first kind
......@@ -417,11 +417,94 @@ class SpecialFunctions(object):
:type z: complex
:rtype: complex
"""
return (cls._a0_d5(n, z) * cls.hn(n, z)
+ cls._a1_d5(n, z) * cls.hn(n + 1, z))
return (cls._a0_d5(n, z) * cls.hankelh1(n, z)
+ cls._a1_d5(n, z) * cls.hankelh1(n + 1, z))
@staticmethod
def hankelh2(n: int, z: complex) -> complex:
"""Order :attr:`n` Spherical Hankel function of the second kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return sqrt(pi / (2 * z)) * hankel2(n + 0.5, z)
@classmethod
def d1_hankelh2(cls, n: int, z: complex) -> complex:
"""First derivative of order :attr:`n` Spherical Hankel function of the
second
kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return -cls.hankelh2(n + 1, z) + (n / z) * cls.hankelh2(n, z)
@classmethod
def adaptive_derivative_jn(cls, n: int, z: complex, i: int) -> complex:
def d2_hankelh2(cls, n: int, z: complex) -> complex:
"""Second derivative of order :attr:`n` Spherical Hankel function of
the second kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return (cls._a0_d2(n, z) * cls.hankelh2(n, z)
+ cls._a1_d2(n, z) * cls.hankelh2(n + 1, z))
@classmethod
def d3_hankelh2(cls, n: int, z: complex) -> complex:
"""Third derivative of order :attr:`n` Spherical Hankel function of
the second kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return (cls._a0_d3(n, z) * cls.hankelh2(n, z)
+ cls._a1_d3(n, z) * cls.hankelh2(n + 1, z))
@classmethod
def d4_hankelh2(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Hankel function of
the second kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return (cls._a0_d4(n, z) * cls.hankelh2(n, z)
+ cls._a1_d4(n, z) * cls.hankelh2(n + 1, z))
@classmethod
def d5_hankelh2(cls, n: int, z: complex) -> complex:
"""Fourth derivative of order :attr:`n` Spherical Hankel function of
the second kind
:param n: order
:type n: int
:param z: argument
:type z: complex
:rtype: complex
"""
return (cls._a0_d5(n, z) * cls.hankelh2(n, z)
+ cls._a1_d5(n, z) * cls.hankelh2(n + 1, z))
@classmethod
def adaptive_derivative_besselj(
cls, n: int, z: complex, i: int) -> complex:
""" Returns the value of the :attr:`i`-th derivative of the spherical
Bessel function of the first kind of order :attr:`n`. The coefficients
for the derivative are calculated at runtime. There is no restriction
......@@ -435,10 +518,29 @@ class SpecialFunctions(object):
:type i: int
:rtype: complex
"""
return cls.__adaptive_derivative(cls.jn, i, n, z)
return cls.__adaptive_derivative(cls.besselj, i, n, z)
@classmethod
def adaptive_derivative_hn(cls, n: int, z: complex, i: int) -> complex:
def adaptive_derivative_bessely(
cls, n: int, z: complex, i: int) -> complex:
""" Returns the value of the :attr:`i`-th derivative of the spherical
Bessel function of the second kind of order :attr:`n`. The coefficients
for the derivative are calculated at runtime. There is no restriction
to the magnitude of :attr:`i` other than it must be greater than `1`.
:param n: order of spherical Hankel function
:type n: int
:param z: argument of the function
:type z: complex
:param i: i-th derivative is computed
:type i: int
:rtype: complex
"""
return cls.__adaptive_derivative(cls.bessely, i, n, z)
@classmethod
def adaptive_derivative_hankelh1(
cls, n: int, z: complex, i: int) -> complex:
""" Returns the value of the :attr:`i`-th derivative of the spherical
Hankel function of order :attr:`n`. The coefficients for the derivative
are calculated at runtime. There is no restriction to the magnitude of
......@@ -452,14 +554,15 @@ class SpecialFunctions(object):
:type i: int
:rtype: complex
"""
return cls.__adaptive_derivative(cls.hn, i, n, z)
return cls.__adaptive_derivative(cls.hankelh1, i, n, z)
@classmethod
def adaptive_derivative_yn(cls, n: int, z: complex, i: int) -> complex:
def adaptive_derivative_hankelh2(
cls, n: int, z: complex, i: int) -> complex:
""" Returns the value of the :attr:`i`-th derivative of the spherical
Bessel function of the second kind of order :attr:`n`. The coefficients
for the derivative are calculated at runtime. There is no restriction
to the magnitude of :attr:`i` other than it must be greater than `1`.
Hankel function of order :attr:`n`. The coefficients for the derivative
are calculated at runtime. There is no restriction to the magnitude of
:attr:`i` other than it must be greater than `1`.
:param n: order of spherical Hankel function
:type n: int
......@@ -469,7 +572,7 @@ class SpecialFunctions(object):
:type i: int
:rtype: complex
"""
return cls.__adaptive_derivative(cls.yn, i, n, z)
return cls.__adaptive_derivative(cls.hankelh2, i, n, z)
@classmethod
def __adaptive_derivative(cls, func: Callable[[int, complex], complex],
......
......@@ -11,7 +11,7 @@ from gorkov import SpecialFunctions as sp
from gorkov import LegendreFunctions as leg
from gorkov import Clebsch_Gordan_coefficient as cg
from scipy.special import jv, yv, hankel1, lpmv
from scipy.special import jv, yv, hankel1, hankel2, lpmv
import numpy as np
from sympy.physics.quantum.cg import CG
......@@ -92,7 +92,7 @@ class TestFunctions(BaseTest):
self.assertEqual(
(v_x, v_z), polar_2_cartesian_velocities(v_r, v_theta, theta))
def test_jn_and_derivatives(self):
def test_besselj_and_derivatives(self):
def j(n, z):
return sqrt(pi / 2 / z) * jv(n + 0.5, z)
......@@ -100,19 +100,27 @@ class TestFunctions(BaseTest):
for n in np.random.randint(0, n_end, size=10):
for _ in np.arange(10):
z = 10 * np.random.randn(1) + 1j * 10 * np.random.randn(1)
self.assertEqual(j(n, z), sp.jn(n, z))
self._assert_equal_complex(self._df(j, n, z), sp.d_jn(n, z))
self._assert_equal_complex(self._d2f(j, n, z), sp.d2_jn(n, z))
self._assert_equal_complex(self._d3f(j, n, z), sp.d3_jn(n, z))
self._assert_equal_complex(self._d4f(j, n, z), sp.d4_jn(n, z))
self.assertEqual(j(n, z), sp.besselj(n, z))
self._assert_equal_complex(
self._df(j, n, z), sp.d1_besselj(n, z))
self._assert_equal_complex(
self._d2f(j, n, z), sp.d2_besselj(n, z))
self._assert_equal_complex(
self._d3f(j, n, z), sp.d3_besselj(n, z))
self._assert_equal_complex(
self._d4f(j, n, z), sp.d4_besselj(n, z))
n = 0
self._assert_equal_complex(self._df(j, n, z), sp.d_jn(n, z))
self._assert_equal_complex(self._d2f(j, n, z), sp.d2_jn(n, z))
self._assert_equal_complex(self._d3f(j, n, z), sp.d3_jn(n, z))
self._assert_equal_complex(self._d4f(j, n, z), sp.d4_jn(n, z))
def test_yn_and_derivatives(self):
self._assert_equal_complex(
self._df(j, n, z), sp.d1_besselj(n, z))
self._assert_equal_complex(
self._d2f(j, n, z), sp.d2_besselj(n, z))
self._assert_equal_complex(
self._d3f(j, n, z), sp.d3_besselj(n, z))
self._assert_equal_complex(
self._d4f(j, n, z), sp.d4_besselj(n, z))
def test_bessely_and_derivatives(self):
def y(n, z):
return sqrt(pi / 2 / z) * yv(n + 0.5, z)
......@@ -120,50 +128,103 @@ class TestFunctions(BaseTest):
for n in np.random.randint(0, n_end, size=10):
for _ in np.arange(10):
z = 10 * np.random.randn(1) + 1j * 10 * np.random.randn(1)
self.assertEqual(y(n, z), sp.yn(n, z))
self._assert_equal_complex(self._df(y, n, z), sp.d_yn(n, z))
self._assert_equal_complex(self._d2f(y, n, z), sp.d2_yn(n, z))
self._assert_equal_complex(self._d3f(y, n, z), sp.d3_yn(n, z))
self._assert_equal_complex(self._d4f(y, n, z), sp.d4_yn(n, z))
self.assertEqual(y(n, z), sp.bessely(n, z))
self._assert_equal_complex(
self._df(y, n, z), sp.d1_bessely(n, z))
self._assert_equal_complex(
self._d2f(y, n, z), sp.d2_bessely(n, z))
self._assert_equal_complex(
self._d3f(y, n, z), sp.d3_bessely(n, z))
self._assert_equal_complex(
self._d4f(y, n, z), sp.d4_bessely(n, z))
n = 0
self._assert_equal_complex(self._df(y, n, z), sp.d_yn(n, z))
self._assert_equal_complex(self._d2f(y, n, z), sp.d2_yn(n, z))
self._assert_equal_complex(self._d3f(y, n, z), sp.d3_yn(n, z))
self._assert_equal_complex(self._d4f(y, n, z), sp.d4_yn(n, z))
def test_hn_and_derivatives(self):
def h(n, z):
self._assert_equal_complex(
self._df(y, n, z), sp.d1_bessely(n, z))
self._assert_equal_complex(
self._d2f(y, n, z), sp.d2_bessely(n, z))
self._assert_equal_complex(
self._d3f(y, n, z), sp.d3_bessely(n, z))
self._assert_equal_complex(
self._d4f(y, n, z), sp.d4_bessely(n, z))
def test_hankelh1_and_derivatives(self):
def h1(n, z):
return sqrt(pi / z / 2) * hankel1(n + 0.5, z)
n_end = np.random.randint(1, 100, 1)
for n in np.random.randint(0, n_end, size=10):
for _ in np.arange(10):
z = 10 * np.random.randn(1) + 1j * 10 * np.random.randn(1)
self.assertEqual(h(n, z), sp.hn(n, z))
self._assert_equal_complex(self._df(h, n, z), sp.d_hn(n, z))
self._assert_equal_complex(self._d2f(h, n, z), sp.d2_hn(n, z))
self._assert_equal_complex(self._d3f(h, n, z), sp.d3_hn(n, z))
self._assert_equal_complex(self._d4f(h, n, z), sp.d4_hn(n, z))
self._assert_equal_complex(self._d5f(h, n, z), sp.d5_hn(n, z))
self.assertEqual(h1(n, z), sp.hankelh1(n, z))
self._assert_equal_complex(
self._df(h1, n, z), sp.d1_hankelh1(n, z))
self._assert_equal_complex(
self._d2f(h1, n, z), sp.d2_hankelh1(n, z))
self._assert_equal_complex(
self._d3f(h1, n, z), sp.d3_hankelh1(n, z))
self._assert_equal_complex(
self._d4f(h1, n, z), sp.d4_hankelh1(n, z))
self._assert_equal_complex(
self._d5f(h1, n, z), sp.d5_hankelh1(n, z))
n = 0
self._assert_equal_complex(
self._df(h1, n, z), sp.d1_hankelh1(n, z))
self._assert_equal_complex(
self._d2f(h1, n, z), sp.d2_hankelh1(n, z))
self._assert_equal_complex(
self._d3f(h1, n, z), sp.d3_hankelh1(n, z))
self._assert_equal_complex(
self._d4f(h1, n, z), sp.d4_hankelh1(n, z))
self._assert_equal_complex(
self._d5f(h1, n, z), sp.d5_hankelh1(n, z))
def test_hankelh2_and_derivatives(self):
def h2(n, z):
return sqrt(pi / z / 2) * hankel2(n + 0.5, z)
n_end = np.random.randint(1, 100, 1)
for n in np.random.randint(0, n_end, size=10):
for _ in np.arange(10):
z = 10 * np.random.randn(1) + 1j * 10 * np.random.randn(1)
self.assertEqual(h2(n, z), sp.hankelh2(n, z))
self._assert_equal_complex(
self._df(h2, n, z), sp.d1_hankelh2(n, z))
self._assert_equal_complex(
self._d2f(h2, n, z), sp.d2_hankelh2(n, z))
self._assert_equal_complex(
self._d3f(h2, n, z), sp.d3_hankelh2(n, z))
self._assert_equal_complex(
self._d4f(h2, n, z), sp.d4_hankelh2(n, z))
self._assert_equal_complex(
self._d5f(h2, n, z), sp.d5_hankelh2(n, z))
n = 0
self._assert_equal_complex(self._df(h, n, z), sp.d_hn(n, z))
self._assert_equal_complex(self._d2f(h, n, z), sp.d2_hn(n, z))
self._assert_equal_complex(self._d3f(h, n, z), sp.d3_hn(n, z))
self._assert_equal_complex(self._d4f(h, n, z), sp.d4_hn(n, z))
self._assert_equal_complex(self._d5f(h, n, z), sp.d5_hn(n, z))
self._assert_equal_complex(
self._df(h2, n, z), sp.d1_hankelh2(n, z))
self._assert_equal_complex(
self._d2f(h2, n, z), sp.d2_hankelh2(n, z))
self._assert_equal_complex(
self._d3f(h2, n, z), sp.d3_hankelh2(n, z))
self._assert_equal_complex(
self._d4f(h2, n, z), sp.d4_hankelh2(n, z))
self._assert_equal_complex(
self._d5f(h2, n, z), sp.d5_hankelh2(n, z))
def test_adaptive_derivative(self):
def j(n, z):
return sqrt(pi / 2 / z) * jv(n + 0.5, z)
def h(n, z):
return sqrt(pi / z / 2) * hankel1(n + 0.5, z)
def y(n, z):
return sqrt(pi / 2 / z) * yv(n + 0.5, z)
def h1(n, z):
return sqrt(pi / z / 2) * hankel1(n + 0.5, z)
def h2(n, z):
return sqrt(pi / z / 2) * hankel2(n + 0.5, z)
dfdzs = [self._df, self._d2f, self._d3f, self._d4f, self._d5f]
n_end = np.random.randint(1, 100, 1)
......@@ -173,18 +234,24 @@ class TestFunctions(BaseTest):
for i, df in enumerate(dfdzs, start=1):
self._assert_equal_complex(
df(h, n, z), sp.adaptive_derivative_hn(n, z, i))
df(j, n, z), sp.adaptive_derivative_besselj(n, z, i))
self._assert_equal_complex(
df(y, n, z), sp.adaptive_derivative_bessely(n,