freealg 0.5.4__py3-none-any.whl → 0.6.1__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.
freealg/freeform.py CHANGED
@@ -12,10 +12,8 @@
12
12
  # =======
13
13
 
14
14
  import numpy
15
- from scipy.stats import gaussian_kde
16
- # from statsmodels.nonparametric.kde import KDEUnivariate
17
15
  from functools import partial
18
- from ._util import compute_eig, beta_kde, force_density
16
+ from ._util import resolve_complex_dtype, compute_eig, kde, force_density
19
17
  from ._jacobi import jacobi_sample_proj, jacobi_kernel_proj, jacobi_density, \
20
18
  jacobi_stieltjes
21
19
  from ._chebyshev import chebyshev_sample_proj, chebyshev_kernel_proj, \
@@ -25,8 +23,8 @@ from ._damp import jackson_damping, lanczos_damping, fejer_damping, \
25
23
  from ._plot_util import plot_fit, plot_density, plot_hilbert, plot_stieltjes
26
24
  from ._pade import fit_pade, eval_pade
27
25
  from ._decompress import decompress
28
- from ._sample import qmc_sample
29
- from ._support import detect_support
26
+ from ._sample import sample
27
+ from ._support import supp
30
28
 
31
29
  # Fallback to previous numpy API
32
30
  if not hasattr(numpy, 'trapezoid'):
@@ -59,8 +57,21 @@ class FreeForm(object):
59
57
  Size of perturbations into the upper half plane for Plemelj's
60
58
  formula.
61
59
 
60
+ dtype : {``'complex128'``, ``'complex256'``}, default = ``'complex128'``
61
+ Data type for inner computations of complex variables:
62
+
63
+ * ``'complex128'``: 128-bit complex numbers, equivalent of two double
64
+ precision floating point.
65
+ * ``'complex256'``: 256-bit complex numbers, equivalent of two long
66
+ double precision floating point. This optino is only available on
67
+ Linux machines.
68
+
69
+ When using series acceleration methods (such as setting
70
+ ``continuation`` in :func:`fit` function to ``wynn-eps``), setting a
71
+ higher precision floating point arithmetics might improve conference.
72
+
62
73
  **kwargs : dict, optional
63
- Parameters for the ``detect_support`` function can also be prescribed
74
+ Parameters for the :func:`supp` function can also be prescribed
64
75
  here when ``support=None``.
65
76
 
66
77
  Notes
@@ -135,7 +146,8 @@ class FreeForm(object):
135
146
  # init
136
147
  # ====
137
148
 
138
- def __init__(self, A, support=None, delta=1e-6, **kwargs):
149
+ def __init__(self, A, support=None, delta=1e-6, dtype='complex128',
150
+ **kwargs):
139
151
  """
140
152
  Initialization.
141
153
  """
@@ -144,6 +156,9 @@ class FreeForm(object):
144
156
  self.eig = None
145
157
  self.delta = delta # Offset above real axis to apply Plemelj formula
146
158
 
159
+ # Data type for complex arrays
160
+ self.dtype = resolve_complex_dtype(dtype)
161
+
147
162
  # Eigenvalues
148
163
  if A.ndim == 1:
149
164
  # When A is a 1D array, it is assumed A is the eigenvalue array.
@@ -160,12 +175,16 @@ class FreeForm(object):
160
175
 
161
176
  # Support
162
177
  if support is None:
163
- self.lam_m, self.lam_p = detect_support(self.eig, **kwargs)
178
+ # Detect support
179
+ self.lam_m, self.lam_p = supp(self.eig, **kwargs)
164
180
  else:
165
- self.lam_m = support[0]
166
- self.lam_p = support[1]
181
+ self.lam_m = float(support[0])
182
+ self.lam_p = float(support[1])
167
183
  self.support = (self.lam_m, self.lam_p)
168
184
 
185
+ # Number of quadrature points to evaluate Stieltjes using Gauss-Jacobi
186
+ self.n_quad = None
187
+
169
188
  # Initialize
170
189
  self.method = None # fitting rho: jacobi, chebyshev
171
190
  self.continuation = None # analytic continuation: pade, wynn
@@ -173,15 +192,17 @@ class FreeForm(object):
173
192
  self.psi = None # coefficients of estimating rho
174
193
  self.alpha = None # Jacobi polynomials alpha parameter
175
194
  self.beta = None # Jacobi polynomials beta parameter
195
+ self.cache = {} # Cache inner-computations
176
196
 
177
197
  # ===
178
198
  # fit
179
199
  # ===
180
200
 
181
- def fit(self, method='jacobi', K=10, alpha=0.0, beta=0.0, reg=0.0,
182
- projection='gaussian', kernel_bw=0.001, damp=None, force=False,
183
- continuation='pade', pade_p=0, pade_q=1, odd_side='left',
184
- pade_reg=0.0, optimizer='ls', plot=False, latex=False, save=False):
201
+ def fit(self, method='jacobi', K=10, alpha=0.0, beta=0.0, n_quad=60,
202
+ reg=0.0, projection='gaussian', kernel_bw=0.001, damp=None,
203
+ force=False, continuation='pade', pade_p=0, pade_q=1,
204
+ odd_side='left', pade_reg=0.0, optimizer='ls', plot=False,
205
+ latex=False, save=False):
185
206
  """
186
207
  Fit model to eigenvalues.
187
208
 
@@ -205,6 +226,11 @@ class FreeForm(object):
205
226
  fitting model on the left side of interval. This should be greater
206
227
  then -1. This option is only applicable when ``method='jacobi'``.
207
228
 
229
+ n_quad : int, default=60
230
+ Number of quadrature points to evaluate Stieltjes transform later
231
+ on (when :func:`decompress` is called) using Gauss-Jacob
232
+ quadrature. This option is relevant only if ``method='jacobi'``.
233
+
208
234
  reg : float, default=0.0
209
235
  Tikhonov regularization coefficient.
210
236
 
@@ -234,7 +260,7 @@ class FreeForm(object):
234
260
  If `True`, it forces the density to have unit mass and to be
235
261
  strictly positive.
236
262
 
237
- continuation : {``'pade'``, ``'wynn-eps'``, ``'wynn-rho'``,
263
+ continuation : {``'pade'``, ``'wynn-eps'``, ``'wynn-rho'``, \
238
264
  ``'levin'``, ``'weniger'``, ``'brezinski'``}, default= ``'pade'``
239
265
  Method of analytic continuation to construct the second branch of
240
266
  Steltjes transform in the lower-half complex plane:
@@ -242,10 +268,12 @@ class FreeForm(object):
242
268
  * ``'pade'``: using Riemann-Hilbert problem with Pade
243
269
  approximation.
244
270
  * ``'wynn-eps'``: Wynn's :math:`\\epsilon` algorithm.
245
- * ``'wynn-rho'``: Wynn's :math:`\\rho` algorithm.
246
- * ``'levin'``: Levin's :math:`u` transform.
247
- * ``'weniger'``: Weniger's :math:`\\delta^2` algorithm.
248
- * ``'brezinski'``: Brezinski's :math:`\\theta` algorithm.
271
+ * ``'wynn-rho'``: Wynn's :math:`\\rho` algorithm (`experimental`).
272
+ * ``'levin'``: Levin's :math:`u` transform (`experimental`).
273
+ * ``'weniger'``: Weniger's :math:`\\delta^2` algorithm
274
+ (`experimental`).
275
+ * ``'brezinski'``: Brezinski's :math:`\\theta` algorithm
276
+ (`experimental`).
249
277
 
250
278
  pade_p : int, default=0
251
279
  Degree of polynomial :math:`P(z)` is :math:`q+p` where :math:`p`
@@ -318,6 +346,10 @@ class FreeForm(object):
318
346
  >>> from freealg import FreeForm
319
347
  """
320
348
 
349
+ # Very important: reset cache whenever this function is called. This
350
+ # also empties all references holdign a cache copy.
351
+ self.cache.clear()
352
+
321
353
  if alpha <= -1:
322
354
  raise ValueError('"alpha" should be greater then "-1".')
323
355
 
@@ -333,56 +365,42 @@ class FreeForm(object):
333
365
  # Project eigenvalues to Jacobi polynomials basis
334
366
  if method == 'jacobi':
335
367
 
368
+ # Set number of Gauss-Jacobi quadratures. This is not used in this
369
+ # function (used later when decompress is called)
370
+ self.n_quad = n_quad
371
+
336
372
  if projection == 'sample':
337
373
  psi = jacobi_sample_proj(self.eig, support=self.support, K=K,
338
374
  alpha=alpha, beta=beta, reg=reg)
339
- else:
375
+ elif projection in ['gaussian', 'beta']:
340
376
  # smooth KDE on a fixed grid
341
377
  xs = numpy.linspace(self.lam_m, self.lam_p, 2000)
342
378
 
343
- if projection == 'gaussian':
344
- pdf = gaussian_kde(self.eig, bw_method=kernel_bw)(xs)
345
- else:
346
- pdf = beta_kde(self.eig, xs, self.lam_m, self.lam_p,
347
- kernel_bw)
348
-
349
- # Adaptive KDE
350
- # k = KDEUnivariate(self.eig)
351
- # k.fit(bw="silverman", fft=False, weights=None, gridsize=1024,
352
- # adaptive=True)
353
- # pdf = k.evaluate(xs)
354
-
355
- # import matplotlib.pyplot as plt
356
- # plt.plot(xs, pdf)
357
- # plt.grid(True)
358
- # plt.show()
379
+ pdf = kde(self.eig, xs, self.lam_m, self.lam_p, kernel_bw,
380
+ kernel=projection)
359
381
 
360
382
  psi = jacobi_kernel_proj(xs, pdf, support=self.support, K=K,
361
383
  alpha=alpha, beta=beta, reg=reg)
384
+ else:
385
+ raise NotImplementedError('"projection" is invalid.')
362
386
 
363
387
  elif method == 'chebyshev':
364
388
 
365
389
  if projection == 'sample':
366
390
  psi = chebyshev_sample_proj(self.eig, support=self.support,
367
391
  K=K, reg=reg)
368
- else:
392
+ elif projection in ['gaussian', 'beta']:
369
393
  # smooth KDE on a fixed grid
370
394
  xs = numpy.linspace(self.lam_m, self.lam_p, 2000)
371
395
 
372
- if projection == 'gaussian':
373
- pdf = gaussian_kde(self.eig, bw_method=kernel_bw)(xs)
374
- else:
375
- pdf = beta_kde(self.eig, xs, self.lam_m, self.lam_p,
376
- kernel_bw)
377
-
378
- # Adaptive KDE
379
- # k = KDEUnivariate(self.eig)
380
- # k.fit(bw="silverman", fft=False, weights=None, gridsize=1024,
381
- # adaptive=True)
382
- # pdf = k.evaluate(xs)
396
+ pdf = kde(self.eig, xs, self.lam_m, self.lam_p, kernel_bw,
397
+ kernel=projection)
383
398
 
384
399
  psi = chebyshev_kernel_proj(xs, pdf, support=self.support,
385
400
  K=K, reg=reg)
401
+ else:
402
+ raise NotImplementedError('"projection" is invalid.')
403
+
386
404
  else:
387
405
  raise NotImplementedError('"method" is invalid.')
388
406
 
@@ -639,8 +657,8 @@ class FreeForm(object):
639
657
  diff = x[:, None] - x_s[None, :]
640
658
  D = rho_s[None, :] / diff
641
659
 
642
- # Principalvalue: wherever t == x_i, then diff == 0, zero that entry
643
- # (numpy.isclose handles floatingpoint exactly)
660
+ # Principal-value: wherever t == x_i, then diff == 0, zero that entry
661
+ # (numpy.isclose handles floating-point exactly)
644
662
  D[numpy.isclose(diff, 0.0)] = 0.0
645
663
 
646
664
  # Integrate each row over t using trapezoid rule on x_s
@@ -726,6 +744,7 @@ class FreeForm(object):
726
744
 
727
745
  See Also
728
746
  --------
747
+
729
748
  density
730
749
  hilbert
731
750
 
@@ -757,7 +776,7 @@ class FreeForm(object):
757
776
 
758
777
  # Create y if not given
759
778
  if (plot is False) and (y is None):
760
- # Do no tuse a Cartesian grid. Create a 1D array z slightly above
779
+ # Do not use a Cartesian grid. Create a 1D array z slightly above
761
780
  # the real line.
762
781
  y = self.delta * 1j
763
782
  z = x.astype(complex) + y # shape (Nx,)
@@ -809,29 +828,39 @@ class FreeForm(object):
809
828
  if self.psi is None:
810
829
  raise RuntimeError('"fit" the model first.')
811
830
 
812
- # Allow for arbitrary input shapes
813
831
  z = numpy.asarray(z)
814
- shape = z.shape
815
- if len(shape) == 0:
816
- shape = (1,)
817
- z = z.reshape(-1, 1)
818
-
819
- # # Set the number of bases as the number of x points insides support
820
- # mask_sup = numpy.logical_and(z.real >= self.lam_m,
821
- # z.real <= self.lam_p)
822
- # n_base = 2 * numpy.sum(mask_sup)
823
832
 
824
833
  # Stieltjes function
825
834
  if self.method == 'jacobi':
826
- stieltjes = partial(jacobi_stieltjes, psi=self.psi,
827
- support=self.support, alpha=self.alpha,
828
- beta=self.beta, continuation=self.continuation)
829
- # n_base = n_base
835
+
836
+ # Number of quadrature points
837
+ if z.ndim == 2:
838
+ # set to twice num x points inside support. This oversampling
839
+ # avoids anti-aliasing when visualizing.
840
+ x = z[0, :].real
841
+ mask_sup = numpy.logical_and(x >= self.lam_m, x <= self.lam_p)
842
+ n_quad = 2 * numpy.sum(mask_sup)
843
+ else:
844
+ # If this is None, the calling function will handle it.
845
+ n_quad = self.n_quad
846
+
847
+ stieltjes = partial(jacobi_stieltjes, cache=self.cache,
848
+ psi=self.psi, support=self.support,
849
+ alpha=self.alpha, beta=self.beta,
850
+ continuation=self.continuation,
851
+ dtype=self.dtype, n_quad=n_quad)
830
852
 
831
853
  elif self.method == 'chebyshev':
832
854
  stieltjes = partial(chebyshev_stieltjes, psi=self.psi,
833
855
  support=self.support,
834
- continuation=self.continuation)
856
+ continuation=self.continuation,
857
+ dtype=self.dtype)
858
+
859
+ # Allow for arbitrary input shapes
860
+ shape = z.shape
861
+ if len(shape) == 0:
862
+ shape = (1,)
863
+ z = z.reshape(-1, 1)
835
864
 
836
865
  mask_p = z.imag >= 0.0
837
866
  mask_m = z.imag < 0.0
@@ -928,7 +957,7 @@ class FreeForm(object):
928
957
  Estimated spectral density at locations x. ``rho`` can be a 1D or
929
958
  2D array output:
930
959
 
931
- * If ``size`` is a scalar, ``rho`` is a 1D array od the same size
960
+ * If ``size`` is a scalar, ``rho`` is a 1D array of the same size
932
961
  as ``x``.
933
962
  * If ``size`` is an array of size `n`, ``rho`` is a 2D array with
934
963
  `n` rows, where each row corresponds to decompression to a size.
@@ -1002,7 +1031,7 @@ class FreeForm(object):
1002
1031
  # Initial guess for roots (only for the first iteration)
1003
1032
  # if i == 0:
1004
1033
  # roots = numpy.full(x.shape, numpy.mean(self.support) - 0.1j,
1005
- # dtype=numpy.complex128)
1034
+ # dtype=self.dtype)
1006
1035
  roots = None
1007
1036
 
1008
1037
  rho[i, :], roots = decompress(
@@ -1081,7 +1110,7 @@ class FreeForm(object):
1081
1110
  size = self.n
1082
1111
 
1083
1112
  rho, x = self.decompress(size, **kwargs)
1084
- eigs = numpy.sort(qmc_sample(x, rho, size, seed=seed))
1113
+ eigs = numpy.sort(sample(x, rho, size, method='qmc', seed=seed))
1085
1114
 
1086
1115
  return eigs
1087
1116
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freealg
3
- Version: 0.5.4
3
+ Version: 0.6.1
4
4
  Summary: Free probability for large matrices
5
5
  Home-page: https://github.com/ameli/freealg
6
6
  Download-URL: https://github.com/ameli/freealg/archive/main.zip
@@ -0,0 +1,26 @@
1
+ freealg/__init__.py,sha256=muuYCvlsXjuX1W67YGFca9nFxprFsALLyB3CrJpXFnY,728
2
+ freealg/__version__.py,sha256=baAcEjLSYFIeNZF51tOMmA_zAMhN8HvKael-UU-Ruec,22
3
+ freealg/_chebyshev.py,sha256=zkyVA8NLf7uUKlJdLz4ijd_SurdsqUgkA5nHGWSybaE,6916
4
+ freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
+ freealg/_decompress.py,sha256=bFhQx--uptWJ7OjVwEs_tWYT6mLijBKJ9EbrD24Sbl0,32199
6
+ freealg/_jacobi.py,sha256=z0X6Ws_BEo_h8EQBzDNHGFhLF9F2PUmnGeBVs0bNL7w,10709
7
+ freealg/_linalg.py,sha256=0BzJNTXiY1VH3OKrCFgbE0QHLgRoKyiILsBWtnygFGc,13141
8
+ freealg/_pade.py,sha256=BthDHScn2lILTTU2hlGNP-8YqddU3Uyxe0n0FkprwDs,13645
9
+ freealg/_plot_util.py,sha256=GKvmc1wjVGeqoomrULPbzBEt6P86FdoR2idBLYh5EDY,20068
10
+ freealg/_sample.py,sha256=yLJSGlq27j8tA-kDntRwfHIUU8Oo2IOmOTxS8yTRGRU,3075
11
+ freealg/_series.py,sha256=33LLCUe4svmV0eWyzhP_XClfDzccQHTW9WBJlYlLfHY,11475
12
+ freealg/_support.py,sha256=nxDa2OFlWBgjD0_1qoSMWG7kub6-GIuxIA04n5bdaYw,6614
13
+ freealg/_util.py,sha256=NaEhcOxbue44l_xAhefnNZYTy3pBBGBFyk9HdaRjQKo,6899
14
+ freealg/freeform.py,sha256=FBC9ab-3JWaQibMAM4LlbYPYvELaUDReJWCwAG0Fwwg,43779
15
+ freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
16
+ freealg/distributions/_kesten_mckay.py,sha256=BM_U8cX3eRstbAA4IZRK4qA_6S9zcogaXeuHyKXen14,19897
17
+ freealg/distributions/_marchenko_pastur.py,sha256=xwk40GwpLvEm9--FN7-T2NWtHTkfzcvOS4tFyrm71ww,16990
18
+ freealg/distributions/_meixner.py,sha256=8zmDnoCp-GOMnd6T2rKLQaMfn6uFmSnd-i5PLlfGOUM,17526
19
+ freealg/distributions/_wachter.py,sha256=d601xAaFSVGeK13SSDavjsJ5a-MJnI2mgzWiplX0Quk,16898
20
+ freealg/distributions/_wigner.py,sha256=w8OlZL9pSfGnXVSSB6A4KBiImr0Zz4iH2PDLCHFfpaY,15877
21
+ freealg-0.6.1.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
22
+ freealg-0.6.1.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
23
+ freealg-0.6.1.dist-info/METADATA,sha256=0iyTPrQe2ZBGlPQr9dAOsunwRx_KS6dRFSaz__Uq2oI,5530
24
+ freealg-0.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ freealg-0.6.1.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
26
+ freealg-0.6.1.dist-info/RECORD,,
@@ -1,26 +0,0 @@
1
- freealg/__init__.py,sha256=KfzqG7qig6ZZCKqgHcC2ApTg4rTLkrbJsvVoJd8UFG8,625
2
- freealg/__version__.py,sha256=DITpct-LrdIsTgwx2NgH5Ghx5y8Xgz1YMimy1ZV5RTY,22
3
- freealg/_chebyshev.py,sha256=UHU9e9LyiTJcs_01h3oIbX8_QQ9wH0P8GRmA3phvWhU,6780
4
- freealg/_damp.py,sha256=k2vtBtWOxQBf4qXaWu_En81lQBXbEO4QbxxWpvuVhdE,1802
5
- freealg/_decompress.py,sha256=RKYnuLKMx1V6-XrFjYX1UkGMRbUD9Gmf9XTyS4ffPSc,31970
6
- freealg/_jacobi.py,sha256=k1zYZtvoA3_gcanqepIVSoA0RJrExtluQzDamkRz_Uk,7570
7
- freealg/_linalg.py,sha256=0BzJNTXiY1VH3OKrCFgbE0QHLgRoKyiILsBWtnygFGc,13141
8
- freealg/_pade.py,sha256=Ecm373RvBWznAaf8a5D9qtjcRA8O_8NQsePwto-dsP4,13656
9
- freealg/_plot_util.py,sha256=GKvmc1wjVGeqoomrULPbzBEt6P86FdoR2idBLYh5EDY,20068
10
- freealg/_sample.py,sha256=MUY9ZkJbdhbC5thoy5_JMRWOHz_OfqMfaH0g2VhKPhg,2550
11
- freealg/_series.py,sha256=MV8yDHentc06aqPuPlqrIQUNgG0-WiviD8ZWMmLWC0I,11490
12
- freealg/_support.py,sha256=ZfU0T7CCDaTXMdEHSbwOL-rMnCPvJWsRb6JtqUMsrzY,6441
13
- freealg/_util.py,sha256=xKhtPgbW4vHidNAG6F5c5aQhTaG4MmaUqCsxwjBznfU,3786
14
- freealg/freeform.py,sha256=i09DcRikLL6dlsu4JzoC1AQ7EHTyacx2fgyEz3hFakI,42432
15
- freealg/distributions/__init__.py,sha256=t_yZyEkW_W_tSV9IvgYXtVASxD2BEdiNVXcV2ebMy8M,579
16
- freealg/distributions/_kesten_mckay.py,sha256=4EvW0seBZUv-cZjuLzfVCredmrCiOJcQ_hJM0mJDl6g,19899
17
- freealg/distributions/_marchenko_pastur.py,sha256=r-jmz8Wq5vG0-x7rB0qvVemqvu0Oq6S-BN67pqH0uiw,16992
18
- freealg/distributions/_meixner.py,sha256=bZv-x4mwS4yjisKoYSZAffHXtvDEKEis-74BeAjK4_s,17530
19
- freealg/distributions/_wachter.py,sha256=rkAmrBLqD2zvpBh0F32aQBscjXv8earXDH9_BITgFF0,16900
20
- freealg/distributions/_wigner.py,sha256=w8OlZL9pSfGnXVSSB6A4KBiImr0Zz4iH2PDLCHFfpaY,15877
21
- freealg-0.5.4.dist-info/licenses/AUTHORS.txt,sha256=0b67Nz4_JgIzUupHJTAZxu5QdSUM_HRM_X_w4xCb17o,30
22
- freealg-0.5.4.dist-info/licenses/LICENSE.txt,sha256=J-EEYEtxb3VVf_Bn1TYfWnpY5lMFIM15iLDDcnaDTPA,1443
23
- freealg-0.5.4.dist-info/METADATA,sha256=JVYKHOmi-IQ1z0jMhAIBqzK1QbblWy9B2aEtGWvZdkQ,5530
24
- freealg-0.5.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- freealg-0.5.4.dist-info/top_level.txt,sha256=eR2wrgYwDdnnJ9Zf5PruPqe4kQav0GMvRsqct6y00Q8,8
26
- freealg-0.5.4.dist-info/RECORD,,