sphere-n 0.2__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.
- sphere_n/__init__.py +16 -0
- sphere_n/cylind_n.py +88 -0
- sphere_n/discrep_2.py +26 -0
- sphere_n/sphere_n.py +195 -0
- sphere_n-0.2.dist-info/METADATA +65 -0
- sphere_n-0.2.dist-info/RECORD +9 -0
- sphere_n-0.2.dist-info/WHEEL +5 -0
- sphere_n-0.2.dist-info/licenses/LICENSE.txt +21 -0
- sphere_n-0.2.dist-info/top_level.txt +1 -0
sphere_n/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
if sys.version_info[:2] >= (3, 8):
|
|
4
|
+
# TODO: Import directly (no need for conditional) when `python_requires = >= 3.9`
|
|
5
|
+
from importlib.metadata import PackageNotFoundError, version # pragma: no cover
|
|
6
|
+
else:
|
|
7
|
+
from importlib_metadata import PackageNotFoundError, version # pragma: no cover
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
# Change here if project is renamed and does not equal the package name
|
|
11
|
+
dist_name = "sphere-n"
|
|
12
|
+
__version__ = version(dist_name)
|
|
13
|
+
except PackageNotFoundError: # pragma: no cover
|
|
14
|
+
__version__ = "unknown"
|
|
15
|
+
finally:
|
|
16
|
+
del version, PackageNotFoundError
|
sphere_n/cylind_n.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This code defines a system for generating points on an n-dimensional sphere using a technique called cylindrical mapping. The main purpose is for the sake of comparison with the sphere_n.py code.
|
|
3
|
+
|
|
4
|
+
The code takes a list of integers as input, which are used as bases for the low-discrepancy sequence generators. These generators help create a more uniform distribution of points compared to random sampling.
|
|
5
|
+
|
|
6
|
+
The output of this code is a list of floating-point numbers representing coordinates on the n-dimensional sphere. Each time you call the pop() method of a CylindN object, it produces a new set of coordinates.
|
|
7
|
+
|
|
8
|
+
The code achieves its purpose through a recursive algorithm. It uses two main components: a van der Corput sequence generator (VdCorput) for one dimension, and either a Circle generator or another CylindN generator for the remaining dimensions. This recursive structure allows it to handle spheres of any dimension.
|
|
9
|
+
|
|
10
|
+
The main logic flow happens in the pop() method. It first generates a cosine value (cosphi) using the van der Corput sequence, mapping it to the range [-1, 1]. Then it calculates the sine value (sinphi) using the Pythagorean identity. The method then recursively generates coordinates for lower dimensions and scales them by sinphi, finally adding cosphi as the last coordinate.
|
|
11
|
+
|
|
12
|
+
An important data transformation occurs in the pop() method, where the uniform distribution from the van der Corput sequence is transformed into a cosine distribution, which is necessary for proper spherical mapping.
|
|
13
|
+
|
|
14
|
+
The code also includes a reseed() method, which allows you to reset the internal state of the generators. This is useful for reproducibility in scientific simulations or when you need to generate the same sequence of points multiple times.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from abc import abstractmethod, ABC
|
|
18
|
+
from typing import List
|
|
19
|
+
|
|
20
|
+
# import numexpr as ne
|
|
21
|
+
from lds_gen.lds import Circle, VdCorput # low-discrepancy sequence generators
|
|
22
|
+
import numpy as np
|
|
23
|
+
import math
|
|
24
|
+
|
|
25
|
+
PI: float = np.pi
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CylindGen(ABC):
|
|
29
|
+
"""Base interface for n-sphere generators using cylindrical mapping."""
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def pop(self) -> List[float]:
|
|
33
|
+
"""Generates and returns a vector of values."""
|
|
34
|
+
raise NotImplementedError
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def reseed(self, seed: int) -> None:
|
|
38
|
+
"""Reseeds the generator with a new seed."""
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CylindN(CylindGen):
|
|
43
|
+
"""Low-discrepency sequence generator using cylindrical mapping.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
>>> cgen = CylindN([2, 3, 5, 7])
|
|
47
|
+
>>> cgen.reseed(0)
|
|
48
|
+
>>> for _ in range(1):
|
|
49
|
+
... print(cgen.pop())
|
|
50
|
+
...
|
|
51
|
+
[0.4702654580212986, 0.5896942325314937, -0.565685424949238, -0.33333333333333337, 0.0]
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, base: List[int]) -> None:
|
|
55
|
+
"""_summary_
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
base (List[int]): _description_
|
|
59
|
+
"""
|
|
60
|
+
n = len(base) - 1
|
|
61
|
+
assert n >= 1
|
|
62
|
+
self.vdc = VdCorput(base[0])
|
|
63
|
+
self.c_gen = Circle(base[1]) if n == 1 else CylindN(base[1:])
|
|
64
|
+
|
|
65
|
+
def pop(self) -> List[float]:
|
|
66
|
+
"""_summary_
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
List[float]: _description_
|
|
70
|
+
"""
|
|
71
|
+
cosphi = 2.0 * self.vdc.pop() - 1.0 # map to [-1, 1]
|
|
72
|
+
sinphi = math.sqrt(1.0 - cosphi * cosphi)
|
|
73
|
+
return [xi * sinphi for xi in self.c_gen.pop()] + [cosphi]
|
|
74
|
+
|
|
75
|
+
def reseed(self, seed: int) -> None:
|
|
76
|
+
"""_summary_
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
seed (int): _description_
|
|
80
|
+
"""
|
|
81
|
+
self.vdc.reseed(seed)
|
|
82
|
+
self.c_gen.reseed(seed)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
import doctest
|
|
87
|
+
|
|
88
|
+
doctest.testmod()
|
sphere_n/discrep_2.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def discrep_2(K, X):
|
|
5
|
+
"""dispersion measure
|
|
6
|
+
|
|
7
|
+
Arguments:
|
|
8
|
+
K ([type]): [description]
|
|
9
|
+
X ([type]): [description]
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
float: dispersion
|
|
13
|
+
"""
|
|
14
|
+
nsimplex, n = K.shape
|
|
15
|
+
maxq = 0
|
|
16
|
+
minq = 1000
|
|
17
|
+
for k in range(nsimplex):
|
|
18
|
+
p = X[K[k, :], :]
|
|
19
|
+
for i in range(n - 1):
|
|
20
|
+
for j in range(i + 1, n):
|
|
21
|
+
dot = np.dot(p[i, :], p[j, :])
|
|
22
|
+
q = 1.0 - dot * dot
|
|
23
|
+
maxq = max(maxq, q)
|
|
24
|
+
minq = min(minq, q)
|
|
25
|
+
dis = np.arcsin(np.sqrt(maxq)) - np.arcsin(np.sqrt(minq))
|
|
26
|
+
return dis
|
sphere_n/sphere_n.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sphere N Generator
|
|
3
|
+
|
|
4
|
+
This code is a Sphere N Generator, which is designed to create points on the surface of spheres in different dimensions. It's a tool that mathematicians, scientists, or computer graphics programmers might use when they need to work with spherical shapes in multiple dimensions.
|
|
5
|
+
|
|
6
|
+
The main input for this code is a list of integers, which are used as bases for generating sequences of numbers. These bases are used to initialize different types of generators that create points on spheres.
|
|
7
|
+
|
|
8
|
+
The output of this code is a series of lists containing floating-point numbers. Each list represents a point on the surface of a sphere, with the number of elements in the list corresponding to the dimension of the sphere.
|
|
9
|
+
|
|
10
|
+
To achieve its purpose, the code uses several mathematical concepts and algorithms. It starts by defining some constants and helper functions that are used in the calculations. These functions (get_tp_odd, get_tp_even, and get_tp) create lookup tables for mapping values in different dimensions.
|
|
11
|
+
|
|
12
|
+
The code then defines several classes that generate points on spheres:
|
|
13
|
+
|
|
14
|
+
1. SphereGen: This is an abstract base class that defines the common interface for all sphere generators.
|
|
15
|
+
|
|
16
|
+
2. Sphere3: This class generates points on a 3-dimensional sphere. It uses a combination of van der Corput sequences and 2-dimensional sphere points to create 3D points.
|
|
17
|
+
|
|
18
|
+
3. SphereN: This class can generate points on spheres of any dimension (3 or higher). It uses a recursive approach, building higher-dimensional spheres from lower-dimensional ones.
|
|
19
|
+
|
|
20
|
+
Each of these classes has methods to generate new points (pop) and to reset the generator with a new starting point (reseed).
|
|
21
|
+
|
|
22
|
+
The code achieves its purpose through a combination of mathematical transformations and recursive algorithms. It uses trigonometric functions (sine, cosine) and interpolation to map values from one range to another. The core idea is to generate sequences of numbers that, when interpreted as coordinates, create an even distribution across the surface of a sphere.
|
|
23
|
+
|
|
24
|
+
An important aspect of the code is its use of caching (@cache decorator) for some functions. This improves performance by storing the results of expensive calculations so they don't need to be repeated.
|
|
25
|
+
|
|
26
|
+
Overall, this code provides a flexible way to generate evenly distributed points on spheres of various dimensions, which can be useful in many scientific and graphical applications.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from abc import abstractmethod, ABC
|
|
30
|
+
from typing import List
|
|
31
|
+
|
|
32
|
+
# import numexpr as ne
|
|
33
|
+
from lds_gen.lds import Sphere, VdCorput # low-discrepancy sequence generators
|
|
34
|
+
from functools import cache
|
|
35
|
+
import numpy as np
|
|
36
|
+
import math
|
|
37
|
+
|
|
38
|
+
PI: float = np.pi
|
|
39
|
+
X: np.ndarray = np.linspace(0.0, PI, 300)
|
|
40
|
+
NEG_COSINE: np.ndarray = -np.cos(X)
|
|
41
|
+
SINE: np.ndarray = np.sin(X)
|
|
42
|
+
F2: np.ndarray = (X + NEG_COSINE * SINE) / 2.0
|
|
43
|
+
HALF_PI = PI / 2.0
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@cache
|
|
47
|
+
def get_tp_odd(n: int) -> np.ndarray:
|
|
48
|
+
"""table-lookup of mapping function for odd n
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
np.ndarray: _description_
|
|
52
|
+
"""
|
|
53
|
+
if n == 1:
|
|
54
|
+
return NEG_COSINE
|
|
55
|
+
tp_minus2 = get_tp_odd(n - 2) # NOQA
|
|
56
|
+
# return ne.evaluate("((n - 1) * tp_minus2 + NEG_COSINE * SINE**(n - 1)) / n")
|
|
57
|
+
return ((n - 1) * tp_minus2 + NEG_COSINE * SINE ** (n - 1)) / n
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@cache
|
|
61
|
+
def get_tp_even(n: int) -> np.ndarray:
|
|
62
|
+
"""table-lookup of mapping function for even n
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
np.ndarray: _description_
|
|
66
|
+
"""
|
|
67
|
+
if n == 0:
|
|
68
|
+
return X
|
|
69
|
+
tp_minus2 = get_tp_even(n - 2) # NOQA
|
|
70
|
+
# return ne.evaluate("((n - 1) * tp_minus2 + NEG_COSINE * SINE**(n - 1)) / n")
|
|
71
|
+
return ((n - 1) * tp_minus2 + NEG_COSINE * SINE ** (n - 1)) / n
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_tp(n: int) -> np.ndarray:
|
|
75
|
+
"""table-lookup of mapping function for n
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
np.ndarray: _description_
|
|
79
|
+
"""
|
|
80
|
+
return get_tp_even(n) if n % 2 == 0 else get_tp_odd(n)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class SphereGen(ABC):
|
|
84
|
+
"""Base class for sphere generators."""
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def pop(self) -> List[float]:
|
|
88
|
+
"""Generates and returns a vector of values."""
|
|
89
|
+
raise NotImplementedError
|
|
90
|
+
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def reseed(self, seed: int) -> None:
|
|
93
|
+
"""Reseeds the generator with a new seed."""
|
|
94
|
+
raise NotImplementedError
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class Sphere3(SphereGen):
|
|
98
|
+
"""3-Sphere sequence generator
|
|
99
|
+
|
|
100
|
+
Examples:
|
|
101
|
+
>>> sgen = Sphere3([2, 3, 5])
|
|
102
|
+
>>> sgen.reseed(0)
|
|
103
|
+
>>> for _ in range(1):
|
|
104
|
+
... print(sgen.pop())
|
|
105
|
+
...
|
|
106
|
+
[0.2913440162992141, 0.8966646826186098, -0.33333333333333337, 6.123233995736766e-17]
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
vdc: VdCorput # van der Corput sequence generator
|
|
110
|
+
sphere2: Sphere # 2-Sphere generator
|
|
111
|
+
|
|
112
|
+
def __init__(self, base: List[int]) -> None:
|
|
113
|
+
"""_summary_
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
base (List[int]): _description_
|
|
117
|
+
"""
|
|
118
|
+
self.vdc = VdCorput(base[0])
|
|
119
|
+
self.sphere2 = Sphere(base[1:3])
|
|
120
|
+
|
|
121
|
+
def reseed(self, seed: int) -> None:
|
|
122
|
+
"""_summary_
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
seed (int): _description_
|
|
126
|
+
"""
|
|
127
|
+
self.vdc.reseed(seed)
|
|
128
|
+
self.sphere2.reseed(seed)
|
|
129
|
+
|
|
130
|
+
def pop(self) -> List[float]:
|
|
131
|
+
"""_summary_
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
List[float]: _description_
|
|
135
|
+
"""
|
|
136
|
+
ti = HALF_PI * self.vdc.pop() # map to [t0, tm-1]
|
|
137
|
+
xi = np.interp(ti, F2, X)
|
|
138
|
+
cosxi = math.cos(xi)
|
|
139
|
+
sinxi = math.sin(xi)
|
|
140
|
+
return [sinxi * s for s in self.sphere2.pop()] + [cosxi]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class SphereN(SphereGen):
|
|
144
|
+
"""Sphere-N sequence generator
|
|
145
|
+
|
|
146
|
+
Examples:
|
|
147
|
+
>>> sgen = SphereN([2, 3, 5, 7])
|
|
148
|
+
>>> sgen.reseed(0)
|
|
149
|
+
>>> for _ in range(1):
|
|
150
|
+
... print(sgen.pop())
|
|
151
|
+
...
|
|
152
|
+
[0.4809684718990214, 0.6031153874276115, -0.5785601510223212, 0.2649326520763179, 6.123233995736766e-17]
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
def __init__(self, base: List[int]) -> None:
|
|
156
|
+
"""_summary_
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
base (List[int]): _description_
|
|
160
|
+
"""
|
|
161
|
+
n = len(base) - 1
|
|
162
|
+
assert n >= 2
|
|
163
|
+
self.vdc = VdCorput(base[0])
|
|
164
|
+
self.s_gen = Sphere(base[1:3]) if n == 2 else SphereN(base[1:])
|
|
165
|
+
self.n = n
|
|
166
|
+
tp = get_tp(n)
|
|
167
|
+
self.range = tp[-1] - tp[0]
|
|
168
|
+
|
|
169
|
+
def pop(self) -> List[float]:
|
|
170
|
+
"""_summary_
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
List[float]: _description_
|
|
174
|
+
"""
|
|
175
|
+
vd = self.vdc.pop()
|
|
176
|
+
tp = get_tp(self.n)
|
|
177
|
+
ti = tp[0] + self.range * vd # map to [t0, tm-1]
|
|
178
|
+
xi = np.interp(ti, tp, X)
|
|
179
|
+
sinphi = math.sin(xi)
|
|
180
|
+
return [xi * sinphi for xi in self.s_gen.pop()] + [math.cos(xi)]
|
|
181
|
+
|
|
182
|
+
def reseed(self, seed: int) -> None:
|
|
183
|
+
"""_summary_
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
seed (int): _description_
|
|
187
|
+
"""
|
|
188
|
+
self.vdc.reseed(seed)
|
|
189
|
+
self.s_gen.reseed(seed)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
if __name__ == "__main__":
|
|
193
|
+
import doctest
|
|
194
|
+
|
|
195
|
+
doctest.testmod()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sphere-n
|
|
3
|
+
Version: 0.2
|
|
4
|
+
Summary: A library for low-discrepancy sequences
|
|
5
|
+
Home-page: https://github.com/pyscaffold/pyscaffold/
|
|
6
|
+
Author: Wai-Shing Luk
|
|
7
|
+
Author-email: luk036@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://pyscaffold.org/
|
|
10
|
+
Platform: any
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/x-rst; charset=UTF-8
|
|
15
|
+
License-File: LICENSE.txt
|
|
16
|
+
Requires-Dist: importlib-metadata
|
|
17
|
+
Requires-Dist: numpy
|
|
18
|
+
Provides-Extra: testing
|
|
19
|
+
Requires-Dist: setuptools; extra == "testing"
|
|
20
|
+
Requires-Dist: pytest; extra == "testing"
|
|
21
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
22
|
+
Requires-Dist: numpy; extra == "testing"
|
|
23
|
+
Requires-Dist: scipy; extra == "testing"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
[](https://codecov.io/gh/luk036/sphere-n)
|
|
27
|
+
[](https://sphere-n.readthedocs.io/en/latest/?badge=latest)
|
|
28
|
+
|
|
29
|
+
# ⚽ sphere-n
|
|
30
|
+
|
|
31
|
+
> Generator of Low discrepancy Sequence on S_n
|
|
32
|
+
|
|
33
|
+
This library implements a generator for the generation of low-discrepancy sequences on n-dimensional spheres. Low-discrepancy sequences are utilized for the generation of points that are distributed uniformly across a given space. This technique is of significant value in a number of fields, including computer graphics, numerical integration, and Monte Carlo simulations.
|
|
34
|
+
|
|
35
|
+
The principal objective of this library is to facilitate the generation of points on the surface of spheres of varying dimensions, including three-dimensional and higher-dimensional spheres. The input required is the dimension of the sphere (n) and a set of base numbers to be used for the underlying sequence generation. The output is a series of vectors, with each vector representing a point on the surface of the n-dimensional sphere.
|
|
36
|
+
|
|
37
|
+
The library achieves this through a combination of mathematical calculations and recursive structures. The library utilizes a number of fundamental components, including:
|
|
38
|
+
|
|
39
|
+
1. The VdCorput sequence generator produces a sequence of numbers that are evenly distributed between 0 and 1.
|
|
40
|
+
2. Subsequently, the aforementioned numerical data is mapped onto the surface of a sphere through the use of interpolation functions.
|
|
41
|
+
3. The SphereGen module represents an abstract base class that defines the common interface for all sphere generators.
|
|
42
|
+
4. The recursive structures, namely Sphere3 and NSphere, facilitate the construction of higher-dimensional spheres from their lower-dimensional counterparts.
|
|
43
|
+
|
|
44
|
+
The primary logic flow begins with the construction of a SphereN object, which utilizes either a Sphere3 (for 3D) or a recursive process to generate lower-dimensional spheres for higher dimensions. In the generation of points, the VdCorput sequence is employed to obtain a base number, which is then subjected to a series of transformations involving sine, cosine, and interpolation in order to map it onto the surface of the sphere.
|
|
45
|
+
|
|
46
|
+
A noteworthy aspect of the library is its incorporation of caching (through the @cache decorator) to optimize performance by storing and reusing calculated values. Moreover, the library provides traits and structures that facilitate the adaptable deployment of the sphere generators. The SphereGen abstract base class serves to define a common interface for a variety of sphere generators, whereas the NSphere and SphereN structures are responsible for implementing the actual generation logic.
|
|
47
|
+
|
|
48
|
+
In conclusion, this library provides a sophisticated yet flexible method for generating evenly distributed points on high-dimensional spheres, which can be advantageous in numerous scientific and computational applications.
|
|
49
|
+
|
|
50
|
+
## Dependencies
|
|
51
|
+
|
|
52
|
+
- [luk036/lds-gen](https://github.com/luk036/lds-gen)
|
|
53
|
+
- numpy
|
|
54
|
+
- scipy (for testing only)
|
|
55
|
+
|
|
56
|
+
## 👀 See also
|
|
57
|
+
|
|
58
|
+
- [sphere-n-cpp](https://github.com/luk036/sphere-n-cpp)
|
|
59
|
+
- [sphere-n-rs](https://github.com/luk036/sphere-n-rs)
|
|
60
|
+
- [slides](https://luk036.github.io/n_sphere/slides.html)
|
|
61
|
+
|
|
62
|
+
## 👉 Note
|
|
63
|
+
|
|
64
|
+
This project has been set up using PyScaffold 3.2.1. For details and usage
|
|
65
|
+
information on PyScaffold see <https://pyscaffold.org/>.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
sphere_n/__init__.py,sha256=maG-vIFXReSK10FS8_urv6C-TfJrlIYSGKw9p9h3hmY,579
|
|
2
|
+
sphere_n/cylind_n.py,sha256=5zRpnSGPdzhM9SSsQBGF7Cr6_HSUWtzrubIL9537p1E,3612
|
|
3
|
+
sphere_n/discrep_2.py,sha256=Ts-D8Rov95aOc0etDc0mE_L7_dDqkamyC-Sm3B4vnCA,612
|
|
4
|
+
sphere_n/sphere_n.py,sha256=ouO9I1MpIDAEhA3S7KEVY9HRG0vEnXqNOA0gj_fmWqE,6723
|
|
5
|
+
sphere_n-0.2.dist-info/licenses/LICENSE.txt,sha256=MyvlyWiWdJ3ZpAOA4wziXlNa9Hbx8XnEL1Aztt9F7W8,1080
|
|
6
|
+
sphere_n-0.2.dist-info/METADATA,sha256=cCpMVrh1qR5T_s2M8oowSzrVghJVW4dZHauBV4N9g6g,4248
|
|
7
|
+
sphere_n-0.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
8
|
+
sphere_n-0.2.dist-info/top_level.txt,sha256=iHzEhUMhA0LQaS3boyXp_F3-Nz1VBrfWAufktLNGrdo,9
|
|
9
|
+
sphere_n-0.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Wai-Shing Luk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sphere_n
|