freealg 0.1.11__py3-none-any.whl → 0.7.12__py3-none-any.whl

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.
Files changed (59) hide show
  1. freealg/__init__.py +8 -2
  2. freealg/__version__.py +1 -1
  3. freealg/_algebraic_form/__init__.py +12 -0
  4. freealg/_algebraic_form/_branch_points.py +288 -0
  5. freealg/_algebraic_form/_constraints.py +139 -0
  6. freealg/_algebraic_form/_continuation_algebraic.py +706 -0
  7. freealg/_algebraic_form/_decompress.py +641 -0
  8. freealg/_algebraic_form/_decompress2.py +204 -0
  9. freealg/_algebraic_form/_edge.py +330 -0
  10. freealg/_algebraic_form/_homotopy.py +323 -0
  11. freealg/_algebraic_form/_moments.py +448 -0
  12. freealg/_algebraic_form/_sheets_util.py +145 -0
  13. freealg/_algebraic_form/_support.py +309 -0
  14. freealg/_algebraic_form/algebraic_form.py +1232 -0
  15. freealg/_free_form/__init__.py +16 -0
  16. freealg/{_chebyshev.py → _free_form/_chebyshev.py} +75 -43
  17. freealg/_free_form/_decompress.py +993 -0
  18. freealg/_free_form/_density_util.py +243 -0
  19. freealg/_free_form/_jacobi.py +359 -0
  20. freealg/_free_form/_linalg.py +508 -0
  21. freealg/{_pade.py → _free_form/_pade.py} +42 -208
  22. freealg/{_plot_util.py → _free_form/_plot_util.py} +37 -22
  23. freealg/{_sample.py → _free_form/_sample.py} +58 -22
  24. freealg/_free_form/_series.py +454 -0
  25. freealg/_free_form/_support.py +214 -0
  26. freealg/_free_form/free_form.py +1362 -0
  27. freealg/_geometric_form/__init__.py +13 -0
  28. freealg/_geometric_form/_continuation_genus0.py +175 -0
  29. freealg/_geometric_form/_continuation_genus1.py +275 -0
  30. freealg/_geometric_form/_elliptic_functions.py +174 -0
  31. freealg/_geometric_form/_sphere_maps.py +63 -0
  32. freealg/_geometric_form/_torus_maps.py +118 -0
  33. freealg/_geometric_form/geometric_form.py +1094 -0
  34. freealg/_util.py +56 -110
  35. freealg/distributions/__init__.py +7 -1
  36. freealg/distributions/_chiral_block.py +494 -0
  37. freealg/distributions/_deformed_marchenko_pastur.py +726 -0
  38. freealg/distributions/_deformed_wigner.py +386 -0
  39. freealg/distributions/_kesten_mckay.py +29 -15
  40. freealg/distributions/_marchenko_pastur.py +224 -95
  41. freealg/distributions/_meixner.py +47 -37
  42. freealg/distributions/_wachter.py +29 -17
  43. freealg/distributions/_wigner.py +27 -14
  44. freealg/visualization/__init__.py +12 -0
  45. freealg/visualization/_glue_util.py +32 -0
  46. freealg/visualization/_rgb_hsv.py +125 -0
  47. freealg-0.7.12.dist-info/METADATA +172 -0
  48. freealg-0.7.12.dist-info/RECORD +53 -0
  49. {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/WHEEL +1 -1
  50. freealg/_decompress.py +0 -180
  51. freealg/_jacobi.py +0 -218
  52. freealg/_support.py +0 -85
  53. freealg/freeform.py +0 -967
  54. freealg-0.1.11.dist-info/METADATA +0 -140
  55. freealg-0.1.11.dist-info/RECORD +0 -24
  56. /freealg/{_damp.py → _free_form/_damp.py} +0 -0
  57. {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/AUTHORS.txt +0 -0
  58. {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/licenses/LICENSE.txt +0 -0
  59. {freealg-0.1.11.dist-info → freealg-0.7.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,118 @@
1
+ # SPDX-FileCopyrightText: Copyright 2026, Siavash Ameli <sameli@berkeley.edu>
2
+ # SPDX-License-Identifier: BSD-3-Clause
3
+ # SPDX-FileType: SOURCE
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the license found in the LICENSE.txt file in the root
7
+ # directory of this source tree.
8
+
9
+
10
+ # =======
11
+ # Imports
12
+ # =======
13
+
14
+ import numpy
15
+ import scipy
16
+ from ._elliptic_functions import ellipj
17
+ from ._continuation_genus1 import _poly_eval
18
+
19
+ __all__ = ['make_torus_grid', 'u_from_angles', 'eval_fitted_m_on_torus']
20
+
21
+
22
+ # ===============
23
+ # make torus grid
24
+ # ===============
25
+
26
+ def make_torus_grid(n_theta=101, n_phi=101, R=1.0, r=0.35):
27
+ """
28
+ Returns an embedded torus mesh (X,Y,Z) with angles (TH,PH).
29
+ TH: around major circle, PH: around tube.
30
+ """
31
+
32
+ if n_phi % 2 == 0:
33
+ raise ValueError('n_phi should be odd number to avoid rendering ' +
34
+ 'issue at phi=0.')
35
+
36
+ # fundamental angles (no endpoint duplicates)
37
+ theta = numpy.linspace(0.0, 2.0*numpy.pi, int(n_theta), endpoint=False)
38
+ phi = numpy.linspace(0.0, 2.0*numpy.pi, int(n_phi), endpoint=False)
39
+
40
+ TH, PH = numpy.meshgrid(theta, phi) # shapes (n_phi, n_theta)
41
+
42
+ # --- wrap/close the grid by appending first row/col ---
43
+ TH = numpy.vstack([TH, TH[0:1, :]]) # add phi seam row
44
+ PH = numpy.vstack([PH, PH[0:1, :]])
45
+
46
+ TH = numpy.hstack([TH, TH[:, 0:1]]) # add theta seam col
47
+ PH = numpy.hstack([PH, PH[:, 0:1]])
48
+
49
+ # torus embedding
50
+ X = (R + r*numpy.cos(PH)) * numpy.cos(TH)
51
+ Y = (R + r*numpy.cos(PH)) * numpy.sin(TH)
52
+ Z = r * numpy.sin(PH)
53
+
54
+ return X, Y, Z, TH, PH
55
+
56
+
57
+ # =============
58
+ # u from angles
59
+ # =============
60
+
61
+ def u_from_angles(TH, PH, lam, center=(0.0, 0.0)):
62
+ """
63
+ Map angles (TH,PH) in [0,2pi)^2 to the elliptic u-plane fundamental cell.
64
+
65
+ u = u0 + (omega1/2pi)*TH + (omega2/2pi)*PH,
66
+ omega1 = 2K(m), omega2 = 2 i K(1-m).
67
+ """
68
+
69
+ m = float(lam)
70
+ K = scipy.special.ellipk(m)
71
+ Kp = scipy.special.ellipk(1.0 - m)
72
+ omega1 = 2.0 * K
73
+ omega2 = 2.0j * Kp
74
+
75
+ u0 = complex(center[0], center[1]) # shift inside the fundamental domain
76
+ u = u0 + (omega1/(2.0*numpy.pi))*TH + (omega2/(2.0*numpy.pi))*PH
77
+
78
+ return u
79
+
80
+
81
+ # ==========================
82
+ # evaluate fitted m on torus
83
+ # ==========================
84
+
85
+ def eval_fitted_m_on_torus(u, a1, b1, a2, b2, p0, p1, q, lam):
86
+ """
87
+ Evaluate the *uniformized* branch m(u) = (p0(X)+Y p1(X))/q(X)
88
+ with X = lam * sn(u)^2 and Y chosen to match the elliptic derivative sign.
89
+
90
+ Requires jacobi_ellipj(u, m) that supports complex arrays and returns
91
+ (sn,cn,dn).
92
+ """
93
+
94
+ sn, cn, dn, _ = ellipj(u, lam)
95
+
96
+ X = lam * (sn * sn)
97
+
98
+ # canonical algebraic Y from curve: Y^2 = X(1-X)(X-lam)
99
+ D = X * (1.0 - X) * (X - lam)
100
+
101
+ Y = numpy.sqrt(D)
102
+
103
+ # enforce "positive imag" convention first
104
+ Y = numpy.where(numpy.imag(Y) < 0.0, -Y, Y)
105
+
106
+ # now align sign with elliptic reference:
107
+ # for Legendre normalization: dX/du = 2 i Y_ref, where Y_ref is equal to
108
+ # i*lam*sn*cn*dn (up to consistent conventions)
109
+ Y_ref = 1j * lam * (sn * cn * dn)
110
+ flip = numpy.real(Y * numpy.conjugate(Y_ref)) < 0.0
111
+ Y = numpy.where(flip, -Y, Y)
112
+
113
+ num0 = _poly_eval(X, p0)
114
+ num1 = _poly_eval(X, p1)
115
+ den = _poly_eval(X, q)
116
+
117
+ m = (num0 + Y * num1) / den
118
+ return m