summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/numeric.py130
-rw-r--r--numpy/core/src/multiarray/ctors.c27
-rw-r--r--numpy/core/src/umath/loops.c.src3
-rw-r--r--numpy/core/src/umath/simd.inc.src183
-rw-r--r--numpy/core/tests/test_numeric.py203
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)