diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/lowlevel_strided_loops.c.src | 2 | ||||
-rw-r--r-- | numpy/core/src/umath/loops.c.src | 55 | ||||
-rw-r--r-- | numpy/lib/twodim_base.py | 19 | ||||
-rw-r--r-- | numpy/ma/core.py | 4 | ||||
-rw-r--r-- | numpy/ma/extras.py | 4 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 15 |
6 files changed, 88 insertions, 11 deletions
diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src index 02920014b..4a75e3293 100644 --- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src +++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src @@ -793,7 +793,7 @@ NPY_NO_EXPORT PyArray_StridedUnaryOp * #endif -static void +static NPY_GCC_OPT_3 void @prefix@_cast_@name1@_to_@name2@( char *dst, npy_intp dst_stride, char *src, npy_intp src_stride, diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index 3f5048592..ee7e7652d 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -52,6 +52,19 @@ && (steps[0] == steps[2])\ && (steps[0] == 0)) +/* binary loop input and output continous */ +#define IS_BINARY_CONT(tin, tout) (steps[0] == sizeof(tin) && \ + steps[1] == sizeof(tin) && \ + steps[2] == sizeof(tout)) +/* binary loop input and output continous with first scalar */ +#define IS_BINARY_CONT_S1(tin, tout) (steps[0] == 0 && \ + steps[1] == sizeof(tin) && \ + steps[2] == sizeof(tout)) +/* binary loop input and output continous with second scalar */ +#define IS_BINARY_CONT_S2(tin, tout) (steps[0] == sizeof(tin) && \ + steps[1] == 0 && \ + steps[2] == sizeof(tout)) + #define OUTPUT_LOOP\ char *op1 = args[1];\ npy_intp os1 = steps[1];\ @@ -803,13 +816,45 @@ NPY_NO_EXPORT void * #OP = ==, !=, >, >=, <, <=, &&, ||# */ -NPY_NO_EXPORT void +NPY_NO_EXPORT NPY_GCC_OPT_3 void @TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - BINARY_LOOP { - const @type@ in1 = *(@type@ *)ip1; - const @type@ in2 = *(@type@ *)ip2; - *((npy_bool *)op1) = in1 @OP@ in2; + /* + * gcc vectorization of this is not good (PR60575) but manual integer + * vectorization is too tedious to be worthwhile + */ + if (IS_BINARY_CONT(@type@, npy_bool)) { + npy_intp i, n = dimensions[0]; + @type@ * a = (@type@ *)args[0], * b = (@type@ *)args[1]; + npy_bool * o = (npy_bool *)args[2]; + for (i = 0; i < n; i++) { + o[i] = a[i] @OP@ b[i]; + } + } + else if (IS_BINARY_CONT_S1(@type@, npy_bool)) { + npy_intp i, n = dimensions[0]; + @type@ a = *(@type@ *)args[0]; + @type@ * b = (@type@ *)args[1]; + npy_bool * o = (npy_bool *)args[2]; + for (i = 0; i < n; i++) { + o[i] = a @OP@ b[i]; + } + } + else if (IS_BINARY_CONT_S2(@type@, npy_bool)) { + npy_intp i, n = dimensions[0]; + @type@ * a = (@type@ *)args[0]; + @type@ b = *(@type@*)args[1]; + npy_bool * o = (npy_bool *)args[2]; + for (i = 0; i < n; i++) { + o[i] = a[i] @OP@ b; + } + } + else { + BINARY_LOOP { + const @type@ in1 = *(@type@ *)ip1; + const @type@ in2 = *(@type@ *)ip2; + *((npy_bool *)op1) = in1 @OP@ in2; + } } } diff --git a/numpy/lib/twodim_base.py b/numpy/lib/twodim_base.py index 5a0c0e7ee..20b5cdd67 100644 --- a/numpy/lib/twodim_base.py +++ b/numpy/lib/twodim_base.py @@ -11,10 +11,24 @@ __all__ = ['diag', 'diagflat', 'eye', 'fliplr', 'flipud', 'rot90', 'tri', from numpy.core.numeric import ( asanyarray, subtract, arange, zeros, greater_equal, multiply, ones, - asarray, where, dtype as np_dtype, less + asarray, where, dtype as np_dtype, less, int8, int16, int32, int64 ) +from numpy.core import iinfo +i1 = iinfo(int8) +i2 = iinfo(int16) +i4 = iinfo(int32) +def _min_int(low, high): + """ get small int that fits the range """ + if high <= i1.max and low >= i1.min: + return int8 + if high <= i2.max and low >= i2.min: + return int16 + if high <= i4.max and low >= i4.min: + return int32 + return int64 + def fliplr(m): """ @@ -396,7 +410,8 @@ def tri(N, M=None, k=0, dtype=float): if M is None: M = N - m = greater_equal.outer(arange(N), arange(-k, M-k)) + m = greater_equal.outer(arange(N, dtype=_min_int(0, N)), + arange(-k, M-k, dtype=_min_int(-k, M - k))) # Avoid making a copy if the requested type is already bool if np_dtype(dtype) != np_dtype(bool): diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 34272d4cf..9c3c6a615 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -7002,6 +7002,8 @@ def asarray(a, dtype=None, order=None): <class 'numpy.ma.core.MaskedArray'> """ + if dtype is None and type(a) is MaskedArray: + return a return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=False) def asanyarray(a, dtype=None): @@ -7047,6 +7049,8 @@ def asanyarray(a, dtype=None): <class 'numpy.ma.core.MaskedArray'> """ + if dtype is None and isinstance(a, MaskedArray): + return a return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index c2d105584..7182bf4ae 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -842,9 +842,9 @@ def mask_rowcols(a, axis=None): fill_value=999999) """ - a = asarray(a) + a = array(a, subok=False) if a.ndim != 2: - raise NotImplementedError("compress2d works for 2D arrays only.") + raise NotImplementedError("mask_rowcols works for 2D arrays only.") m = getmask(a) # Nothing is masked: return a if m is nomask or not m.any(): diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 8cc973d09..b9b84d7b2 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -186,11 +186,24 @@ class TestMaskedArray(TestCase): (x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d xm.fill_value = -9999 xm._hardmask = True - xmm = asarray(xm) + xmm = asarray(xm, xm.dtype) assert_equal(xmm._data, xm._data) assert_equal(xmm._mask, xm._mask) assert_equal(xmm.fill_value, xm.fill_value) assert_equal(xmm._hardmask, xm._hardmask) + # address gh-4043 + self.assertTrue(xm is asarray(xm)) + + def test_asanyarray(self): + class M(MaskedArray): + pass + xm = M([]) + self.assertTrue(xm is not asarray(xm)) + # address gh-4043 + self.assertTrue(xm is asanyarray(xm)) + test = asanyarray(xm, np.int64) + self.assertTrue(isinstance(test, M)) + assert_equal(test.dtype, np.int64) def test_fix_invalid(self): # Checks fix_invalid. |