pynumerics 2.3.0__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.
- pynumerics/__init__.py +73 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.LICENSE.txt +27 -0
- pynumerics/_bin/Microsoft.CodeAnalysis.dll +0 -0
- pynumerics/_bin/Numerics.dll +0 -0
- pynumerics/_bin/pynumerics.runtimeconfig.json +15 -0
- pynumerics/_coverage.py +3825 -0
- pynumerics/_util.py +237 -0
- pynumerics/_version.py +40 -0
- pynumerics/bootstrap.py +593 -0
- pynumerics/callbacks.py +791 -0
- pynumerics/copulas.py +910 -0
- pynumerics/data.py +2233 -0
- pynumerics/differentiation.py +348 -0
- pynumerics/distributions.py +4043 -0
- pynumerics/download.py +623 -0
- pynumerics/enums.py +119 -0
- pynumerics/errors.py +245 -0
- pynumerics/functions.py +1142 -0
- pynumerics/goodness_of_fit.py +699 -0
- pynumerics/graphs.py +556 -0
- pynumerics/hypothesis_tests.py +445 -0
- pynumerics/identity.py +144 -0
- pynumerics/integration.py +677 -0
- pynumerics/linalg.py +1408 -0
- pynumerics/machine_learning.py +1335 -0
- pynumerics/marshal.py +733 -0
- pynumerics/mathematics.py +1053 -0
- pynumerics/mcmc.py +1406 -0
- pynumerics/multivariate.py +1539 -0
- pynumerics/ode.py +156 -0
- pynumerics/optimization.py +1736 -0
- pynumerics/probability.py +966 -0
- pynumerics/py.typed +0 -0
- pynumerics/regional.py +522 -0
- pynumerics/roots.py +274 -0
- pynumerics/runtime.py +384 -0
- pynumerics/sampling.py +1758 -0
- pynumerics/special.py +1079 -0
- pynumerics/statistics.py +1958 -0
- pynumerics/timeseries.py +1326 -0
- pynumerics-2.3.0.dist-info/METADATA +142 -0
- pynumerics-2.3.0.dist-info/RECORD +46 -0
- pynumerics-2.3.0.dist-info/WHEEL +5 -0
- pynumerics-2.3.0.dist-info/licenses/LICENSE +10 -0
- pynumerics-2.3.0.dist-info/top_level.txt +1 -0
pynumerics/_util.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""Shared helpers for the typed wrappers: enum mapping, array dispatch and unwrapping."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import enum
|
|
6
|
+
from collections.abc import Callable, Sequence
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from pynumerics.errors import translated
|
|
12
|
+
from pynumerics.marshal import _flat_doubles, to_numpy_doubles
|
|
13
|
+
from pynumerics.runtime import initialize
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def unwrap(obj: Any) -> Any:
|
|
17
|
+
"""Return the concrete .NET object behind a pythonnet interface or base-class wrapper.
|
|
18
|
+
|
|
19
|
+
pythonnet 3 wraps return values at their declared type; ``__implementation__``
|
|
20
|
+
exposes the runtime type so members of the concrete class are reachable.
|
|
21
|
+
"""
|
|
22
|
+
return getattr(obj, "__implementation__", obj)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_ENUM_MEMBERS: dict[tuple[Any, str], Any] = {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def fold_name(name: str) -> str:
|
|
29
|
+
"""Return the folded form of an enum name: underscores removed, lower case.
|
|
30
|
+
|
|
31
|
+
``"normal_z"``, ``"NORMAL_Z"`` and ``"NormalZ"`` all fold to ``"normalz"``. :func:`net_enum` and
|
|
32
|
+
the ``_missing_`` lookup of the pynumerics enums match names by this rule.
|
|
33
|
+
"""
|
|
34
|
+
return name.replace("_", "").lower()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def net_enum(net_type: Any, value: Any) -> Any:
|
|
38
|
+
"""Map a Python enum member or a name to a member of a .NET enum.
|
|
39
|
+
|
|
40
|
+
Names match case-insensitively and ignore underscores, so ``"normal_z"``,
|
|
41
|
+
``"NormalZ"`` and ``Transform.NORMAL_Z`` all select ``Transform.NormalZ``.
|
|
42
|
+
A resolved name is remembered per enum type: resolving it again through
|
|
43
|
+
``System.Enum.GetNames`` costs about fifteen microseconds a call, more than many of
|
|
44
|
+
the members the value is passed to.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
ValueError
|
|
49
|
+
If the name matches no member of ``net_type``.
|
|
50
|
+
"""
|
|
51
|
+
if isinstance(value, enum.Enum):
|
|
52
|
+
value = value.value
|
|
53
|
+
if not isinstance(value, str):
|
|
54
|
+
return value
|
|
55
|
+
key = fold_name(value)
|
|
56
|
+
member = _ENUM_MEMBERS.get((net_type, key))
|
|
57
|
+
if member is not None:
|
|
58
|
+
return member
|
|
59
|
+
import clr # noqa: PLC0415
|
|
60
|
+
import System # noqa: PLC0415 - the runtime is started by the caller
|
|
61
|
+
|
|
62
|
+
clr_type = clr.GetClrType(net_type)
|
|
63
|
+
for name in System.Enum.GetNames(clr_type):
|
|
64
|
+
if str(name).lower() == key:
|
|
65
|
+
member = _ENUM_MEMBERS[(net_type, key)] = getattr(net_type, str(name))
|
|
66
|
+
return member
|
|
67
|
+
names = ", ".join(str(name) for name in System.Enum.GetNames(clr_type))
|
|
68
|
+
raise ValueError(f"'{value}' is not a member of {clr_type.Name} ({names}).")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@translated
|
|
72
|
+
def evaluate(values: Any, scalar: Callable[[float], float], vector: Callable[[Any], Any]) -> Any:
|
|
73
|
+
"""Evaluate a Numerics member on a scalar or on an array through its array overload.
|
|
74
|
+
|
|
75
|
+
A scalar input calls ``scalar`` and returns a Python float. Any other input is
|
|
76
|
+
flattened to float64, passed to ``vector`` as one ``System.Double[]`` (the
|
|
77
|
+
``IList<double>`` overload), and the result is reshaped to the input's shape.
|
|
78
|
+
Callers pass ``vector`` already bound with :func:`bind_list` where the member is a
|
|
79
|
+
method group, so the overload is not resolved again on every call.
|
|
80
|
+
"""
|
|
81
|
+
array = np.asarray(values, dtype=np.float64)
|
|
82
|
+
if array.ndim == 0:
|
|
83
|
+
return float(scalar(float(array)))
|
|
84
|
+
result = to_numpy_doubles(vector(_flat_doubles(array)))
|
|
85
|
+
return result if array.ndim == 1 else result.reshape(array.shape)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@translated
|
|
89
|
+
def loop(values: Any, scalar: Callable[[float], float]) -> Any:
|
|
90
|
+
"""Evaluate a scalar-only Numerics member element by element.
|
|
91
|
+
|
|
92
|
+
Used only where Numerics has no array overload; the arithmetic stays in Numerics.
|
|
93
|
+
"""
|
|
94
|
+
array = np.asarray(values, dtype=np.float64)
|
|
95
|
+
if array.ndim == 0:
|
|
96
|
+
return float(scalar(float(array)))
|
|
97
|
+
out = np.empty(array.size, dtype=np.float64)
|
|
98
|
+
for index, value in enumerate(array.ravel()):
|
|
99
|
+
out[index] = scalar(float(value))
|
|
100
|
+
return out.reshape(array.shape)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def bind(member: Any, arity: int = 1) -> Any:
|
|
104
|
+
"""Return the overload of a .NET method group that takes ``arity`` doubles.
|
|
105
|
+
|
|
106
|
+
pythonnet resolves an overloaded method group on every call, which costs several times
|
|
107
|
+
the call itself for the cheap scalar members (``InverseCDF(double)`` beside
|
|
108
|
+
``InverseCDF(IList<double>)``); binding the overload once makes repeated scalar calls
|
|
109
|
+
about six times faster. The arithmetic is unchanged: the bound overload is the member
|
|
110
|
+
the group would have resolved to. A group without that overload is returned as it is.
|
|
111
|
+
"""
|
|
112
|
+
import System # noqa: PLC0415 - the runtime is started by the caller
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
return member.Overloads[(System.Double,) * arity] if arity > 1 else member.Overloads[System.Double]
|
|
116
|
+
except (KeyError, TypeError, AttributeError):
|
|
117
|
+
return member
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def bind_list(member: Any) -> Any:
|
|
121
|
+
"""Return the ``IList<double>`` overload of a .NET method group.
|
|
122
|
+
|
|
123
|
+
pythonnet resolves an overloaded method group on every call. For the array members
|
|
124
|
+
(``InverseCDF(IList<double>)`` beside ``InverseCDF(double)``) the resolution costs about
|
|
125
|
+
30 microseconds a call, several times the evaluation of a short array; binding the
|
|
126
|
+
overload once removes it. The arithmetic is unchanged: the bound overload is the member
|
|
127
|
+
the group resolves to for a ``System.Double[]`` argument. A group without that overload
|
|
128
|
+
is returned as it is.
|
|
129
|
+
"""
|
|
130
|
+
import System # noqa: PLC0415 - the runtime is started by the caller
|
|
131
|
+
from System.Collections.Generic import IList # noqa: PLC0415
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
return member.Overloads[IList[System.Double]]
|
|
135
|
+
except (KeyError, TypeError, AttributeError):
|
|
136
|
+
return member
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def list_overload(member: Any) -> Any:
|
|
140
|
+
"""Return the ``IList<double>`` overload of a .NET method group, or None when it has none.
|
|
141
|
+
|
|
142
|
+
Like :func:`bind_list`, but a group without the array overload gives None, so a wrapper
|
|
143
|
+
can evaluate an array element by element with the scalar member instead.
|
|
144
|
+
"""
|
|
145
|
+
bound = bind_list(member)
|
|
146
|
+
return None if bound is member else bound
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
_OVERLOADS: dict[str, Any] = {}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def cached_overload(key: str, factory: Callable[[], Any]) -> Any:
|
|
153
|
+
"""Return a bound .NET overload, resolving it with ``factory`` on first use only.
|
|
154
|
+
|
|
155
|
+
pythonnet resolves an overloaded method group on every call; for a group with many
|
|
156
|
+
overloads (``Statistics.Percentile`` has eight) the resolution costs 40 to 70
|
|
157
|
+
microseconds, several times the call itself. Binding the exact overload once per
|
|
158
|
+
process, under a key naming the member and its signature, removes that cost without
|
|
159
|
+
changing which member runs.
|
|
160
|
+
"""
|
|
161
|
+
member = _OVERLOADS.get(key)
|
|
162
|
+
if member is None:
|
|
163
|
+
member = _OVERLOADS[key] = factory()
|
|
164
|
+
return member
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
_NAMESPACES: dict[str, Any] = {}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def namespace(name: str) -> Any:
|
|
171
|
+
"""Start the runtime and import a .NET namespace by dotted name, once per process.
|
|
172
|
+
|
|
173
|
+
Wrappers call this on every evaluation; returning the imported module from a dictionary
|
|
174
|
+
skips the import machinery, which costs a few microseconds a call.
|
|
175
|
+
"""
|
|
176
|
+
module = _NAMESPACES.get(name)
|
|
177
|
+
if module is None:
|
|
178
|
+
initialize()
|
|
179
|
+
import importlib # noqa: PLC0415
|
|
180
|
+
|
|
181
|
+
module = _NAMESPACES[name] = importlib.import_module(name)
|
|
182
|
+
return module
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _nd() -> Any:
|
|
186
|
+
"""Return the ``Numerics.Distributions`` namespace after starting the runtime."""
|
|
187
|
+
return namespace("Numerics.Distributions")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _data() -> Any:
|
|
191
|
+
"""Return the ``Numerics.Data`` namespace after starting the runtime."""
|
|
192
|
+
return namespace("Numerics.Data")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _opt() -> Any:
|
|
196
|
+
"""Return the ``Numerics.Mathematics.Optimization`` namespace after starting the runtime."""
|
|
197
|
+
return namespace("Numerics.Mathematics.Optimization")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def overload(member: Any, *types: str) -> Any:
|
|
201
|
+
"""Return the overload of a .NET method group taking the named types.
|
|
202
|
+
|
|
203
|
+
Each name is a ``System`` type (``"Double"``, ``"Int32"``, ``"Boolean"``), an array of one
|
|
204
|
+
(``"Double[]"``) or a list of one (``"IList[Double]"``).
|
|
205
|
+
"""
|
|
206
|
+
import System # noqa: PLC0415 - the caller started the runtime
|
|
207
|
+
from System.Collections.Generic import IList # noqa: PLC0415
|
|
208
|
+
|
|
209
|
+
resolved = []
|
|
210
|
+
for name in types:
|
|
211
|
+
if name.startswith("IList["):
|
|
212
|
+
resolved.append(IList[getattr(System, name[6:-1])])
|
|
213
|
+
elif name.endswith("[]"):
|
|
214
|
+
resolved.append(System.Array[getattr(System, name[:-2])])
|
|
215
|
+
else:
|
|
216
|
+
resolved.append(getattr(System, name))
|
|
217
|
+
return member.Overloads[tuple(resolved)] if len(resolved) > 1 else member.Overloads[resolved[0]]
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@translated
|
|
221
|
+
def broadcast_loop(member: Callable[..., Any], *args: Any, kinds: Sequence[type] | None = None) -> Any:
|
|
222
|
+
"""Evaluate a scalar-only Numerics member of several arguments over their broadcast shape.
|
|
223
|
+
|
|
224
|
+
Each argument is converted with its entry of ``kinds`` (``float`` by default, ``int`` for
|
|
225
|
+
integer parameters such as a Bessel order). Scalars give a Python float; arrays give a float64
|
|
226
|
+
array of the broadcast shape. Used only where Numerics has no array overload; every value is
|
|
227
|
+
the scalar member's.
|
|
228
|
+
"""
|
|
229
|
+
kinds = kinds or (float,) * len(args)
|
|
230
|
+
arrays = np.broadcast_arrays(*(np.asarray(a, dtype=np.int64 if k is int else np.float64)
|
|
231
|
+
for a, k in zip(args, kinds, strict=True)))
|
|
232
|
+
if arrays[0].ndim == 0:
|
|
233
|
+
return float(member(*(k(a) for a, k in zip(arrays, kinds, strict=True))))
|
|
234
|
+
out = np.empty(arrays[0].size, dtype=np.float64)
|
|
235
|
+
for index, values in enumerate(zip(*(a.ravel().tolist() for a in arrays), strict=True)):
|
|
236
|
+
out[index] = member(*values)
|
|
237
|
+
return out.reshape(arrays[0].shape)
|
pynumerics/_version.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Version of the pynumerics distribution and the identity of the Numerics assembly it ships.
|
|
2
|
+
|
|
3
|
+
The wheel ships ``lib/net10.0/Numerics.dll`` of the RMC.Numerics NuGet package of the same version.
|
|
4
|
+
``scripts/build_wheel.py`` reads the package version, the assembly version and the SHA-256 from the
|
|
5
|
+
package and writes them into the wheel's copy of this file; it refuses a package whose version or
|
|
6
|
+
assembly version differs from the values below. In a source checkout ``NUMERICS_SHA256`` is empty,
|
|
7
|
+
because the digest of a published package is known only when it is built. ``NUMERICS_SOURCE_COMMIT``
|
|
8
|
+
and ``NUMERICS_BUILD_COMMAND`` are written only for a wheel built from a local ``Numerics.dll``
|
|
9
|
+
(``build_wheel.py --dll``, as in the pull request check); they are empty in a published wheel.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "2.3.0"
|
|
13
|
+
"""The distribution version; it equals the RMC.Numerics version of the bundled assembly (PEP 440 form)."""
|
|
14
|
+
|
|
15
|
+
NUMERICS_VERSION = "2.3.0"
|
|
16
|
+
"""The RMC.Numerics version of the bundled ``Numerics.dll`` (a NuGet package version, or the local build's)."""
|
|
17
|
+
|
|
18
|
+
NUMERICS_ASSEMBLY_VERSION = "2.3.0.0"
|
|
19
|
+
"""The assembly version recorded in the bundled ``Numerics.dll``."""
|
|
20
|
+
|
|
21
|
+
NUMERICS_SHA256 = "68b437e7541a3a2cbaa629ecbc3b074941ef37da58919c97cdc6654b1e63b992"
|
|
22
|
+
"""SHA-256 of the bundled ``Numerics.dll``, written when the wheel is built (empty in a source checkout)."""
|
|
23
|
+
|
|
24
|
+
NUMERICS_SOURCE_COMMIT = ""
|
|
25
|
+
"""The Numerics commit a locally built ``Numerics.dll`` was built from; empty for a NuGet package assembly."""
|
|
26
|
+
|
|
27
|
+
NUMERICS_BUILD_COMMAND = ""
|
|
28
|
+
"""How a locally built ``Numerics.dll`` was built (receipts record it); empty for a NuGet package assembly."""
|
|
29
|
+
|
|
30
|
+
ROSLYN_VERSION = "4.14.0"
|
|
31
|
+
"""The Microsoft.CodeAnalysis.Common and .CSharp package version bundled for ``callbacks.compile_csharp``."""
|
|
32
|
+
|
|
33
|
+
ROSLYN_TARGET_FRAMEWORK = "net9.0"
|
|
34
|
+
"""The ``lib`` folder of the Roslyn packages the bundled assemblies come from (they run on the .NET 10 runtime)."""
|
|
35
|
+
|
|
36
|
+
ROSLYN_CODEANALYSIS_SHA256 = "395736b2d0e02be77bedc3847b269da7a93bf8e49cd3431a4a8e68d2c52d5846"
|
|
37
|
+
"""SHA-256 of the bundled ``Microsoft.CodeAnalysis.dll`` (Microsoft.CodeAnalysis.Common ``ROSLYN_VERSION``)."""
|
|
38
|
+
|
|
39
|
+
ROSLYN_CSHARP_SHA256 = "53302acca07700e9bb10dcf21034435d6e0454c8eebf2481164ec13e520004c9"
|
|
40
|
+
"""SHA-256 of the bundled ``Microsoft.CodeAnalysis.CSharp.dll`` (Microsoft.CodeAnalysis.CSharp ``ROSLYN_VERSION``)."""
|