diff options
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/numeric.py | 130 | ||||
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 27 | ||||
-rw-r--r-- | numpy/core/src/umath/loops.c.src | 3 | ||||
-rw-r--r-- | numpy/core/src/umath/simd.inc.src | 183 | ||||
-rw-r--r-- | numpy/core/tests/test_numeric.py | 203 |
5 files changed, 503 insertions, 43 deletions
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index bb2f3d28d..13ee89744 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -40,7 +40,7 @@ __all__ = ['newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc', 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN', 'False_', 'True_', 'bitwise_not', 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS', 'BUFSIZE', 'ALLOW_THREADS', - 'ComplexWarning', 'may_share_memory'] + 'ComplexWarning', 'may_share_memory', 'full', 'full_like'] if sys.version_info[0] < 3: __all__.extend(['getbuffer', 'newbuffer']) @@ -137,7 +137,21 @@ def ones(shape, dtype=None, order='C'): """ Return a new array of given shape and type, filled with ones. - Please refer to the documentation for `zeros` for further details. + Parameters + ---------- + shape : int or sequence of ints + Shape of the new array, e.g., ``(2, 3)`` or ``2``. + dtype : data-type, optional + The desired data-type for the array, e.g., `numpy.int8`. Default is + `numpy.float64`. + order : {'C', 'F'}, optional + Whether to store multidimensional data in C- or Fortran-contiguous + (row- or column-wise) order in memory. + + Returns + ------- + out : ndarray + Array of ones with the given shape, dtype, and order. See Also -------- @@ -223,6 +237,111 @@ def ones_like(a, dtype=None, order='K', subok=True): multiarray.copyto(res, 1, casting='unsafe') return res +def full(shape, fill_value, dtype=None, order='C'): + """ + Return a new array of given shape and type, filled with `fill_value`. + + Parameters + ---------- + shape : int or sequence of ints + Shape of the new array, e.g., ``(2, 3)`` or ``2``. + fill_value : scalar + Fill value. + dtype : data-type, optional + The desired data-type for the array, e.g., `numpy.int8`. Default is + is chosen as `np.array(fill_value).dtype`. + order : {'C', 'F'}, optional + Whether to store multidimensional data in C- or Fortran-contiguous + (row- or column-wise) order in memory. + + Returns + ------- + out : ndarray + Array of `fill_value` with the given shape, dtype, and order. + + See Also + -------- + zeros_like : Return an array of zeros with shape and type of input. + ones_like : Return an array of ones with shape and type of input. + empty_like : Return an empty array with shape and type of input. + full_like : Fill an array with shape and type of input. + zeros : Return a new array setting values to zero. + ones : Return a new array setting values to one. + empty : Return a new uninitialized array. + + Examples + -------- + >>> np.full((2, 2), np.inf) + array([[ inf, inf], + [ inf, inf]]) + >>> np.full((2, 2), 10, dtype=np.int) + array([[10, 10], + [10, 10]]) + + """ + a = empty(shape, dtype, order) + multiarray.copyto(a, fill_value, casting='unsafe') + return a + +def full_like(a, fill_value, dtype=None, order='K', subok=True): + """ + Return a full array with the same shape and type as a given array. + + Parameters + ---------- + a : array_like + The shape and data-type of `a` define these same attributes of + the returned array. + fill_value : scalar + Fill value. + dtype : data-type, optional + Overrides the data type of the result. + order : {'C', 'F', 'A', or 'K'}, optional + Overrides the memory layout of the result. 'C' means C-order, + 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, + 'C' otherwise. 'K' means match the layout of `a` as closely + as possible. + subok : bool, optional. + If True, then the newly created array will use the sub-class + type of 'a', otherwise it will be a base-class array. Defaults + to True. + + Returns + ------- + out : ndarray + Array of `fill_value` with the same shape and type as `a`. + + See Also + -------- + zeros_like : Return an array of zeros with shape and type of input. + ones_like : Return an array of ones with shape and type of input. + empty_like : Return an empty array with shape and type of input. + zeros : Return a new array setting values to zero. + ones : Return a new array setting values to one. + empty : Return a new uninitialized array. + full : Fill a new array. + + Examples + -------- + >>> x = np.arange(6, dtype=np.int) + >>> np.full_like(x, 1) + array([1, 1, 1, 1, 1, 1]) + >>> np.full_like(x, 0.1) + array([0, 0, 0, 0, 0, 0]) + >>> np.full_like(x, 0.1, dtype=np.double) + array([ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) + >>> np.full_like(x, np.nan, dtype=np.double) + array([ nan, nan, nan, nan, nan, nan]) + + >>> y = np.arange(6, dtype=np.double) + >>> np.full_like(y, 0.1) + array([ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]) + + """ + res = empty_like(a, dtype=dtype, order=order, subok=subok) + multiarray.copyto(res, fill_value, casting='unsafe') + return res + def extend_all(module): adict = {} @@ -2005,7 +2124,12 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8): x = x[~xinf] y = y[~xinf] - return all(less_equal(abs(x-y), atol + rtol * abs(y))) + # ignore invalid fpe's + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + r = all(less_equal(abs(x-y), atol + rtol * abs(y))) + + return r def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): """ diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 62e84e699..41a56431b 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -3483,9 +3483,9 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) goto done; } elcount = (count < 0) ? 0 : count; - if ((elsize=dtype->elsize) == 0) { - PyErr_SetString(PyExc_ValueError, "Must specify length "\ - "when using variable-size data-type."); + if ((elsize = dtype->elsize) == 0) { + PyErr_SetString(PyExc_ValueError, + "Must specify length when using variable-size data-type."); goto done; } @@ -3494,8 +3494,8 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) * reference counts before throwing away any memory. */ if (PyDataType_REFCHK(dtype)) { - PyErr_SetString(PyExc_ValueError, "cannot create "\ - "object arrays from iterator"); + PyErr_SetString(PyExc_ValueError, + "cannot create object arrays from iterator"); goto done; } @@ -3522,7 +3522,7 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) } if (new_data == NULL) { PyErr_SetString(PyExc_MemoryError, - "cannot allocate array memory"); + "cannot allocate array memory"); Py_DECREF(value); goto done; } @@ -3530,16 +3530,21 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) } PyArray_DIMS(ret)[0] = i + 1; - if (((item = index2ptr(ret, i)) == NULL) - || (PyArray_DESCR(ret)->f->setitem(value, item, ret) == -1)) { + if (((item = index2ptr(ret, i)) == NULL) || + (PyArray_DESCR(ret)->f->setitem(value, item, ret) == -1)) { Py_DECREF(value); goto done; } Py_DECREF(value); } + + if (PyErr_Occurred()) { + goto done; + } if (i < count) { - PyErr_SetString(PyExc_ValueError, "iterator too short"); + PyErr_SetString(PyExc_ValueError, + "iterator too short"); goto done; } @@ -3548,11 +3553,13 @@ PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count) * (assuming realloc is reasonably good about reusing space...) */ if (i == 0) { + /* The size cannot be zero for PyDataMem_RENEW. */ i = 1; } new_data = PyDataMem_RENEW(PyArray_DATA(ret), i * elsize); if (new_data == NULL) { - PyErr_SetString(PyExc_MemoryError, "cannot allocate array memory"); + PyErr_SetString(PyExc_MemoryError, + "cannot allocate array memory"); goto done; } ((PyArrayObject_fields *)ret)->data = new_data; diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index a99bdb9d2..0559fb416 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -1351,6 +1351,9 @@ NPY_NO_EXPORT void NPY_NO_EXPORT void @TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { + if (run_binary_simd_@kind@_@TYPE@(args, dimensions, steps)) { + return; + } BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; const @type@ in2 = *(@type@ *)ip2; diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src index dc3b6ad8e..98e2beb30 100644 --- a/numpy/core/src/umath/simd.inc.src +++ b/numpy/core/src/umath/simd.inc.src @@ -24,6 +24,7 @@ #endif #include <assert.h> #include <stdlib.h> +#include <string.h> /* for memcpy */ int PyUFunc_getfperr(void); void PyUFunc_clearfperr(void); @@ -59,6 +60,19 @@ void PyUFunc_clearfperr(void); ((abs(args[2] - args[0]) >= (vsize)) || (abs(args[2] - args[0]) == 0)) && \ abs(args[2] - args[1]) >= (esize)) +#define IS_BLOCKABLE_BINARY_BOOL(esize, vsize) \ + (steps[0] == (esize) && steps[0] == steps[1] && steps[2] == (1) && \ + npy_is_aligned(args[1], (esize)) && \ + npy_is_aligned(args[0], (esize))) + +#define IS_BLOCKABLE_BINARY_SCALAR1_BOOL(esize, vsize) \ + (steps[0] == 0 && steps[1] == (esize) && steps[2] == (1) && \ + npy_is_aligned(args[1], (esize))) + +#define IS_BLOCKABLE_BINARY_SCALAR2_BOOL(esize, vsize) \ + (steps[0] == (esize) && steps[1] == 0 && steps[2] == (1) && \ + npy_is_aligned(args[0], (esize))) + /* align var to alignment */ #define LOOP_BLOCK_ALIGN_VAR(var, type, alignment)\ npy_intp i, peel = npy_aligned_block_offset(var, sizeof(type),\ @@ -72,6 +86,35 @@ void PyUFunc_clearfperr(void); #define LOOP_BLOCKED_END\ for (; i < n; i++) +/* fanout two bits to two bytes */ +static const npy_int16 fanout_2[] = { + 0x0000, + 0x0001, + 0x0100, + 0x0101, +}; + +/* fanout four bits to four bytes */ +static const npy_int32 fanout_4[] = { + 0x00000000, + 0x00000001, + 0x00000100, + 0x00000101, + 0x00010000, + 0x00010001, + 0x00010100, + 0x00010101, + 0x01000000, + 0x01000001, + 0x01000100, + 0x01000101, + 0x01010000, + 0x01010001, + 0x01010100, + 0x01010101 +}; + + /* * Dispatcher functions * decide whether the operation can be vectorized and run it @@ -122,7 +165,6 @@ run_@name@_simd_@func@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps /**begin repeat1 * Arithmetic * # kind = add, subtract, multiply, divide# - * # OP = +, -, *, /# */ #if @vector@ && defined HAVE_EMMINTRIN_H @@ -168,6 +210,55 @@ run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps /**end repeat1**/ +/**begin repeat1 + * #kind = equal, not_equal, less, less_equal, greater, greater_equal, + * logical_and, logical_or# + * #simd = 1, 1, 1, 1, 1, 1, 0, 0# + */ + +#if @vector@ && @simd@ && defined HAVE_EMMINTRIN_H + +/* prototypes */ +static void +sse2_binary_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, + npy_intp n); +static void +sse2_binary_scalar1_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, + npy_intp n); +static void +sse2_binary_scalar2_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, + npy_intp n); + +#endif + +static NPY_INLINE int +run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps) +{ +#if @vector@ && @simd@ && defined HAVE_EMMINTRIN_H + @type@ * ip1 = (@type@ *)args[0]; + @type@ * ip2 = (@type@ *)args[1]; + npy_bool * op = (npy_bool *)args[2]; + npy_intp n = dimensions[0]; + /* argument one scalar */ + if (IS_BLOCKABLE_BINARY_SCALAR1_BOOL(sizeof(@type@), 16)) { + sse2_binary_scalar1_@kind@_@TYPE@(op, ip1, ip2, n); + return 1; + } + /* argument two scalar */ + else if (IS_BLOCKABLE_BINARY_SCALAR2_BOOL(sizeof(@type@), 16)) { + sse2_binary_scalar2_@kind@_@TYPE@(op, ip1, ip2, n); + return 1; + } + else if (IS_BLOCKABLE_BINARY_BOOL(sizeof(@type@), 16)) { + sse2_binary_@kind@_@TYPE@(op, ip1, ip2, n); + return 1; + } +#endif + return 0; +} + +/**end repeat1**/ + /**end repeat**/ /* @@ -281,7 +372,10 @@ static NPY_INLINE npy_double sse2_horizontal_@VOP@___m128d(__m128d v) * #vtype = __m128, __m128d# * #vpre = _mm, _mm# * #vsuf = ps, pd# + * #vsufs = ss, sd# * #nan = NPY_NANF, NPY_NAN# + * #mtype = npy_int32, npy_int16# + * #fanout = fanout_4, fanout_2# */ @@ -407,6 +501,93 @@ sse2_binary_scalar2_@kind@_@TYPE@(@type@ * op, @type@ * ip1, @type@ * ip2, npy_i /**end repeat1**/ +/**begin repeat1 + * #kind = equal, not_equal, less, less_equal, greater, greater_equal# + * #OP = ==, !=, <, <=, >, >=# + * #VOP = cmpeq, cmpneq, cmplt, cmple, cmpgt, cmpge# +*/ + +/* sets invalid fpu flag on QNaN for consistency with packed compare */ +static NPY_INLINE int +sse2_ordered_cmp_@kind@_@TYPE@(const @type@ a, const @type@ b) +{ + @type@ tmp; + @vtype@ v = @vpre@_@VOP@_@vsufs@(@vpre@_load_@vsufs@(&a), + @vpre@_load_@vsufs@(&b)); + @vpre@_store_@vsufs@(&tmp, v); + return sizeof(@type@) == 4 ? + (*(npy_uint32 *)&tmp) & 1 : (*(npy_uint64 *)&tmp) & 1; +} + +static void +sse2_binary_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, npy_intp n) +{ + npy_bool * r; + LOOP_BLOCK_ALIGN_VAR(ip1, @type@, 16) { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[i], ip2[i]); + } + r = &op[i]; + LOOP_BLOCKED(@type@, 16) { + @vtype@ a = @vpre@_load_@vsuf@(&ip1[i]); + @vtype@ b = @vpre@_loadu_@vsuf@(&ip2[i]); + @vtype@ c = @vpre@_@VOP@_@vsuf@(a, b); + @mtype@ ir = @fanout@[@vpre@_movemask_@vsuf@(c)]; + /* may be unaligned */ + memcpy(r, &ir, sizeof(ir)); + r += sizeof(ir); + } + LOOP_BLOCKED_END { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[i], ip2[i]); + } +} + + +static void +sse2_binary_scalar1_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, npy_intp n) +{ + npy_bool * r; + @vtype@ a = @vpre@_set1_@vsuf@(ip1[0]); + LOOP_BLOCK_ALIGN_VAR(ip2, @type@, 16) { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[0], ip2[i]); + } + r = &op[i]; + LOOP_BLOCKED(@type@, 16) { + @vtype@ b = @vpre@_load_@vsuf@(&ip2[i]); + @vtype@ c = @vpre@_@VOP@_@vsuf@(a, b); + @mtype@ ir = @fanout@[@vpre@_movemask_@vsuf@(c)]; + /* may be unaligned */ + memcpy(r, &ir, sizeof(ir)); + r += sizeof(ir); + } + LOOP_BLOCKED_END { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[0], ip2[i]); + } +} + + +static void +sse2_binary_scalar2_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2, npy_intp n) +{ + npy_bool * r; + @vtype@ b = @vpre@_set1_@vsuf@(ip2[0]); + LOOP_BLOCK_ALIGN_VAR(ip1, @type@, 16) { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[i], ip2[0]); + } + r = &op[i]; + LOOP_BLOCKED(@type@, 16) { + @vtype@ a = @vpre@_load_@vsuf@(&ip1[i]); + @vtype@ c = @vpre@_@VOP@_@vsuf@(a, b); + @mtype@ ir = @fanout@[@vpre@_movemask_@vsuf@(c)]; + /* may be unaligned */ + memcpy(r, &ir, sizeof(ir)); + r += sizeof(ir); + } + LOOP_BLOCKED_END { + op[i] = sse2_ordered_cmp_@kind@_@TYPE@(ip1[i], ip2[0]); + } +} +/**end repeat1**/ + static void sse2_sqrt_@TYPE@(@type@ * op, @type@ * ip, const npy_intp n) { diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index ed4e0b79e..751722ffb 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -293,6 +293,53 @@ class TestBoolArray(TestCase): assert_array_equal(self.im ^ False, self.im) +class TestBoolCmp(TestCase): + def setUp(self): + self.f = ones(256, dtype=np.float32) + self.ef = ones(self.f.size, dtype=np.bool) + self.d = ones(128, dtype=np.float64) + self.ed = ones(self.d.size, dtype=np.bool) + # generate values for all permutation of 256bit simd vectors + s = 0 + for i in range(32): + self.f[s:s+8] = [i & 2**x for x in range(8)] + self.ef[s:s+8] = [(i & 2**x) != 0 for x in range(8)] + s += 8 + s = 0 + for i in range(16): + self.d[s:s+4] = [i & 2**x for x in range(4)] + self.ed[s:s+4] = [(i & 2**x) != 0 for x in range(4)] + s += 4 + + def test_float(self): + # offset for alignment test + for i in range(4): + assert_array_equal(self.f[i:] != 0, self.ef[i:]) + assert_array_equal(self.f[i:] > 0, self.ef[i:]) + assert_array_equal(self.f[i:] - 1 >= 0, self.ef[i:]) + assert_array_equal(self.f[i:] == 0, ~self.ef[i:]) + assert_array_equal(-self.f[i:] < 0, self.ef[i:]) + assert_array_equal(-self.f[i:] + 1 <= 0, self.ef[i:]) + + assert_array_equal(0 != self.f[i:], self.ef[i:]) + assert_array_equal(np.zeros_like(self.f)[i:] != self.f[i:], + self.ef[i:]) + + def test_double(self): + # offset for alignment test + for i in range(2): + assert_array_equal(self.d[i:] != 0, self.ed[i:]) + assert_array_equal(self.d[i:] > 0, self.ed[i:]) + assert_array_equal(self.d[i:] - 1 >= 0, self.ed[i:]) + assert_array_equal(self.d[i:] == 0, ~self.ed[i:]) + assert_array_equal(-self.d[i:] < 0, self.ed[i:]) + assert_array_equal(-self.d[i:] + 1 <= 0, self.ed[i:]) + + assert_array_equal(0 != self.d[i:], self.ed[i:]) + assert_array_equal(np.zeros_like(self.d)[i:] != self.d[i:], + self.ed[i:]) + + class TestSeterr(TestCase): def test_default(self): err = geterr() @@ -346,13 +393,12 @@ class TestFloatExceptions(TestCase): "Type %s raised wrong fpe error '%s'." % (ftype, exc)) def assert_op_raises_fpe(self, fpeerr, flop, sc1, sc2): - """Check that fpe exception is raised. - - Given a floating operation `flop` and two scalar values, check that - the operation raises the floating point exception specified by - `fpeerr`. Tests all variants with 0-d array scalars as well. + # Check that fpe exception is raised. + # + # Given a floating operation `flop` and two scalar values, check that + # the operation raises the floating point exception specified by + #`fpeerr`. Tests all variants with 0-d array scalars as well. - """ self.assert_raises_fpe(fpeerr, flop, sc1, sc2); self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2); self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]); @@ -360,7 +406,7 @@ class TestFloatExceptions(TestCase): @dec.knownfailureif(True, "See ticket 1755") def test_floating_exceptions(self): - """Test basic arithmetic function errors""" + # Test basic arithmetic function errors oldsettings = np.seterr(all='raise') try: # Test for all real and complex float types @@ -476,9 +522,11 @@ class TestTypes(TestCase): assert_equal(promote_func(array([b]),u64), np.dtype(uint64)) assert_equal(promote_func(array([i8]),f64), np.dtype(float64)) assert_equal(promote_func(array([u16]),f64), np.dtype(float64)) + # uint and int are treated as the same "kind" for # the purposes of array-scalar promotion. assert_equal(promote_func(array([u16]), i32), np.dtype(uint16)) + # float and complex are treated as the same "kind" for # the purposes of array-scalar promotion, so that you can do # (0j + float32array) to get a complex64 array instead of @@ -588,6 +636,11 @@ class TestTypes(TestCase): assert_raises(TypeError, np.can_cast, 'i4', None) assert_raises(TypeError, np.can_cast, None, 'i4') + +# Custom exception class to test exception propagation in fromiter +class NIterError(Exception): pass + + class TestFromiter(TestCase): def makegen(self): for x in range(24): @@ -607,12 +660,8 @@ class TestFromiter(TestCase): a20 = fromiter(self.makegen(), int, 20) self.assertTrue(len(a) == len(expected)) self.assertTrue(len(a20) == 20) - try: - fromiter(self.makegen(), int, len(expected) + 10) - except ValueError: - pass - else: - self.fail() + self.assertRaises(ValueError, fromiter, + self.makegen(), int, len(expected) + 10) def test_values(self): expected = array(list(self.makegen())) @@ -621,6 +670,28 @@ class TestFromiter(TestCase): self.assertTrue(alltrue(a == expected,axis=0)) self.assertTrue(alltrue(a20 == expected[:20],axis=0)) + def load_data(self, n, eindex): + # Utility method for the issue 2592 tests. + # Raise an exception at the desired index in the iterator. + for e in range(n): + if e == eindex: + raise NIterError('error at index %s' % eindex) + yield e + + def test_2592(self): + # Test iteration exceptions are correctly raised. + count, eindex = 10, 5 + self.assertRaises(NIterError, np.fromiter, + self.load_data(count, eindex), dtype=int, count=count) + + def test_2592_edge(self): + # Test iter. exceptions, edge case (exception at end of iterator). + count = 10 + eindex = count-1 + self.assertRaises(NIterError, np.fromiter, + self.load_data(count, eindex), dtype=int, count=count) + + class TestNonzero(TestCase): def test_nonzero_trivial(self): assert_equal(np.count_nonzero(array([])), 0) @@ -1398,8 +1469,63 @@ class TestStdVarComplex(TestCase): assert_almost_equal(std(A)**2,real_var) +class TestCreationFuncs(TestCase): + + '''Test ones, zeros, empty and filled''' + + def setUp(self): + self.dtypes = ('b', 'i', 'u', 'f', 'c', 'S', 'a', 'U', 'V') + self.orders = {'C': 'c_contiguous', 'F': 'f_contiguous'} + self.ndims = 10 + + def check_function(self, func, fill_value=None): + fill_kwarg = {} + if fill_value is not None: + fill_kwarg = {'fill_value': fill_value} + for size in (0, 1, 2): # size in one dimension + for ndims in range(self.ndims): # [], [size], [size, size] etc. + shape = ndims * [size] + for order in self.orders: # C, F + for type in self.dtypes: # bool, int, float etc. + for bytes in 2**np.arange(9): # byte size for type + try: + dtype = np.dtype('{0}{1}'.format(type, bytes)) + except TypeError: # dtype combination does not exist + continue + else: + # do not fill void type + if fill_value is not None and type in 'V': + continue + + arr = func(shape, order=order, dtype=dtype, + **fill_kwarg) + + assert arr.dtype == dtype + assert getattr(arr.flags, self.orders[order]) + + if fill_value is not None: + if dtype.str.startswith('|S'): + val = str(fill_value) + else: + val = fill_value + assert_equal(arr, dtype.type(val)) + + def test_zeros(self): + self.check_function(np.zeros) + + def test_ones(self): + self.check_function(np.zeros) + + def test_empty(self): + self.check_function(np.empty) + + def test_filled(self): + self.check_function(np.full, 0) + self.check_function(np.full, 1) + + class TestLikeFuncs(TestCase): - '''Test ones_like, zeros_like, and empty_like''' + '''Test ones_like, zeros_like, empty_like and full_like''' def setUp(self): self.data = [ @@ -1426,10 +1552,26 @@ class TestLikeFuncs(TestCase): (arange(24).reshape(4,3,2).swapaxes(0,1), '?'), ] - def check_like_function(self, like_function, value): + def compare_array_value(self, dz, value, fill_value): + if value is not None: + if fill_value: + try: + z = dz.dtype.type(value) + except OverflowError: + pass + else: + assert_(all(dz == z)) + else: + assert_(all(dz == value)) + + def check_like_function(self, like_function, value, fill_value=False): + if fill_value: + fill_kwarg = {'fill_value': value} + else: + fill_kwarg = {} for d, dtype in self.data: # default (K) order, dtype - dz = like_function(d, dtype=dtype) + dz = like_function(d, dtype=dtype, **fill_kwarg) assert_equal(dz.shape, d.shape) assert_equal(array(dz.strides)*d.dtype.itemsize, array(d.strides)*dz.dtype.itemsize) @@ -1439,33 +1581,30 @@ class TestLikeFuncs(TestCase): assert_equal(dz.dtype, d.dtype) else: assert_equal(dz.dtype, np.dtype(dtype)) - if not value is None: - assert_(all(dz == value)) + self.compare_array_value(dz, value, fill_value) # C order, default dtype - dz = like_function(d, order='C', dtype=dtype) + dz = like_function(d, order='C', dtype=dtype, **fill_kwarg) assert_equal(dz.shape, d.shape) assert_(dz.flags.c_contiguous) if dtype is None: assert_equal(dz.dtype, d.dtype) else: assert_equal(dz.dtype, np.dtype(dtype)) - if not value is None: - assert_(all(dz == value)) + self.compare_array_value(dz, value, fill_value) # F order, default dtype - dz = like_function(d, order='F', dtype=dtype) + dz = like_function(d, order='F', dtype=dtype, **fill_kwarg) assert_equal(dz.shape, d.shape) assert_(dz.flags.f_contiguous) if dtype is None: assert_equal(dz.dtype, d.dtype) else: assert_equal(dz.dtype, np.dtype(dtype)) - if not value is None: - assert_(all(dz == value)) + self.compare_array_value(dz, value, fill_value) # A order - dz = like_function(d, order='A', dtype=dtype) + dz = like_function(d, order='A', dtype=dtype, **fill_kwarg) assert_equal(dz.shape, d.shape) if d.flags.f_contiguous: assert_(dz.flags.f_contiguous) @@ -1475,16 +1614,15 @@ class TestLikeFuncs(TestCase): assert_equal(dz.dtype, d.dtype) else: assert_equal(dz.dtype, np.dtype(dtype)) - if not value is None: - assert_(all(dz == value)) + self.compare_array_value(dz, value, fill_value) # Test the 'subok' parameter a = np.matrix([[1,2],[3,4]]) - b = like_function(a) + b = like_function(a, **fill_kwarg) assert_(type(b) is np.matrix) - b = like_function(a, subok=False) + b = like_function(a, subok=False, **fill_kwarg) assert_(type(b) is not np.matrix) def test_ones_like(self): @@ -1496,6 +1634,13 @@ class TestLikeFuncs(TestCase): def test_empty_like(self): self.check_like_function(np.empty_like, None) + def test_filled_like(self): + self.check_like_function(np.full_like, 0, True) + self.check_like_function(np.full_like, 1, True) + self.check_like_function(np.full_like, 1000, True) + self.check_like_function(np.full_like, 123.456, True) + self.check_like_function(np.full_like, np.inf, True) + class _TestCorrelate(TestCase): def _setup(self, dt): self.x = np.array([1, 2, 3, 4, 5], dtype=dt) |