diff options
author | Mark Wiebe <mwwiebe@gmail.com> | 2010-12-21 13:51:38 -0800 |
---|---|---|
committer | Mark Wiebe <mwwiebe@gmail.com> | 2011-01-09 01:55:00 -0800 |
commit | ba576a7faa8b5c67de4e078dba53f7fd88b0b8a1 (patch) | |
tree | 84b874c1b16823017d6f56777deca200cd45e9b6 | |
parent | f36566682043e9b2a27f3171c1fc94e63977d494 (diff) | |
download | numpy-ba576a7faa8b5c67de4e078dba53f7fd88b0b8a1.tar.gz |
ENH: iter: Move casting flags into a casting= parameter
-rw-r--r-- | numpy/core/include/numpy/ndarraytypes.h | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/new_iterator.c.src | 62 | ||||
-rw-r--r-- | numpy/core/src/multiarray/new_iterator.h | 39 | ||||
-rw-r--r-- | numpy/core/src/multiarray/new_iterator_pywrap.c | 105 | ||||
-rw-r--r-- | numpy/core/tests/test_new_iterator.py | 97 |
5 files changed, 209 insertions, 100 deletions
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index a0ae16990..5a552b8e6 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -174,14 +174,18 @@ typedef enum { } NPY_SCALARKIND; #define NPY_NSCALARKINDS (NPY_OBJECT_SCALAR + 1) +/* For specifying array memory layout or iteration order */ typedef enum { + /* Fortran order if inputs are all Fortran, C otherwise */ NPY_ANYORDER=-1, + /* C order */ NPY_CORDER=0, + /* Fortran order */ NPY_FORTRANORDER=1, + /* An order as close to the inputs as possible */ NPY_KEEPORDER=2 } NPY_ORDER; - typedef enum { NPY_CLIP=0, NPY_WRAP=1, diff --git a/numpy/core/src/multiarray/new_iterator.c.src b/numpy/core/src/multiarray/new_iterator.c.src index e853d9df0..2ede07943 100644 --- a/numpy/core/src/multiarray/new_iterator.c.src +++ b/numpy/core/src/multiarray/new_iterator.c.src @@ -51,7 +51,7 @@ /* The operand never needs buffering */ #define NPY_OP_ITFLAG_BUFNEVER 0x20 /* The operand is aligned */ -#define NPY_OP_ITFLAG_ALIGNED 0x80 +#define NPY_OP_ITFLAG_ALIGNED 0x40 /* Internal flag, for the type of operands */ #define NPY_ITER_OP_ARRAY 0 @@ -189,7 +189,7 @@ pyiter_prepare_operand(PyArrayObject **op, PyArray_Descr *op_request_dtype, static int npyiter_check_casting(npy_intp niter, PyArrayObject **op, PyArray_Descr **op_dtype, - npy_uint32 *op_flags, + NPY_CASTING casting, char *op_itflags); static int npyiter_fill_axisdata(NpyIter *iter, PyArrayObject **op, @@ -222,6 +222,8 @@ npyiter_get_common_dtype(npy_intp niter, PyArrayObject **op, npy_intp *op_ndim, int only_inputs); static int npyiter_promote_types(int type1, int type2); +static int +npyiter_can_cast(PyArray_Descr *from, PyArray_Descr *to, NPY_CASTING casting); static PyArrayObject * npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype, @@ -240,7 +242,8 @@ npyiter_copy_to_buffers(NpyIter *iter); /* The constructor for an iterator over multiple objects */ NpyIter* NpyIter_MultiNew(npy_intp niter, PyArrayObject **op_in, npy_uint32 flags, - NPY_ORDER order, npy_uint32 *op_flags, + NPY_ORDER order, NPY_CASTING casting, + npy_uint32 *op_flags, PyArray_Descr **op_request_dtypes, npy_intp oa_ndim, npy_intp **op_axes, npy_intp buffersize) { @@ -611,7 +614,7 @@ NpyIter_MultiNew(npy_intp niter, PyArrayObject **op_in, npy_uint32 flags, * to check that data type conversions are following the * casting rules. */ - if (!npyiter_check_casting(niter, op, op_dtype, op_flags, op_itflags)) { + if (!npyiter_check_casting(niter, op, op_dtype, casting, op_itflags)) { NpyIter_Deallocate(iter); return NULL; } @@ -848,7 +851,8 @@ NpyIter_MultiNew(npy_intp niter, PyArrayObject **op_in, npy_uint32 flags, /* The constructor for an iterator over one object */ NpyIter* NpyIter_New(PyArrayObject *op, npy_uint32 flags, - NPY_ORDER order, PyArray_Descr* dtype, + NPY_ORDER order, NPY_CASTING casting, + PyArray_Descr* dtype, npy_intp a_ndim, npy_intp *axes, npy_intp buffersize) { /* Split the flags into separate global and op flags */ @@ -856,11 +860,13 @@ NpyIter_New(PyArrayObject *op, npy_uint32 flags, flags &= NPY_ITER_GLOBAL_FLAGS; if (a_ndim > 0) { - return NpyIter_MultiNew(1, &op, flags, order, &op_flags, &dtype, + return NpyIter_MultiNew(1, &op, flags, order, casting, + &op_flags, &dtype, a_ndim, &axes, buffersize); } else { - return NpyIter_MultiNew(1, &op, flags, order, &op_flags, &dtype, + return NpyIter_MultiNew(1, &op, flags, order, casting, + &op_flags, &dtype, 0, NULL, buffersize); } } @@ -1970,22 +1976,27 @@ npyiter_check_per_op_flags(npy_uint32 op_flags, char *op_itflags) /* * Returns 1 if the from -> to cast can be done, based on the casting * flags provided in op_flags, and 0 otherwise. + * + * TODO: Maybe this approach, with the NPY_CASTING enum, should replace + * the PyArray_CanCastTo code for NumPy 2.0? */ static int -npyiter_can_cast(npy_uint32 op_flags, PyArray_Descr *from, PyArray_Descr *to) +npyiter_can_cast(PyArray_Descr *from, PyArray_Descr *to, NPY_CASTING casting) { /* If unsafe casts are allowed */ - if (op_flags&NPY_ITER_UNSAFE_CASTS) { + if (casting == NPY_UNSAFE_CASTING) { return 1; } - /* Equivalent types can be cast even with no casting flags */ + /* Equivalent types can be cast with any value of 'casting' */ else if (PyArray_EquivTypenums(from->type_num, to->type_num)) { /* If the types are extended, convert to NBO and compare */ if (PyTypeNum_ISEXTENDED(from->type_num)) { int ret; - if (!PyArray_ISNBO(from->byteorder) || - !PyArray_ISNBO(to->byteorder)) { + /* Only NPY_NO_CASTING prevents byte order conversion */ + if ((casting != NPY_NO_CASTING) && + (!PyArray_ISNBO(from->byteorder) || + !PyArray_ISNBO(to->byteorder))) { PyArray_Descr *nbo_from, *nbo_to; nbo_from = PyArray_DescrNewByteorder(from, NPY_NATIVE); @@ -2008,19 +2019,22 @@ npyiter_can_cast(npy_uint32 op_flags, PyArray_Descr *from, PyArray_Descr *to) return 1; } /* If safe or same-kind casts are allowed */ - else if (op_flags&(NPY_ITER_SAFE_CASTS| - NPY_ITER_SAME_KIND_CASTS)) { + else if (casting == NPY_SAFE_CASTING || casting == NPY_SAME_KIND_CASTING) { if (PyArray_CanCastTo(from, to)) { return 1; } - else if(op_flags&NPY_ITER_SAME_KIND_CASTS) { + else if(casting == NPY_SAME_KIND_CASTING) { + /* TODO: Should also allow casting from "lower" to "higher + * kinds, but kind is a char so we need to remap to + * an ordered version (like NPY_SCALARKIND is ordered). + */ return from->kind == to->kind; } else { return 0; } } - /* No casting flags were specified */ + /* NPY_NO_CASTING or NPY_EQUIV_CASTING was specified */ else { return 0; } @@ -2143,7 +2157,7 @@ pyiter_prepare_operand(PyArrayObject **op, PyArray_Descr *op_request_dtype, static int npyiter_check_casting(npy_intp niter, PyArrayObject **op, PyArray_Descr **op_dtype, - npy_uint32 *op_flags, + NPY_CASTING casting, char *op_itflags) { npy_intp iiter; @@ -2154,22 +2168,24 @@ npyiter_check_casting(npy_intp niter, PyArrayObject **op, op_dtype[iiter])) { /* Check read (op -> temp) casting */ if ((op_itflags[iiter]&NPY_OP_ITFLAG_READ) && - !npyiter_can_cast(op_flags[iiter], - PyArray_DESCR(op[iiter]), op_dtype[iiter])) { + !npyiter_can_cast(PyArray_DESCR(op[iiter]), + op_dtype[iiter], + casting)) { PyErr_Format(PyExc_TypeError, "Iterator operand %d dtype could not be cast " "to the requested dtype, according to " - "the casting flags given", (int)iiter); + "the casting enabled", (int)iiter); return 0; } /* Check write (temp -> op) casting */ if ((op_itflags[iiter]&NPY_OP_ITFLAG_WRITE) && - !npyiter_can_cast(op_flags[iiter], - op_dtype[iiter], PyArray_DESCR(op[iiter]))) { + !npyiter_can_cast(op_dtype[iiter], + PyArray_DESCR(op[iiter]), + casting)) { PyErr_Format(PyExc_TypeError, "Iterator requested dtype could not be cast " "to the operand %d dtype, according to " - "the casting flags given", (int)iiter); + "the casting enabled", (int)iiter); return 0; } diff --git a/numpy/core/src/multiarray/new_iterator.h b/numpy/core/src/multiarray/new_iterator.h index 1e551952d..a1071925f 100644 --- a/numpy/core/src/multiarray/new_iterator.h +++ b/numpy/core/src/multiarray/new_iterator.h @@ -12,18 +12,33 @@ typedef int (*NpyIter_IterNext_Fn )(NpyIter *iter); typedef void (*NpyIter_GetCoords_Fn )(NpyIter *iter, npy_intp *outcoords); +/* For specifying allowed casting in operations which support it */ +typedef enum { + /* Only allow exactly equivalent types */ + NPY_NO_CASTING=0, + /* Allow casts between equivalent types of different byte orders */ + NPY_EQUIV_CASTING=0, + /* Only allow safe casts */ + NPY_SAFE_CASTING=1, + /* Allow safe casts or casts within the same kind */ + NPY_SAME_KIND_CASTING=2, + /* Allow any casts */ + NPY_UNSAFE_CASTING=3 +} NPY_CASTING; + /* Allocate a new iterator over one array object */ NpyIter* NpyIter_New(PyArrayObject* op, npy_uint32 flags, - NPY_ORDER order, PyArray_Descr* dtype, + NPY_ORDER order, NPY_CASTING casting, + PyArray_Descr* dtype, npy_intp a_ndim, npy_intp *axes, npy_intp buffersize); /* Allocate a new iterator over multiple array objects */ NpyIter* NpyIter_MultiNew(npy_intp niter, PyArrayObject **op_in, npy_uint32 flags, - NPY_ORDER order, npy_uint32 *op_flags, - PyArray_Descr **op_request_dtypes, + NPY_ORDER order, NPY_CASTING casting, + npy_uint32 *op_flags, PyArray_Descr **op_request_dtypes, npy_intp oa_ndim, npy_intp **op_axes, npy_intp buffersize); /* Removes coords support from an iterator */ @@ -122,20 +137,14 @@ NPY_NO_EXPORT void NpyIter_DebugPrint(NpyIter *iter); #define NPY_ITER_COPY 0x00100000 /* The operand may be copied with UPDATEIFCOPY to satisfy requirements */ #define NPY_ITER_UPDATEIFCOPY 0x00200000 -/* Allow safe casts to be used when converting data */ -#define NPY_ITER_SAFE_CASTS 0x00400000 -/* Allow casts within types of the same kind to be used when converting data */ -#define NPY_ITER_SAME_KIND_CASTS 0x00800000 -/* Allow any casts when converting data */ -#define NPY_ITER_UNSAFE_CASTS 0x01000000 /* Allow writeable operands to have references or pointers */ -#define NPY_ITER_WRITEABLE_REFERENCES 0x02000000 +#define NPY_ITER_WRITEABLE_REFERENCES 0x00400000 /* Allocate the operand if it is NULL */ -#define NPY_ITER_ALLOCATE 0x04000000 -/* If an operand is allocated, don't use the priority subtype */ -#define NPY_ITER_NO_SUBTYPE 0x08000000 -/* Disallows broadcasting of the dimensions, they must match exactly */ -#define NPY_ITER_NO_BROADCAST 0x10000000 +#define NPY_ITER_ALLOCATE 0x00800000 +/* If an operand is allocated, don't use any subtype */ +#define NPY_ITER_NO_SUBTYPE 0x01000000 +/* Require that the dimension match the iterator dimensions exactly */ +#define NPY_ITER_NO_BROADCAST 0x02000000 #define NPY_ITER_GLOBAL_FLAGS 0x0000ffff #define NPY_ITER_PER_OP_FLAGS 0xffff0000 diff --git a/numpy/core/src/multiarray/new_iterator_pywrap.c b/numpy/core/src/multiarray/new_iterator_pywrap.c index e37b95417..94c9a04a1 100644 --- a/numpy/core/src/multiarray/new_iterator_pywrap.c +++ b/numpy/core/src/multiarray/new_iterator_pywrap.c @@ -79,10 +79,11 @@ static int npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"op", "flags", "op_flags", "op_dtypes", - "order", "op_axes", "buffersize"}; + "order", "casting", "op_axes", "buffersize", + NULL}; PyObject *op_in, *flags_in = NULL, *order_in = NULL, *op_flags_in = NULL, - *op_dtypes_in = NULL, *op_axes_in = NULL; + *op_dtypes_in = NULL, *casting_in = NULL, *op_axes_in = NULL; npy_intp iiter, buffersize = 0; @@ -90,6 +91,7 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) PyArrayObject *op[NPY_MAXARGS]; npy_uint32 flags = 0; NPY_ORDER order = NPY_KEEPORDER; + NPY_CASTING casting = NPY_NO_CASTING; npy_uint32 op_flags[NPY_MAXARGS]; PyArray_Descr *op_request_dtypes[NPY_MAXARGS]; npy_intp oa_ndim = 0; @@ -102,9 +104,9 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) return -1; } - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOi", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOi", kwlist, &op_in, &flags_in, &op_flags_in, &op_dtypes_in, - &order_in, &op_axes_in, &buffersize)) { + &order_in, &casting_in, &op_axes_in, &buffersize)) { return -1; } @@ -239,7 +241,7 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) if (length != 1) { PyErr_SetString(PyExc_ValueError, - "order must be 'C', 'F', 'A', or 'K'"); + "order must be one of 'C', 'F', 'A', or 'K'"); goto fail; } switch (str[0]) { @@ -257,10 +259,72 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) break; default: PyErr_SetString(PyExc_ValueError, - "order must be 'C', 'F', 'A', or 'K'"); + "order must be one of 'C', 'F', 'A', or 'K'"); goto fail; } } + /* casting */ + if (casting_in != NULL) { + char *str = NULL; + Py_ssize_t length = 0; + int bad_cast_input = 0; + + if (PyString_AsStringAndSize(casting_in, &str, &length) == -1) { + goto fail; + } + if (length >= 2) switch (str[2]) { + case 0: + if (strcmp(str, "no") == 0) { + casting = NPY_NO_CASTING; + } + else { + bad_cast_input = 1; + } + break; + case 'u': + if (strcmp(str, "equiv") == 0) { + casting = NPY_EQUIV_CASTING; + } + else { + bad_cast_input = 1; + } + break; + case 'f': + if (strcmp(str, "safe") == 0) { + casting = NPY_SAFE_CASTING; + } + else { + bad_cast_input = 1; + } + break; + case 'm': + if (strcmp(str, "same_kind") == 0) { + casting = NPY_SAME_KIND_CASTING; + } + else { + bad_cast_input = 1; + } + break; + case 's': + if (strcmp(str, "unsafe") == 0) { + casting = NPY_UNSAFE_CASTING; + } + else { + bad_cast_input = 1; + } + break; + default: + bad_cast_input = 1; + break; + + } + if (bad_cast_input) { + PyErr_SetString(PyExc_ValueError, + "casting must be one of 'no', 'equiv', 'safe', " + "'same_kind', or 'unsafe'"); + goto fail; + } + } /* op_flags */ if (op_flags_in == NULL) { for (iiter = 0; iiter < niter; ++iiter) { @@ -350,32 +414,9 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) break; } break; - case 's': - if (length > 2) switch (str[2]) { - case 'f': - if (strcmp(str, "safe_casts") == 0) { - flag = NPY_ITER_SAFE_CASTS; - } - break; - case 'm': - if (strcmp(str, "same_kind_casts") == 0) { - flag = NPY_ITER_SAME_KIND_CASTS; - } - break; - } - break; case 'u': - switch (str[1]) { - case 'n': - if (strcmp(str, "unsafe_casts") == 0) { - flag = NPY_ITER_UNSAFE_CASTS; - } - break; - case 'p': - if (strcmp(str, "updateifcopy") == 0) { - flag = NPY_ITER_UPDATEIFCOPY; - } - break; + if (strcmp(str, "updateifcopy") == 0) { + flag = NPY_ITER_UPDATEIFCOPY; } break; case 'w': @@ -553,7 +594,7 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds) } } - self->iter = NpyIter_MultiNew(niter, op, flags, order, op_flags, + self->iter = NpyIter_MultiNew(niter, op, flags, order, casting, op_flags, (PyArray_Descr**)op_request_dtypes, oa_ndim, oa_ndim > 0 ? op_axes : NULL, buffersize); diff --git a/numpy/core/tests/test_new_iterator.py b/numpy/core/tests/test_new_iterator.py index 50596fd73..37d71e7d9 100644 --- a/numpy/core/tests/test_new_iterator.py +++ b/numpy/core/tests/test_new_iterator.py @@ -27,7 +27,8 @@ def test_iter_refcount(): rc_a = sys.getrefcount(a) rc_dt = sys.getrefcount(dt) it = newiter(a, [], - [['readwrite','unsafe_casts','updateifcopy']], + [['readwrite','updateifcopy']], + casting='unsafe', op_dtypes=[dt]) assert_(sys.getrefcount(a) > rc_a) assert_(sys.getrefcount(dt) > rc_dt) @@ -664,16 +665,26 @@ def test_iter_array_cast(): assert_equal(i.operands[0], a) assert_equal(i.operands[0].dtype, np.dtype('f4')) + # Byte-order cast '<f4' -> '>f4' + a = np.arange(6, dtype='<f4').reshape(2,3) + i = newiter(a, [], [['readwrite','updateifcopy']], + casting='equiv', + op_dtypes=[np.dtype('>f4')]) + assert_equal(i.operands[0], a) + assert_equal(i.operands[0].dtype, np.dtype('>f4')) + # Safe case 'f4' -> 'f8' a = np.arange(24, dtype='f4').reshape(2,3,4).swapaxes(1,2) - i = newiter(a, [], [['readonly','copy','safe_casts']], + i = newiter(a, [], [['readonly','copy']], + casting='safe', op_dtypes=[np.dtype('f8')]) assert_equal(i.operands[0], a) assert_equal(i.operands[0].dtype, np.dtype('f8')) # The memory layout of the temporary should match a (a is (48,4,16)) assert_equal(i.operands[0].strides, (96,8,32)) a = a[::-1,:,::-1] - i = newiter(a, [], [['readonly','copy','safe_casts']], + i = newiter(a, [], [['readonly','copy']], + casting='safe', op_dtypes=[np.dtype('f8')]) assert_equal(i.operands[0], a) assert_equal(i.operands[0].dtype, np.dtype('f8')) @@ -682,7 +693,8 @@ def test_iter_array_cast(): # Same-kind cast 'f8' -> 'f4' -> 'f8' a = np.arange(24, dtype='f8').reshape(2,3,4).T i = newiter(a, [], - [['readwrite','updateifcopy','same_kind_casts']], + [['readwrite','updateifcopy']], + casting='same_kind', op_dtypes=[np.dtype('f4')]) assert_equal(i.operands[0], a) assert_equal(i.operands[0].dtype, np.dtype('f4')) @@ -696,7 +708,8 @@ def test_iter_array_cast(): # Unsafe cast 'f4' -> 'i4' a = np.arange(6, dtype='i4')[::-2] i = newiter(a, [], - [['writeonly','updateifcopy','unsafe_casts']], + [['writeonly','updateifcopy']], + casting='unsafe', op_dtypes=[np.dtype('f4')]) assert_equal(i.operands[0].dtype, np.dtype('f4')) assert_equal(i.operands[0].strides, (-4,)) @@ -716,19 +729,27 @@ def test_iter_array_cast_errors(): assert_raises(TypeError, newiter, arange(2,dtype='f8'), [], [['writeonly','updateifcopy']], op_dtypes=[np.dtype('f4')]) + # '<f4' -> '>f4' should not work with casting='no' + assert_raises(TypeError, newiter, arange(2,dtype='<f4'), [], + [['readonly']], casting='no', + op_dtypes=[np.dtype('>f4')]) # 'f4' -> 'f8' is a safe cast, but 'f8' -> 'f4' isn't assert_raises(TypeError, newiter, arange(2,dtype='f4'), [], - [['readwrite','updateifcopy','safe_casts']], + [['readwrite','updateifcopy']], + casting='safe', op_dtypes=[np.dtype('f8')]) assert_raises(TypeError, newiter, arange(2,dtype='f8'), [], - [['readwrite','updateifcopy','safe_casts']], + [['readwrite','updateifcopy']], + casting='safe', op_dtypes=[np.dtype('f4')]) # 'f4' -> 'i4' is neither a safe nor a same-kind cast assert_raises(TypeError, newiter, arange(2,dtype='f4'), [], - [['readonly','copy','same_kind_casts']], + [['readonly','copy']], + casting='same_kind', op_dtypes=[np.dtype('i4')]) assert_raises(TypeError, newiter, arange(2,dtype='i4'), [], - [['writeonly','updateifcopy','same_kind_casts']], + [['writeonly','updateifcopy']], + casting='same_kind', op_dtypes=[np.dtype('f4')]) def test_iter_scalar_cast(): @@ -742,21 +763,24 @@ def test_iter_scalar_cast(): assert_equal(i.value, 2.5) # Safe cast 'f4' -> 'f8' i = newiter(np.float32(2.5), [], - [['readonly','copy','safe_casts']], + [['readonly','copy']], + casting='safe', op_dtypes=[np.dtype('f8')]) assert_equal(i.dtypes[0], np.dtype('f8')) assert_equal(i.value.dtype, np.dtype('f8')) assert_equal(i.value, 2.5) # Same-kind cast 'f8' -> 'f4' i = newiter(np.float64(2.5), [], - [['readonly','copy','same_kind_casts']], + [['readonly','copy']], + casting='same_kind', op_dtypes=[np.dtype('f4')]) assert_equal(i.dtypes[0], np.dtype('f4')) assert_equal(i.value.dtype, np.dtype('f4')) assert_equal(i.value, 2.5) # Unsafe cast 'f8' -> 'i4' i = newiter(np.float64(3.0), [], - [['readonly','copy','unsafe_casts']], + [['readonly','copy']], + casting='unsafe', op_dtypes=[np.dtype('i4')]) assert_equal(i.dtypes[0], np.dtype('i4')) assert_equal(i.value.dtype, np.dtype('i4')) @@ -772,11 +796,13 @@ def test_iter_scalar_cast_errors(): [['readonly']], op_dtypes=[np.dtype('f4')]) # 'f8' -> 'f4' isn't a safe cast assert_raises(TypeError, newiter, np.float64(2), [], - [['readonly','safe_casts']], + [['readonly']], + casting='safe', op_dtypes=[np.dtype('f4')]) # 'f4' -> 'i4' is neither a safe nor a same-kind cast assert_raises(TypeError, newiter, np.float32(2), [], - [['readonly','same_kind_casts']], + [['readonly']], + casting='same_kind', op_dtypes=[np.dtype('i4')]) def test_iter_common_data_type(): @@ -784,17 +810,20 @@ def test_iter_common_data_type(): i = newiter([array([3],dtype='f4'),array([0],dtype='f8')], ['common_data_type'], - [['readonly','copy','safe_casts']]*2) + [['readonly','copy']]*2, + casting='safe') assert_equal(i.dtypes[0], np.dtype('f8')); assert_equal(i.dtypes[1], np.dtype('f8')); i = newiter([array([3],dtype='i4'),array([0],dtype='f4')], ['common_data_type'], - [['readonly','copy','safe_casts']]*2) + [['readonly','copy']]*2, + casting='safe') assert_equal(i.dtypes[0], np.dtype('f8')); assert_equal(i.dtypes[1], np.dtype('f8')); i = newiter([array([3],dtype='f4'),array(0,dtype='f8')], ['common_data_type'], - [['readonly','copy','same_kind_casts']]*2) + [['readonly','copy']]*2, + casting='same_kind') assert_equal(i.dtypes[0], np.dtype('f4')); assert_equal(i.dtypes[1], np.dtype('f4')); # TODO @@ -804,18 +833,21 @@ def test_iter_common_data_type(): # be written during iteration, invalidating the scalar kind assumed! i = newiter([array([3],dtype='u4'),array(0,dtype='i4')], ['common_data_type'], - [['readonly','copy','unsafe_casts']]*2) + [['readonly','copy']]*2, + casting='unsafe') assert_equal(i.dtypes[0], np.dtype('u4')); assert_equal(i.dtypes[1], np.dtype('u4')); i = newiter([array([3],dtype='u4'),array(-12,dtype='i4')], ['common_data_type'], - [['readonly','copy','safe_casts']]*2) + [['readonly','copy']]*2, + casting='safe') assert_equal(i.dtypes[0], np.dtype('i8')); assert_equal(i.dtypes[1], np.dtype('i8')); i = newiter([array([3],dtype='u4'),array(-12,dtype='i4'), array([2j],dtype='c8'),array([9],dtype='f8')], ['common_data_type'], - [['readonly','copy','safe_casts']]*4) + [['readonly','copy']]*4, + casting='safe') assert_equal(i.dtypes[0], np.dtype('c16')); assert_equal(i.dtypes[1], np.dtype('c16')); assert_equal(i.dtypes[2], np.dtype('c16')); @@ -824,18 +856,20 @@ def test_iter_common_data_type(): # When allocating outputs, other outputs aren't factored in i = newiter([array([3],dtype='i4'),None,array([2j],dtype='c16')], [], - [['readonly','copy','safe_casts'], + [['readonly','copy'], ['writeonly','allocate'], - ['writeonly']]) + ['writeonly']], + casting='safe') assert_equal(i.dtypes[0], np.dtype('i4')); assert_equal(i.dtypes[1], np.dtype('i4')); assert_equal(i.dtypes[2], np.dtype('c16')); # But, if common data types are requested, they are i = newiter([array([3],dtype='i4'),None,array([2j],dtype='c16')], ['common_data_type'], - [['readonly','copy','safe_casts'], + [['readonly','copy'], ['writeonly','allocate'], - ['writeonly']]) + ['writeonly']], + casting='safe') assert_equal(i.dtypes[0], np.dtype('c16')); assert_equal(i.dtypes[1], np.dtype('c16')); assert_equal(i.dtypes[2], np.dtype('c16')); @@ -1128,7 +1162,8 @@ def test_iter_buffered_cast_simple(): a = np.arange(10, dtype='f4') i = np.newiter(a, ['buffered','no_inner_iteration'], - [['readwrite','nbo_aligned','same_kind_casts']], + [['readwrite','nbo_aligned']], + casting='same_kind', op_dtypes=[np.dtype('f8')], buffersize=3) for v in i: @@ -1165,7 +1200,8 @@ def test_iter_buffered_cast_byteswapped(): a = np.arange(10, dtype='c8').newbyteorder().byteswap() a += 2j i = np.newiter(a, ['buffered','no_inner_iteration'], - [['readwrite','nbo_aligned','same_kind_casts']], + [['readwrite','nbo_aligned']], + casting='same_kind', op_dtypes=[np.dtype('c16')], buffersize=3) for v in i: @@ -1175,7 +1211,8 @@ def test_iter_buffered_cast_byteswapped(): a = np.arange(10, dtype='c8') a += 2j i = np.newiter(a, ['buffered','no_inner_iteration'], - [['readwrite','nbo_aligned','same_kind_casts']], + [['readwrite','nbo_aligned']], + casting='same_kind', op_dtypes=[np.dtype('c16').newbyteorder()], buffersize=3) for v in i: @@ -1185,7 +1222,8 @@ def test_iter_buffered_cast_byteswapped(): a = np.arange(10, dtype=np.clongdouble).newbyteorder().byteswap() a += 2j i = np.newiter(a, ['buffered','no_inner_iteration'], - [['readwrite','nbo_aligned','same_kind_casts']], + [['readwrite','nbo_aligned']], + casting='same_kind', op_dtypes=[np.dtype('c16')], buffersize=3) for v in i: @@ -1194,7 +1232,8 @@ def test_iter_buffered_cast_byteswapped(): a = np.arange(10, dtype=np.longdouble).newbyteorder().byteswap() i = np.newiter(a, ['buffered','no_inner_iteration'], - [['readwrite','nbo_aligned','same_kind_casts']], + [['readwrite','nbo_aligned']], + casting='same_kind', op_dtypes=[np.dtype('f4')], buffersize=7) for v in i: |