elliptic-functions 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- elliptic_functions-4.0.0/.gitignore +6 -0
- elliptic_functions-4.0.0/PKG-INFO +160 -0
- elliptic_functions-4.0.0/README.md +137 -0
- elliptic_functions-4.0.0/bench.py +514 -0
- elliptic_functions-4.0.0/bench_results.csv +136 -0
- elliptic_functions-4.0.0/bench_results_gpu2.csv +103 -0
- elliptic_functions-4.0.0/elliptic/__init__.py +101 -0
- elliptic_functions-4.0.0/elliptic/_agm.py +57 -0
- elliptic_functions-4.0.0/elliptic/_utils.py +86 -0
- elliptic_functions-4.0.0/elliptic/_xputils.py +13 -0
- elliptic_functions-4.0.0/elliptic/agm.py +19 -0
- elliptic_functions-4.0.0/elliptic/applications.py +61 -0
- elliptic_functions-4.0.0/elliptic/bulirsch.py +70 -0
- elliptic_functions-4.0.0/elliptic/carlson.py +186 -0
- elliptic_functions-4.0.0/elliptic/complex_elliptic.py +142 -0
- elliptic_functions-4.0.0/elliptic/ellipj.py +77 -0
- elliptic_functions-4.0.0/elliptic/elliptic12.py +102 -0
- elliptic_functions-4.0.0/elliptic/elliptic3.py +67 -0
- elliptic_functions-4.0.0/elliptic/ellipticBD.py +54 -0
- elliptic_functions-4.0.0/elliptic/ellipticBDJ.py +74 -0
- elliptic_functions-4.0.0/elliptic/inverse.py +62 -0
- elliptic_functions-4.0.0/elliptic/jacobi_edj.py +48 -0
- elliptic_functions-4.0.0/elliptic/nome.py +75 -0
- elliptic_functions-4.0.0/elliptic/theta.py +250 -0
- elliptic_functions-4.0.0/elliptic/weierstrass.py +209 -0
- elliptic_functions-4.0.0/pyproject.toml +34 -0
- elliptic_functions-4.0.0/tests/conftest.py +43 -0
- elliptic_functions-4.0.0/tests/test_associate.py +239 -0
- elliptic_functions-4.0.0/tests/test_elliptic12.py +87 -0
- elliptic_functions-4.0.0/tests/test_parity.py +343 -0
- elliptic_functions-4.0.0/tests/test_reference_tables.py +342 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: elliptic-functions
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: Elliptic integrals and functions — NumPy, PyTorch, JAX
|
|
5
|
+
Author-email: Igor Moiseev <moiseev.igor@gmail.com>
|
|
6
|
+
License: GPL-2.0
|
|
7
|
+
Keywords: elliptic functions,elliptic integrals,mathematics,special functions
|
|
8
|
+
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: array-api-compat>=1.9
|
|
13
|
+
Requires-Dist: numpy>=1.24
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: mpmath>=1.3; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
17
|
+
Requires-Dist: scipy>=1.8; extra == 'dev'
|
|
18
|
+
Provides-Extra: jax
|
|
19
|
+
Requires-Dist: jax>=0.4; extra == 'jax'
|
|
20
|
+
Provides-Extra: torch
|
|
21
|
+
Requires-Dist: torch>=2.0; extra == 'torch'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# elliptic (Python)
|
|
26
|
+
|
|
27
|
+
Standalone Python implementation of elliptic integrals and functions.
|
|
28
|
+
Works identically on NumPy arrays, PyTorch tensors (CPU and CUDA), and JAX arrays — no scipy runtime dependency.
|
|
29
|
+
|
|
30
|
+
[](https://github.com/moiseevigor/elliptic/actions/workflows/python.yml)
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install elliptic-functions # NumPy only
|
|
36
|
+
pip install "elliptic-functions[torch]" # + PyTorch backend
|
|
37
|
+
pip install "elliptic-functions[jax]" # + JAX backend
|
|
38
|
+
pip install "elliptic-functions[dev]" # + test deps (scipy, mpmath, pytest)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import numpy as np
|
|
45
|
+
import elliptic
|
|
46
|
+
|
|
47
|
+
phi = np.linspace(0, np.pi/2, 200)
|
|
48
|
+
m = 0.7
|
|
49
|
+
|
|
50
|
+
# Incomplete integrals F(φ|m), E(φ|m), Jacobi zeta Z(φ|m)
|
|
51
|
+
F, E, Z = elliptic.elliptic12(phi, m)
|
|
52
|
+
|
|
53
|
+
# Third kind Π(φ,m,n) — missing from scipy (issue #4452)
|
|
54
|
+
Pi = elliptic.elliptic3(phi, m, 0.3)
|
|
55
|
+
|
|
56
|
+
# Jacobi elliptic functions sn, cn, dn, am
|
|
57
|
+
sn, cn, dn, am = elliptic.ellipj(np.linspace(0, 3, 100), m)
|
|
58
|
+
|
|
59
|
+
# Associate incomplete integrals B, D, J (DLMF §19.2)
|
|
60
|
+
B, D, J = elliptic.ellipticBDJ(phi, m, 0.3)
|
|
61
|
+
# identities: F = B+D, E = B+(1-m)D, Pi = B+D+n*J
|
|
62
|
+
|
|
63
|
+
# Complete associate integrals B(m), D(m), S(m)
|
|
64
|
+
B_c, D_c, S_c = elliptic.ellipticBD(np.array([0.3, 0.5, 0.7]))
|
|
65
|
+
|
|
66
|
+
# Carlson symmetric forms (DLMF §19.16)
|
|
67
|
+
RF = elliptic.carlsonRF(0.0, 1.0 - m, 1.0) # = K(m)
|
|
68
|
+
RD = elliptic.carlsonRD(0.0, 1.0 - m, 1.0) # = 3D(m)
|
|
69
|
+
|
|
70
|
+
# Bulirsch generalised complete integrals
|
|
71
|
+
K = elliptic.cel1(np.sqrt(1 - m)) # = K(m)
|
|
72
|
+
E2 = elliptic.cel2(np.sqrt(1 - m), 1.0, 1-m) # = E(m)
|
|
73
|
+
|
|
74
|
+
# Jacobi theta functions (4 types)
|
|
75
|
+
Th3 = elliptic.theta(3, phi, m)
|
|
76
|
+
Th, H = elliptic.jacobiThetaEta(np.linspace(0, 1, 50), m)
|
|
77
|
+
Th3, dTh3 = elliptic.theta_prime(3, phi, m)
|
|
78
|
+
|
|
79
|
+
# Weierstrass functions
|
|
80
|
+
e1, e2, e3 = 2.0, 0.5, -2.5
|
|
81
|
+
P = elliptic.weierstrassP(0.4, e1, e2, e3)
|
|
82
|
+
Zf = elliptic.weierstrassZeta(0.4, e1, e2, e3)
|
|
83
|
+
S = elliptic.weierstrassSigma(0.4, e1, e2, e3)
|
|
84
|
+
dP = elliptic.weierstrassPPrime(0.4, e1, e2, e3)
|
|
85
|
+
g2, g3, Delta = elliptic.weierstrassInvariants(e1, e2, e3)
|
|
86
|
+
|
|
87
|
+
# Nome and inverse
|
|
88
|
+
q = elliptic.nomeq(m)
|
|
89
|
+
m_back = elliptic.inversenomeq(q)
|
|
90
|
+
|
|
91
|
+
# Inverse E(phi|m): given E value, solve for phi
|
|
92
|
+
phi_inv = elliptic.inverselliptic2(E, m)
|
|
93
|
+
|
|
94
|
+
# Arithmetic-geometric mean
|
|
95
|
+
agm_val = elliptic.agm(1.0, np.sqrt(1 - m)) # = π/(2K(m))
|
|
96
|
+
|
|
97
|
+
# Complex arguments
|
|
98
|
+
import numpy as np
|
|
99
|
+
u_c = np.array([0.4 + 0.3j, 0.8 - 0.2j])
|
|
100
|
+
Fi, Ei, Zi = elliptic.elliptic12i(u_c, m)
|
|
101
|
+
sni, cni, dni = elliptic.ellipji(u_c, m)
|
|
102
|
+
|
|
103
|
+
# Application: ellipse arc length
|
|
104
|
+
arc = elliptic.arclength_ellipse(5, 10) # full perimeter ≈ 48.44
|
|
105
|
+
arc = elliptic.arclength_ellipse(5, 10, 0, np.pi/4) # quarter arc
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## GPU (PyTorch)
|
|
109
|
+
|
|
110
|
+
Pass a `torch.Tensor` on any device:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import torch, elliptic
|
|
114
|
+
|
|
115
|
+
phi = torch.linspace(0.01, 1.5, 1_000_000, dtype=torch.float64, device="cuda")
|
|
116
|
+
F, E, Z = elliptic.elliptic12(phi, torch.full_like(phi, 0.7))
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## JAX (jit / vmap)
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import jax, jax.numpy as jnp, elliptic
|
|
123
|
+
|
|
124
|
+
phi = jnp.linspace(0.01, 1.5, 10_000)
|
|
125
|
+
F, E, Z = jax.jit(elliptic.elliptic12)(phi, 0.7)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Comparison with scipy.special
|
|
129
|
+
|
|
130
|
+
| Function | scipy | elliptic |
|
|
131
|
+
|---|:---:|:---:|
|
|
132
|
+
| K(m), E(m) | ✓ | ✓ |
|
|
133
|
+
| F(φ,m), E(φ,m) | ✓ | ✓ |
|
|
134
|
+
| Jacobi sn/cn/dn (real) | ✓ | ✓ |
|
|
135
|
+
| Jacobi sn/cn/dn (complex) | ✗ | ✓ |
|
|
136
|
+
| F(u,m), E(u,m) (complex) | ✗ | ✓ |
|
|
137
|
+
| **Π(φ,m,n) — 3rd kind** | ✗ (open since 2015) | ✓ |
|
|
138
|
+
| Carlson RF/RD/RJ/RC | ✓ since v1.8 | ✓ |
|
|
139
|
+
| **B, D, J associate** | ✗ | ✓ |
|
|
140
|
+
| **Bulirsch cel** | ✗ | ✓ |
|
|
141
|
+
| **Jacobi theta θ₁…θ₄** | ✗ | ✓ |
|
|
142
|
+
| **Weierstrass P/ζ/σ/℘′** | ✗ | ✓ |
|
|
143
|
+
| **Weierstrass invariants g₂,g₃** | ✗ | ✓ |
|
|
144
|
+
| **Nome q(m) and m(q)** | ✗ | ✓ |
|
|
145
|
+
| **Inverse E(φ,m)** | ✗ | ✓ |
|
|
146
|
+
| **AGM** | ✗ | ✓ |
|
|
147
|
+
| **Ellipse arc length** | ✗ | ✓ |
|
|
148
|
+
| **PyTorch GPU** | ✗ | ✓ |
|
|
149
|
+
| **JAX jit/vmap** | ✗ | ✓ |
|
|
150
|
+
|
|
151
|
+
All algorithms run identically across backends — the same Python code dispatches to NumPy, PyTorch CUDA, or JAX TPU.
|
|
152
|
+
|
|
153
|
+
## References
|
|
154
|
+
|
|
155
|
+
- Abramowitz & Stegun, *Handbook of Mathematical Functions*, §16–18
|
|
156
|
+
- NIST DLMF §19, §22, §23 — https://dlmf.nist.gov
|
|
157
|
+
- Fukushima (2015), "Elliptic functions and elliptic integrals for celestial mechanics"
|
|
158
|
+
- Bulirsch (1965), "Numerical computation of elliptic integrals"
|
|
159
|
+
- Carlson (1995), "Numerical Computation of Real or Complex Elliptic Integrals"
|
|
160
|
+
- Boyd (2012), "Numerical inversion of the incomplete elliptic integral of the second kind"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
|
|
2
|
+
# elliptic (Python)
|
|
3
|
+
|
|
4
|
+
Standalone Python implementation of elliptic integrals and functions.
|
|
5
|
+
Works identically on NumPy arrays, PyTorch tensors (CPU and CUDA), and JAX arrays — no scipy runtime dependency.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/moiseevigor/elliptic/actions/workflows/python.yml)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install elliptic-functions # NumPy only
|
|
13
|
+
pip install "elliptic-functions[torch]" # + PyTorch backend
|
|
14
|
+
pip install "elliptic-functions[jax]" # + JAX backend
|
|
15
|
+
pip install "elliptic-functions[dev]" # + test deps (scipy, mpmath, pytest)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import numpy as np
|
|
22
|
+
import elliptic
|
|
23
|
+
|
|
24
|
+
phi = np.linspace(0, np.pi/2, 200)
|
|
25
|
+
m = 0.7
|
|
26
|
+
|
|
27
|
+
# Incomplete integrals F(φ|m), E(φ|m), Jacobi zeta Z(φ|m)
|
|
28
|
+
F, E, Z = elliptic.elliptic12(phi, m)
|
|
29
|
+
|
|
30
|
+
# Third kind Π(φ,m,n) — missing from scipy (issue #4452)
|
|
31
|
+
Pi = elliptic.elliptic3(phi, m, 0.3)
|
|
32
|
+
|
|
33
|
+
# Jacobi elliptic functions sn, cn, dn, am
|
|
34
|
+
sn, cn, dn, am = elliptic.ellipj(np.linspace(0, 3, 100), m)
|
|
35
|
+
|
|
36
|
+
# Associate incomplete integrals B, D, J (DLMF §19.2)
|
|
37
|
+
B, D, J = elliptic.ellipticBDJ(phi, m, 0.3)
|
|
38
|
+
# identities: F = B+D, E = B+(1-m)D, Pi = B+D+n*J
|
|
39
|
+
|
|
40
|
+
# Complete associate integrals B(m), D(m), S(m)
|
|
41
|
+
B_c, D_c, S_c = elliptic.ellipticBD(np.array([0.3, 0.5, 0.7]))
|
|
42
|
+
|
|
43
|
+
# Carlson symmetric forms (DLMF §19.16)
|
|
44
|
+
RF = elliptic.carlsonRF(0.0, 1.0 - m, 1.0) # = K(m)
|
|
45
|
+
RD = elliptic.carlsonRD(0.0, 1.0 - m, 1.0) # = 3D(m)
|
|
46
|
+
|
|
47
|
+
# Bulirsch generalised complete integrals
|
|
48
|
+
K = elliptic.cel1(np.sqrt(1 - m)) # = K(m)
|
|
49
|
+
E2 = elliptic.cel2(np.sqrt(1 - m), 1.0, 1-m) # = E(m)
|
|
50
|
+
|
|
51
|
+
# Jacobi theta functions (4 types)
|
|
52
|
+
Th3 = elliptic.theta(3, phi, m)
|
|
53
|
+
Th, H = elliptic.jacobiThetaEta(np.linspace(0, 1, 50), m)
|
|
54
|
+
Th3, dTh3 = elliptic.theta_prime(3, phi, m)
|
|
55
|
+
|
|
56
|
+
# Weierstrass functions
|
|
57
|
+
e1, e2, e3 = 2.0, 0.5, -2.5
|
|
58
|
+
P = elliptic.weierstrassP(0.4, e1, e2, e3)
|
|
59
|
+
Zf = elliptic.weierstrassZeta(0.4, e1, e2, e3)
|
|
60
|
+
S = elliptic.weierstrassSigma(0.4, e1, e2, e3)
|
|
61
|
+
dP = elliptic.weierstrassPPrime(0.4, e1, e2, e3)
|
|
62
|
+
g2, g3, Delta = elliptic.weierstrassInvariants(e1, e2, e3)
|
|
63
|
+
|
|
64
|
+
# Nome and inverse
|
|
65
|
+
q = elliptic.nomeq(m)
|
|
66
|
+
m_back = elliptic.inversenomeq(q)
|
|
67
|
+
|
|
68
|
+
# Inverse E(phi|m): given E value, solve for phi
|
|
69
|
+
phi_inv = elliptic.inverselliptic2(E, m)
|
|
70
|
+
|
|
71
|
+
# Arithmetic-geometric mean
|
|
72
|
+
agm_val = elliptic.agm(1.0, np.sqrt(1 - m)) # = π/(2K(m))
|
|
73
|
+
|
|
74
|
+
# Complex arguments
|
|
75
|
+
import numpy as np
|
|
76
|
+
u_c = np.array([0.4 + 0.3j, 0.8 - 0.2j])
|
|
77
|
+
Fi, Ei, Zi = elliptic.elliptic12i(u_c, m)
|
|
78
|
+
sni, cni, dni = elliptic.ellipji(u_c, m)
|
|
79
|
+
|
|
80
|
+
# Application: ellipse arc length
|
|
81
|
+
arc = elliptic.arclength_ellipse(5, 10) # full perimeter ≈ 48.44
|
|
82
|
+
arc = elliptic.arclength_ellipse(5, 10, 0, np.pi/4) # quarter arc
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## GPU (PyTorch)
|
|
86
|
+
|
|
87
|
+
Pass a `torch.Tensor` on any device:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import torch, elliptic
|
|
91
|
+
|
|
92
|
+
phi = torch.linspace(0.01, 1.5, 1_000_000, dtype=torch.float64, device="cuda")
|
|
93
|
+
F, E, Z = elliptic.elliptic12(phi, torch.full_like(phi, 0.7))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## JAX (jit / vmap)
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
import jax, jax.numpy as jnp, elliptic
|
|
100
|
+
|
|
101
|
+
phi = jnp.linspace(0.01, 1.5, 10_000)
|
|
102
|
+
F, E, Z = jax.jit(elliptic.elliptic12)(phi, 0.7)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Comparison with scipy.special
|
|
106
|
+
|
|
107
|
+
| Function | scipy | elliptic |
|
|
108
|
+
|---|:---:|:---:|
|
|
109
|
+
| K(m), E(m) | ✓ | ✓ |
|
|
110
|
+
| F(φ,m), E(φ,m) | ✓ | ✓ |
|
|
111
|
+
| Jacobi sn/cn/dn (real) | ✓ | ✓ |
|
|
112
|
+
| Jacobi sn/cn/dn (complex) | ✗ | ✓ |
|
|
113
|
+
| F(u,m), E(u,m) (complex) | ✗ | ✓ |
|
|
114
|
+
| **Π(φ,m,n) — 3rd kind** | ✗ (open since 2015) | ✓ |
|
|
115
|
+
| Carlson RF/RD/RJ/RC | ✓ since v1.8 | ✓ |
|
|
116
|
+
| **B, D, J associate** | ✗ | ✓ |
|
|
117
|
+
| **Bulirsch cel** | ✗ | ✓ |
|
|
118
|
+
| **Jacobi theta θ₁…θ₄** | ✗ | ✓ |
|
|
119
|
+
| **Weierstrass P/ζ/σ/℘′** | ✗ | ✓ |
|
|
120
|
+
| **Weierstrass invariants g₂,g₃** | ✗ | ✓ |
|
|
121
|
+
| **Nome q(m) and m(q)** | ✗ | ✓ |
|
|
122
|
+
| **Inverse E(φ,m)** | ✗ | ✓ |
|
|
123
|
+
| **AGM** | ✗ | ✓ |
|
|
124
|
+
| **Ellipse arc length** | ✗ | ✓ |
|
|
125
|
+
| **PyTorch GPU** | ✗ | ✓ |
|
|
126
|
+
| **JAX jit/vmap** | ✗ | ✓ |
|
|
127
|
+
|
|
128
|
+
All algorithms run identically across backends — the same Python code dispatches to NumPy, PyTorch CUDA, or JAX TPU.
|
|
129
|
+
|
|
130
|
+
## References
|
|
131
|
+
|
|
132
|
+
- Abramowitz & Stegun, *Handbook of Mathematical Functions*, §16–18
|
|
133
|
+
- NIST DLMF §19, §22, §23 — https://dlmf.nist.gov
|
|
134
|
+
- Fukushima (2015), "Elliptic functions and elliptic integrals for celestial mechanics"
|
|
135
|
+
- Bulirsch (1965), "Numerical computation of elliptic integrals"
|
|
136
|
+
- Carlson (1995), "Numerical Computation of Real or Complex Elliptic Integrals"
|
|
137
|
+
- Boyd (2012), "Numerical inversion of the incomplete elliptic integral of the second kind"
|