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.
Files changed (46) hide show
  1. pynumerics/__init__.py +73 -0
  2. pynumerics/_bin/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  3. pynumerics/_bin/Microsoft.CodeAnalysis.LICENSE.txt +27 -0
  4. pynumerics/_bin/Microsoft.CodeAnalysis.dll +0 -0
  5. pynumerics/_bin/Numerics.dll +0 -0
  6. pynumerics/_bin/pynumerics.runtimeconfig.json +15 -0
  7. pynumerics/_coverage.py +3825 -0
  8. pynumerics/_util.py +237 -0
  9. pynumerics/_version.py +40 -0
  10. pynumerics/bootstrap.py +593 -0
  11. pynumerics/callbacks.py +791 -0
  12. pynumerics/copulas.py +910 -0
  13. pynumerics/data.py +2233 -0
  14. pynumerics/differentiation.py +348 -0
  15. pynumerics/distributions.py +4043 -0
  16. pynumerics/download.py +623 -0
  17. pynumerics/enums.py +119 -0
  18. pynumerics/errors.py +245 -0
  19. pynumerics/functions.py +1142 -0
  20. pynumerics/goodness_of_fit.py +699 -0
  21. pynumerics/graphs.py +556 -0
  22. pynumerics/hypothesis_tests.py +445 -0
  23. pynumerics/identity.py +144 -0
  24. pynumerics/integration.py +677 -0
  25. pynumerics/linalg.py +1408 -0
  26. pynumerics/machine_learning.py +1335 -0
  27. pynumerics/marshal.py +733 -0
  28. pynumerics/mathematics.py +1053 -0
  29. pynumerics/mcmc.py +1406 -0
  30. pynumerics/multivariate.py +1539 -0
  31. pynumerics/ode.py +156 -0
  32. pynumerics/optimization.py +1736 -0
  33. pynumerics/probability.py +966 -0
  34. pynumerics/py.typed +0 -0
  35. pynumerics/regional.py +522 -0
  36. pynumerics/roots.py +274 -0
  37. pynumerics/runtime.py +384 -0
  38. pynumerics/sampling.py +1758 -0
  39. pynumerics/special.py +1079 -0
  40. pynumerics/statistics.py +1958 -0
  41. pynumerics/timeseries.py +1326 -0
  42. pynumerics-2.3.0.dist-info/METADATA +142 -0
  43. pynumerics-2.3.0.dist-info/RECORD +46 -0
  44. pynumerics-2.3.0.dist-info/WHEEL +5 -0
  45. pynumerics-2.3.0.dist-info/licenses/LICENSE +10 -0
  46. 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``)."""