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 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)