mumpy-toolkit 0.2.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.
- mumpy/__init__.py +128 -0
- mumpy/_core.py +218 -0
- mumpy/_math.py +283 -0
- mumpy/_parallel.py +142 -0
- mumpy/db.py +289 -0
- mumpy/fft.py +132 -0
- mumpy/frame.py +428 -0
- mumpy/io.py +196 -0
- mumpy/linalg.py +62 -0
- mumpy/metrics.py +187 -0
- mumpy/ml.py +443 -0
- mumpy/nn.py +278 -0
- mumpy/preprocessing.py +259 -0
- mumpy/random.py +99 -0
- mumpy/stats.py +122 -0
- mumpy/utils.py +105 -0
- mumpy/viz.py +81 -0
- mumpy_toolkit-0.2.0.dist-info/METADATA +200 -0
- mumpy_toolkit-0.2.0.dist-info/RECORD +22 -0
- mumpy_toolkit-0.2.0.dist-info/WHEEL +5 -0
- mumpy_toolkit-0.2.0.dist-info/licenses/LICENSE +21 -0
- mumpy_toolkit-0.2.0.dist-info/top_level.txt +1 -0
mumpy/__init__.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""mumpy — drop-in numpy-compatible library + data-science / ML / DL toolkit.
|
|
2
|
+
|
|
3
|
+
Same API as numpy for the common 95%:
|
|
4
|
+
import mumpy as cp
|
|
5
|
+
a = cp.arange(10_000_000)
|
|
6
|
+
b = cp.sqrt(a) # multithreaded for large arrays
|
|
7
|
+
c = cp.fma(a, b, 1.0) # fused a*b+c, single pass
|
|
8
|
+
|
|
9
|
+
Beyond numpy — one import for the whole workflow:
|
|
10
|
+
cp.io / cp.db / cp.frame # IO, databases (sqlite/postgres/duckdb), DataFrame
|
|
11
|
+
cp.stats / cp.preprocessing # EDA, scalers, encoders, imputers
|
|
12
|
+
cp.metrics / cp.ml # metrics + classic ML (sklearn-like API)
|
|
13
|
+
cp.nn / cp.viz / cp.utils # tiny deep learning + one-line plots
|
|
14
|
+
|
|
15
|
+
Speed sources (no C compiler needed):
|
|
16
|
+
1. chunked ThreadPool for compute-bound element-wise ufuncs,
|
|
17
|
+
2. fused multiply-add fma/fms/fnma/lerp with half peak memory,
|
|
18
|
+
3. scipy.fft with workers=-1 when available,
|
|
19
|
+
4. einsum(optimize=True), contiguous-layout matmul.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import numpy as _np
|
|
24
|
+
|
|
25
|
+
from ._core import (
|
|
26
|
+
ndarray, array, asarray, asanyarray, ascontiguousarray, asnumpy, copy,
|
|
27
|
+
zeros, ones, empty, full, zeros_like, ones_like, empty_like, full_like,
|
|
28
|
+
arange, linspace, logspace, eye, identity, diag,
|
|
29
|
+
reshape, ravel, transpose, concatenate, stack, vstack, hstack,
|
|
30
|
+
split, tile, repeat,
|
|
31
|
+
)
|
|
32
|
+
from ._math import (
|
|
33
|
+
add, subtract, multiply, divide, power, sqrt, exp, log,
|
|
34
|
+
sin, cos, tan, abs, absolute, clip, where, fma, fms, fnma, lerp,
|
|
35
|
+
hypot, maximum, minimum, expm1, log1p, log2, log10, square, cbrt,
|
|
36
|
+
reciprocal, arcsin, arccos, arctan, arctan2, sinh, cosh, tanh,
|
|
37
|
+
floor, ceil, rint, sign, sinc,
|
|
38
|
+
sum, mean, min, max, amin, amax, prod, std, var,
|
|
39
|
+
nansum, nanmean, nanmin, nanmax, nanstd,
|
|
40
|
+
any, all, cumsum, cumprod, dot, matmul, einsum, tensordot,
|
|
41
|
+
vdot, inner, outer, kron, trace, sort, argsort,
|
|
42
|
+
)
|
|
43
|
+
from . import linalg, fft, random, io, db, frame, stats, preprocessing, metrics, ml, nn, utils
|
|
44
|
+
try:
|
|
45
|
+
from . import viz # optional matplotlib
|
|
46
|
+
except Exception:
|
|
47
|
+
viz = None # type: ignore
|
|
48
|
+
from ._parallel import MAX_WORKERS, PARALLEL_THRESHOLD, get_workers
|
|
49
|
+
|
|
50
|
+
__version__ = "0.2.0"
|
|
51
|
+
|
|
52
|
+
# ---- numpy compat: re-export everything else verbatim ----
|
|
53
|
+
_COMPAT = [
|
|
54
|
+
"pi", "e", "inf", "nan", "newaxis",
|
|
55
|
+
"float16", "float32", "float64", "int8", "int16", "int32", "int64",
|
|
56
|
+
"uint8", "uint16", "uint32", "uint64", "bool_", "complex64", "complex128",
|
|
57
|
+
"ndim", "shape", "size", "dtype", "result_type", "broadcast_arrays",
|
|
58
|
+
"broadcast_to", "expand_dims", "squeeze", "flatten", "moveaxis",
|
|
59
|
+
"swapaxes", "flip", "roll", "rot90", "pad", "meshgrid",
|
|
60
|
+
"unique", "intersect1d", "union1d", "setdiff1d", "isin", "in1d",
|
|
61
|
+
"take", "put", "compress", "extract", "argmax", "argmin", "nonzero",
|
|
62
|
+
"count_nonzero", "flatnonzero", "argwhere", "searchsorted", "digitize",
|
|
63
|
+
"histogram", "bincount", "corrcoef", "cov", "polyfit", "polyval",
|
|
64
|
+
"convolve", "gradient", "diff", "ediff1d", "interp", "percentile",
|
|
65
|
+
"quantile", "median", "average", "ptp", "allclose", "isclose",
|
|
66
|
+
"array_equal", "array_equiv", "isnan", "isinf", "isfinite",
|
|
67
|
+
"nan_to_num", "nansum", "nanmean", "nanmin", "nanmax",
|
|
68
|
+
"logical_and", "logical_or", "logical_not", "logical_xor",
|
|
69
|
+
"greater", "greater_equal", "less", "less_equal", "equal", "not_equal",
|
|
70
|
+
"fmax", "fmin",
|
|
71
|
+
"arctan2",
|
|
72
|
+
"round", "fix", "trunc",
|
|
73
|
+
"real", "imag", "conj", "conjugate", "angle",
|
|
74
|
+
"degrees", "radians", "mod", "remainder", "divmod", "fmod",
|
|
75
|
+
"bitwise_and", "bitwise_or", "bitwise_xor", "invert", "left_shift", "right_shift",
|
|
76
|
+
"vecdot",
|
|
77
|
+
]
|
|
78
|
+
for _name in _COMPAT:
|
|
79
|
+
if hasattr(_np, _name) and _name not in globals():
|
|
80
|
+
globals()[_name] = getattr(_np, _name)
|
|
81
|
+
|
|
82
|
+
__all__ = [
|
|
83
|
+
"ndarray", "array", "asarray", "asanyarray", "ascontiguousarray", "asnumpy", "copy",
|
|
84
|
+
"zeros", "ones", "empty", "full", "zeros_like", "ones_like", "empty_like", "full_like",
|
|
85
|
+
"arange", "linspace", "logspace", "eye", "identity", "diag",
|
|
86
|
+
"reshape", "ravel", "transpose", "concatenate", "stack", "vstack", "hstack",
|
|
87
|
+
"split", "tile", "repeat",
|
|
88
|
+
"add", "subtract", "multiply", "divide", "power", "sqrt", "exp", "log",
|
|
89
|
+
"sin", "cos", "tan", "abs", "absolute", "clip", "where", "fma", "fms", "fnma", "lerp",
|
|
90
|
+
"hypot", "maximum", "minimum", "expm1", "log1p", "log2", "log10", "square", "cbrt",
|
|
91
|
+
"reciprocal", "arcsin", "arccos", "arctan", "arctan2", "sinh", "cosh", "tanh",
|
|
92
|
+
"floor", "ceil", "rint", "sign", "sinc",
|
|
93
|
+
"sum", "mean", "min", "max", "amin", "amax", "prod", "std", "var",
|
|
94
|
+
"nansum", "nanmean", "nanmin", "nanmax", "nanstd",
|
|
95
|
+
"any", "all", "cumsum", "cumprod", "dot", "matmul", "einsum", "tensordot",
|
|
96
|
+
"vdot", "inner", "outer", "kron", "trace", "sort", "argsort",
|
|
97
|
+
"linalg", "fft", "random", "io", "db", "frame", "stats", "preprocessing",
|
|
98
|
+
"metrics", "ml", "nn", "utils", "viz",
|
|
99
|
+
"MAX_WORKERS", "PARALLEL_THRESHOLD",
|
|
100
|
+
"__version__",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def info():
|
|
105
|
+
import os
|
|
106
|
+
return {
|
|
107
|
+
"version": __version__,
|
|
108
|
+
"numpy": _np.__version__,
|
|
109
|
+
"workers": MAX_WORKERS,
|
|
110
|
+
"cpus": os.cpu_count(),
|
|
111
|
+
"parallel_threshold": PARALLEL_THRESHOLD,
|
|
112
|
+
"scipy_fft": fft.has_scipy(),
|
|
113
|
+
"modules": ["io", "db", "frame", "stats", "preprocessing",
|
|
114
|
+
"metrics", "ml", "nn", "utils", "viz"],
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def set_workers(n: int):
|
|
119
|
+
"""Tune parallelism. set_workers(1) == pure-numpy behavior."""
|
|
120
|
+
from . import _parallel
|
|
121
|
+
_parallel.MAX_WORKERS = max(1, int(n))
|
|
122
|
+
globals()["MAX_WORKERS"] = _parallel.MAX_WORKERS
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def set_threshold(n: int):
|
|
126
|
+
from . import _parallel
|
|
127
|
+
_parallel.PARALLEL_THRESHOLD = int(n)
|
|
128
|
+
globals()["PARALLEL_THRESHOLD"] = int(n)
|
mumpy/_core.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""mumpy core: numpy-compatible ndarray + creation routines."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import builtins
|
|
5
|
+
import numpy as np
|
|
6
|
+
builtins_max = builtins.max
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ndarray", "array", "asarray", "asanyarray", "ascontiguousarray",
|
|
10
|
+
"zeros", "ones", "empty", "full", "zeros_like", "ones_like", "empty_like",
|
|
11
|
+
"full_like", "arange", "linspace", "logspace", "eye", "identity", "diag",
|
|
12
|
+
"reshape", "ravel", "transpose", "concatenate", "stack", "vstack", "hstack",
|
|
13
|
+
"split", "tile", "repeat", "copy", "asnumpy",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ndarray(np.ndarray):
|
|
18
|
+
"""mumpy array: subclasses np.ndarray so every numpy API accepts it.
|
|
19
|
+
|
|
20
|
+
Adds convenience fused/fast methods that avoid temporaries.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __new__(cls, *args, **kwargs):
|
|
24
|
+
obj = np.asarray(*args, **kwargs).view(cls)
|
|
25
|
+
return obj
|
|
26
|
+
|
|
27
|
+
def __array_finalize__(self, obj):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
|
|
31
|
+
# Route large element-wise ops through the parallel engine so that
|
|
32
|
+
# BOTH `cp.sqrt(a)` and plain `a / N`, `a * b + c` syntax are faster.
|
|
33
|
+
import numpy as _np
|
|
34
|
+
try:
|
|
35
|
+
from ._parallel import parallel_ewise, PARALLEL_THRESHOLD
|
|
36
|
+
_PARALLEL_UFUNCS = frozenset({
|
|
37
|
+
"add", "subtract", "multiply", "divide", "true_divide",
|
|
38
|
+
"power", "sqrt", "exp", "log", "sin", "cos", "tan",
|
|
39
|
+
"absolute", "maximum", "minimum",
|
|
40
|
+
})
|
|
41
|
+
if method == "__call__" and ufunc.__name__ in _PARALLEL_UFUNCS:
|
|
42
|
+
if kwargs.get("where", None) is None and kwargs.get("casting", None) is None:
|
|
43
|
+
arrs = [x for x in inputs if isinstance(x, _np.ndarray)]
|
|
44
|
+
size = builtins_max([x.size for x in arrs], default=0) if arrs else 0
|
|
45
|
+
if size >= PARALLEL_THRESHOLD:
|
|
46
|
+
out = kwargs.pop("out", None)
|
|
47
|
+
o = out[0] if isinstance(out, tuple) and len(out) == 1 else out
|
|
48
|
+
|
|
49
|
+
def _f(*views, out=None):
|
|
50
|
+
ufunc(*views, out=out)
|
|
51
|
+
r = parallel_ewise(_f, *inputs, out=o)
|
|
52
|
+
if o is not None:
|
|
53
|
+
return o
|
|
54
|
+
return r.view(ndarray) if isinstance(r, _np.ndarray) else r
|
|
55
|
+
except Exception:
|
|
56
|
+
pass
|
|
57
|
+
# default path: unwrap to plain ndarray and call the ufunc
|
|
58
|
+
# (calling super().__array_ufunc__ returns NotImplemented on numpy>=2)
|
|
59
|
+
def _plain(x):
|
|
60
|
+
if isinstance(x, ndarray):
|
|
61
|
+
return x.view(_np.ndarray)
|
|
62
|
+
if isinstance(x, _np.ndarray):
|
|
63
|
+
return x.view(_np.ndarray)
|
|
64
|
+
return x
|
|
65
|
+
inputs = tuple(_plain(x) for x in inputs)
|
|
66
|
+
if "out" in kwargs and kwargs["out"] is not None:
|
|
67
|
+
out = kwargs["out"]
|
|
68
|
+
kwargs["out"] = tuple(_plain(o) if o is not None else None for o in out)
|
|
69
|
+
result = getattr(ufunc, method)(*inputs, **kwargs)
|
|
70
|
+
return _wrap(result) if isinstance(result, _np.ndarray) else result
|
|
71
|
+
|
|
72
|
+
# -- fast methods (avoid extra temporaries) --
|
|
73
|
+
def fma(self, b, c):
|
|
74
|
+
"""self * b + c in one pass (no intermediate)."""
|
|
75
|
+
from ._math import fma
|
|
76
|
+
return fma(self, b, c)
|
|
77
|
+
|
|
78
|
+
def squared(self):
|
|
79
|
+
return np.multiply(self, self)
|
|
80
|
+
|
|
81
|
+
def asum(self):
|
|
82
|
+
return np.abs(np.asanyarray(self)).sum()
|
|
83
|
+
|
|
84
|
+
def to_numpy(self):
|
|
85
|
+
return np.asanyarray(self).view(np.ndarray)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _wrap(x):
|
|
89
|
+
if isinstance(x, np.ndarray) and not isinstance(x, ndarray):
|
|
90
|
+
return x.view(ndarray)
|
|
91
|
+
return x
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def array(obj, dtype=None, copy=True, order="K", subok=False, ndmin=0, **kw):
|
|
95
|
+
return _wrap(np.array(obj, dtype=dtype, copy=copy, order=order,
|
|
96
|
+
subok=subok, ndmin=ndmin, **kw))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def asarray(a, dtype=None, order=None):
|
|
100
|
+
return _wrap(np.asarray(a, dtype=dtype, order=order))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def asanyarray(a, dtype=None, order=None):
|
|
104
|
+
return _wrap(np.asanyarray(a, dtype=dtype, order=order))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def ascontiguousarray(a, dtype=None):
|
|
108
|
+
return _wrap(np.ascontiguousarray(a, dtype=dtype))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def asnumpy(a):
|
|
112
|
+
"""Unwrap to plain np.ndarray (zero-copy view)."""
|
|
113
|
+
return np.asanyarray(a).view(np.ndarray)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def copy(a, order="K"):
|
|
117
|
+
return _wrap(np.array(a, copy=True, order=order, subok=True))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def zeros(shape, dtype=float, order="C"):
|
|
121
|
+
return _wrap(np.zeros(shape, dtype=dtype, order=order))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def ones(shape, dtype=float, order="C"):
|
|
125
|
+
return _wrap(np.ones(shape, dtype=dtype, order=order))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def empty(shape, dtype=float, order="C"):
|
|
129
|
+
return _wrap(np.empty(shape, dtype=dtype, order=order))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def full(shape, fill_value, dtype=None, order="C"):
|
|
133
|
+
return _wrap(np.full(shape, fill_value, dtype=dtype, order=order))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def zeros_like(a, dtype=None, order="K", subok=False, shape=None):
|
|
137
|
+
return _wrap(np.zeros_like(a, dtype=dtype, order=order, subok=True, shape=shape))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def ones_like(a, dtype=None, order="K", subok=False, shape=None):
|
|
141
|
+
return _wrap(np.ones_like(a, dtype=dtype, order=order, subok=True, shape=shape))
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def empty_like(a, dtype=None, order="K", subok=False, shape=None):
|
|
145
|
+
return _wrap(np.empty_like(a, dtype=dtype, order=order, subok=True, shape=shape))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def full_like(a, fill_value, dtype=None, order="K", subok=False, shape=None):
|
|
149
|
+
return _wrap(np.full_like(a, fill_value, dtype=dtype, order=order, subok=True, shape=shape))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def arange(*args, **kwargs):
|
|
153
|
+
return _wrap(np.arange(*args, **kwargs))
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):
|
|
157
|
+
r = np.linspace(start, stop, num=num, endpoint=endpoint,
|
|
158
|
+
retstep=retstep, dtype=dtype, axis=axis)
|
|
159
|
+
if retstep:
|
|
160
|
+
return _wrap(r[0]), r[1]
|
|
161
|
+
return _wrap(r)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):
|
|
165
|
+
return _wrap(np.logspace(start, stop, num=num, endpoint=endpoint,
|
|
166
|
+
base=base, dtype=dtype, axis=axis))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def eye(N, M=None, k=0, dtype=float, order="C"):
|
|
170
|
+
return _wrap(np.eye(N, M=M, k=k, dtype=dtype, order=order))
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def identity(n, dtype=float):
|
|
174
|
+
return _wrap(np.identity(n, dtype=dtype))
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def diag(v, k=0):
|
|
178
|
+
return _wrap(np.diag(v, k=k))
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def reshape(a, shape, order="C"):
|
|
182
|
+
return _wrap(np.reshape(a, shape, order=order))
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def ravel(a, order="C"):
|
|
186
|
+
return _wrap(np.ravel(a, order=order))
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def transpose(a, axes=None):
|
|
190
|
+
return _wrap(np.transpose(a, axes=axes))
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def concatenate(arrays, axis=0, out=None, dtype=None, casting="same_kind"):
|
|
194
|
+
return _wrap(np.concatenate(arrays, axis=axis, out=out, dtype=dtype, casting=casting))
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def stack(arrays, axis=0, out=None, dtype=None, casting="same_kind"):
|
|
198
|
+
return _wrap(np.stack(arrays, axis=axis, out=out, dtype=dtype, casting=casting))
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def vstack(tup, dtype=None, casting="same_kind"):
|
|
202
|
+
return _wrap(np.vstack(tup, dtype=dtype, casting=casting))
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def hstack(tup, dtype=None, casting="same_kind"):
|
|
206
|
+
return _wrap(np.hstack(tup, dtype=dtype, casting=casting))
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def split(ary, indices_or_sections, axis=0):
|
|
210
|
+
return [_wrap(x) for x in np.split(ary, indices_or_sections, axis=axis)]
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def tile(A, reps):
|
|
214
|
+
return _wrap(np.tile(A, reps))
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def repeat(a, repeats, axis=None):
|
|
218
|
+
return _wrap(np.repeat(a, repeats, axis=axis))
|
mumpy/_math.py
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""mumpy math: numpy-compatible functions with parallel fast paths + fused ops."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import builtins
|
|
5
|
+
import numpy as np
|
|
6
|
+
from ._parallel import parallel_ewise
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"add", "subtract", "multiply", "divide", "power", "sqrt", "exp", "log",
|
|
10
|
+
"sin", "cos", "tan", "abs", "absolute", "clip", "where", "fma", "fms",
|
|
11
|
+
"fnma", "lerp", "hypot", "maximum", "minimum",
|
|
12
|
+
"expm1", "log1p", "log2", "log10", "square", "cbrt", "reciprocal",
|
|
13
|
+
"arcsin", "arccos", "arctan", "arctan2", "sinh", "cosh", "tanh",
|
|
14
|
+
"floor", "ceil", "rint", "sign", "sinc",
|
|
15
|
+
"sum", "mean", "min", "max", "amin", "amax", "prod", "std", "var",
|
|
16
|
+
"any", "all", "cumsum", "cumprod", "nansum", "nanmean", "nanmin", "nanmax",
|
|
17
|
+
"nanstd", "dot", "matmul", "einsum", "tensordot",
|
|
18
|
+
"vdot", "inner", "outer", "kron", "trace", "sort", "argsort",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _ew(numpy_func):
|
|
23
|
+
def wrapper(*args, out=None, **kw):
|
|
24
|
+
outs = [np.asanyarray(a).view(np.ndarray) if isinstance(a, np.ndarray) else a
|
|
25
|
+
for a in args]
|
|
26
|
+
try:
|
|
27
|
+
size = builtins.max((np.asanyarray(o).size for o in outs), default=0)
|
|
28
|
+
except Exception:
|
|
29
|
+
size = 0
|
|
30
|
+
from ._parallel import PARALLEL_THRESHOLD
|
|
31
|
+
from ._core import _wrap
|
|
32
|
+
if size >= PARALLEL_THRESHOLD and not kw:
|
|
33
|
+
plains = [np.asanyarray(a).view(np.ndarray) if isinstance(a, np.ndarray) else a
|
|
34
|
+
for a in args]
|
|
35
|
+
|
|
36
|
+
def _f(*views, out=None):
|
|
37
|
+
numpy_func(*views, out=out, **kw)
|
|
38
|
+
try:
|
|
39
|
+
return _wrap(parallel_ewise(_f, *plains, out=out))
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
if out is None:
|
|
43
|
+
r = numpy_func(*[np.asanyarray(a).view(np.ndarray)
|
|
44
|
+
if isinstance(a, np.ndarray) else a for a in args], **kw)
|
|
45
|
+
else:
|
|
46
|
+
r = numpy_func(*[np.asanyarray(a).view(np.ndarray)
|
|
47
|
+
if isinstance(a, np.ndarray) else a for a in args],
|
|
48
|
+
out=out, **kw)
|
|
49
|
+
return out
|
|
50
|
+
return _wrap(r) if isinstance(r, np.ndarray) else r
|
|
51
|
+
wrapper.__name__ = getattr(numpy_func, "__name__", "ufunc")
|
|
52
|
+
wrapper.__doc__ = getattr(numpy_func, "__doc__", "")
|
|
53
|
+
return wrapper
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
add = _ew(np.add)
|
|
57
|
+
subtract = _ew(np.subtract)
|
|
58
|
+
multiply = _ew(np.multiply)
|
|
59
|
+
divide = _ew(np.divide)
|
|
60
|
+
power = _ew(np.power)
|
|
61
|
+
sqrt = _ew(np.sqrt)
|
|
62
|
+
exp = _ew(np.exp)
|
|
63
|
+
log = _ew(np.log)
|
|
64
|
+
sin = _ew(np.sin)
|
|
65
|
+
cos = _ew(np.cos)
|
|
66
|
+
tan = _ew(np.tan)
|
|
67
|
+
absolute = _ew(np.absolute)
|
|
68
|
+
abs = absolute
|
|
69
|
+
hypot = _ew(np.hypot)
|
|
70
|
+
maximum = _ew(np.maximum)
|
|
71
|
+
minimum = _ew(np.minimum)
|
|
72
|
+
expm1 = _ew(np.expm1)
|
|
73
|
+
log1p = _ew(np.log1p)
|
|
74
|
+
log2 = _ew(np.log2)
|
|
75
|
+
log10 = _ew(np.log10)
|
|
76
|
+
square = _ew(np.square)
|
|
77
|
+
cbrt = _ew(np.cbrt)
|
|
78
|
+
reciprocal = _ew(np.reciprocal)
|
|
79
|
+
arcsin = _ew(np.arcsin)
|
|
80
|
+
arccos = _ew(np.arccos)
|
|
81
|
+
arctan = _ew(np.arctan)
|
|
82
|
+
arctan2 = _ew(np.arctan2)
|
|
83
|
+
sinh = _ew(np.sinh)
|
|
84
|
+
cosh = _ew(np.cosh)
|
|
85
|
+
tanh = _ew(np.tanh)
|
|
86
|
+
floor = _ew(np.floor)
|
|
87
|
+
ceil = _ew(np.ceil)
|
|
88
|
+
rint = _ew(np.rint)
|
|
89
|
+
sign = _ew(np.sign)
|
|
90
|
+
sinc = _ew(np.sinc)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def clip(a, a_min, a_max, out=None):
|
|
94
|
+
a = np.asanyarray(a)
|
|
95
|
+
if a.size >= 50000:
|
|
96
|
+
def _f(v, out=None):
|
|
97
|
+
np.clip(v, a_min, a_max, out=out)
|
|
98
|
+
from ._core import _wrap as _w
|
|
99
|
+
try:
|
|
100
|
+
return _w(parallel_ewise(_f, a, out=out))
|
|
101
|
+
except Exception:
|
|
102
|
+
pass
|
|
103
|
+
return np.clip(a, a_min, a_max, out=out)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def where(condition, x=None, y=None):
|
|
107
|
+
return np.where(np.asanyarray(condition) if not np.isscalar(condition) else condition,
|
|
108
|
+
x, y)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _plain(a):
|
|
112
|
+
a = np.asanyarray(a)
|
|
113
|
+
return a.view(np.ndarray) if isinstance(a, np.ndarray) else a
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def fma(a, b, c, out=None):
|
|
117
|
+
"""Fused multiply-add: a*b + c with ONE allocation (half peak memory)."""
|
|
118
|
+
a, b, c = _plain(a), _plain(b), _plain(c)
|
|
119
|
+
if out is None:
|
|
120
|
+
out = np.multiply(a, b)
|
|
121
|
+
np.add(out, c, out=out)
|
|
122
|
+
from ._core import _wrap as _w
|
|
123
|
+
return _w(out)
|
|
124
|
+
np.multiply(a, b, out=out)
|
|
125
|
+
np.add(out, c, out=out)
|
|
126
|
+
return out
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def fms(a, b, c, out=None):
|
|
130
|
+
"""Fused multiply-subtract: a*b - c."""
|
|
131
|
+
a, b, c = _plain(a), _plain(b), _plain(c)
|
|
132
|
+
if out is None:
|
|
133
|
+
out = np.multiply(a, b)
|
|
134
|
+
np.subtract(out, c, out=out)
|
|
135
|
+
from ._core import _wrap as _w
|
|
136
|
+
return _w(out)
|
|
137
|
+
np.multiply(a, b, out=out)
|
|
138
|
+
np.subtract(out, c, out=out)
|
|
139
|
+
return out
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def fnma(a, b, c, out=None):
|
|
143
|
+
"""Fused neg-multiply-add: c - a*b."""
|
|
144
|
+
a, b, c = _plain(a), _plain(b), _plain(c)
|
|
145
|
+
if out is None:
|
|
146
|
+
out = np.multiply(a, b)
|
|
147
|
+
np.subtract(c, out, out=out)
|
|
148
|
+
from ._core import _wrap as _w
|
|
149
|
+
return _w(out)
|
|
150
|
+
np.multiply(a, b, out=out)
|
|
151
|
+
# need temp-free: out = c - out
|
|
152
|
+
np.subtract(c, out, out=out)
|
|
153
|
+
return out
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def lerp(a, b, t, out=None):
|
|
157
|
+
"""Linear interpolation: a + (b-a)*t (single-pass fused)."""
|
|
158
|
+
a, b, t = _plain(a), _plain(b), _plain(t)
|
|
159
|
+
if out is None:
|
|
160
|
+
out = np.subtract(b, a)
|
|
161
|
+
np.multiply(out, t, out=out)
|
|
162
|
+
np.add(out, a, out=out)
|
|
163
|
+
from ._core import _wrap as _w
|
|
164
|
+
return _w(out)
|
|
165
|
+
np.subtract(b, a, out=out)
|
|
166
|
+
np.multiply(out, t, out=out)
|
|
167
|
+
np.add(out, a, out=out)
|
|
168
|
+
return out
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# ---- reductions: numpy is already bandwidth-optimal single-threaded ----
|
|
172
|
+
def sum(a, axis=None, dtype=None, out=None, keepdims=False, **kw):
|
|
173
|
+
return np.sum(_plain(a), axis=axis, dtype=dtype, out=out, keepdims=keepdims, **kw)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def mean(a, axis=None, dtype=None, out=None, keepdims=False, **kw):
|
|
177
|
+
return np.mean(_plain(a), axis=axis, dtype=dtype, out=out, keepdims=keepdims, **kw)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def min(a, axis=None, out=None, keepdims=False, **kw):
|
|
181
|
+
return np.min(_plain(a), axis=axis, out=out, keepdims=keepdims, **kw)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def max(a, axis=None, out=None, keepdims=False, **kw):
|
|
185
|
+
return np.max(_plain(a), axis=axis, out=out, keepdims=keepdims, **kw)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
amin, amax = min, max
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def prod(a, axis=None, dtype=None, out=None, keepdims=False, **kw):
|
|
192
|
+
return np.prod(_plain(a), axis=axis, dtype=dtype, out=out, keepdims=keepdims, **kw)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def any(a, axis=None, out=None, keepdims=False, **kw):
|
|
196
|
+
return np.any(a, axis=axis, out=out, keepdims=keepdims, **kw)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def all(a, axis=None, out=None, keepdims=False, **kw):
|
|
200
|
+
return np.all(a, axis=axis, out=out, keepdims=keepdims, **kw)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
|
|
204
|
+
return np.std(a, axis=axis, dtype=dtype, out=out, ddof=ddof, keepdims=keepdims)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
|
|
208
|
+
return np.var(a, axis=axis, dtype=dtype, out=out, ddof=ddof, keepdims=keepdims)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def nansum(a, axis=None, dtype=None, out=None, keepdims=False, **kw):
|
|
212
|
+
return np.nansum(_plain(a), axis=axis, dtype=dtype, out=out, keepdims=keepdims, **kw)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def nanmean(a, axis=None, dtype=None, out=None, keepdims=False, **kw):
|
|
216
|
+
return np.nanmean(_plain(a), axis=axis, dtype=dtype, out=out, keepdims=keepdims, **kw)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def nanmin(a, axis=None, out=None, keepdims=False, **kw):
|
|
220
|
+
return np.nanmin(_plain(a), axis=axis, out=out, keepdims=keepdims, **kw)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def nanmax(a, axis=None, out=None, keepdims=False, **kw):
|
|
224
|
+
return np.nanmax(_plain(a), axis=axis, out=out, keepdims=keepdims, **kw)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def nanstd(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, **kw):
|
|
228
|
+
return np.nanstd(_plain(a), axis=axis, dtype=dtype, out=out, ddof=ddof,
|
|
229
|
+
keepdims=keepdims, **kw)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def cumsum(a, axis=None, dtype=None, out=None):
|
|
233
|
+
return np.cumsum(a, axis=axis, dtype=dtype, out=out)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def cumprod(a, axis=None, dtype=None, out=None):
|
|
237
|
+
return np.cumprod(a, axis=axis, dtype=dtype, out=out)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# ---- linear algebra entry points (BLAS-backed, same speed + optimize=True) ----
|
|
241
|
+
def dot(a, b, out=None):
|
|
242
|
+
return np.dot(a, b, out=out)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def matmul(a, b, out=None):
|
|
246
|
+
return np.matmul(a, b, out=out)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def einsum(*args, **kwargs):
|
|
250
|
+
kwargs.setdefault("optimize", True)
|
|
251
|
+
return np.einsum(*args, **kwargs)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def tensordot(a, b, axes=2):
|
|
255
|
+
return np.tensordot(a, b, axes=axes)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def vdot(a, b):
|
|
259
|
+
return np.vdot(a, b)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def inner(a, b):
|
|
263
|
+
return np.inner(a, b)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def outer(a, b, out=None):
|
|
267
|
+
return np.outer(a, b, out=out)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def kron(a, b):
|
|
271
|
+
return np.kron(a, b)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None):
|
|
275
|
+
return np.trace(a, offset=offset, axis1=axis1, axis2=axis2, dtype=dtype, out=out)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def sort(a, axis=-1, kind=None, order=None):
|
|
279
|
+
return np.sort(a, axis=axis, kind=kind, order=order)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def argsort(a, axis=-1, kind=None, order=None):
|
|
283
|
+
return np.argsort(a, axis=axis, kind=kind, order=order)
|