summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMark Wiebe <mwiebe@enthought.com>2011-07-18 18:08:57 -0500
committerMark Wiebe <mwiebe@enthought.com>2011-07-19 14:00:28 -0500
commitc9f0f296bea82af0cf475d21b44f10ebd9e99268 (patch)
treed6d5b21d95067cd51f5bf2756d5c329735a69810 /numpy
parent0a7156ffdc9fae4432d60a52a6360e4d2fa43cbb (diff)
downloadnumpy-c9f0f296bea82af0cf475d21b44f10ebd9e99268.tar.gz
ENH: core: Fix more test failures post-field access deprecation
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/calculation.c19
-rw-r--r--numpy/core/src/multiarray/ctors.c22
-rw-r--r--numpy/core/src/multiarray/item_selection.c130
-rw-r--r--numpy/core/src/multiarray/iterators.c9
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c10
-rw-r--r--numpy/core/tests/test_einsum.py18
-rw-r--r--numpy/core/tests/test_multiarray.py8
-rw-r--r--numpy/core/tests/test_ufunc.py4
8 files changed, 107 insertions, 113 deletions
diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c
index 5c4a3099c..a6cb82ecb 100644
--- a/numpy/core/src/multiarray/calculation.c
+++ b/numpy/core/src/multiarray/calculation.c
@@ -45,7 +45,6 @@ PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
intp *rptr;
intp i, n, m;
int elsize;
- int copyret = 0;
NPY_BEGIN_THREADS_DEF;
if ((ap=(PyArrayObject *)PyArray_CheckAxis(op, &axis, 0)) == NULL) {
@@ -76,8 +75,7 @@ PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
}
/* Will get native-byte order contiguous copy. */
- ap = (PyArrayObject *)
- PyArray_ContiguousFromAny((PyObject *)op,
+ ap = (PyArrayObject *)PyArray_ContiguousFromAny((PyObject *)op,
PyArray_DESCR(op)->type_num, 1, 0);
Py_DECREF(op);
if (ap == NULL) {
@@ -112,16 +110,12 @@ PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
PyErr_SetString(PyExc_TypeError,
"invalid shape for output array.");
}
- rp = (PyArrayObject *)\
- PyArray_FromArray(out,
+ rp = (PyArrayObject *)PyArray_FromArray(out,
PyArray_DescrFromType(PyArray_INTP),
NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY);
if (rp == NULL) {
goto fail;
}
- if (rp != out) {
- copyret = 1;
- }
}
NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(ap));
@@ -134,12 +128,11 @@ PyArray_ArgMax(PyArrayObject *op, int axis, PyArrayObject *out)
NPY_END_THREADS_DESCR(PyArray_DESCR(ap));
Py_DECREF(ap);
- if (copyret) {
- PyArrayObject *obj;
- obj = (PyArrayObject *)PyArray_BASE(rp);
- Py_INCREF(obj);
+ /* Trigger the UPDATEIFCOPY if necessary */
+ if (out != NULL && out != rp) {
Py_DECREF(rp);
- rp = obj;
+ rp = out;
+ Py_INCREF(rp);
}
return (PyObject *)rp;
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 41db49832..50a4387bf 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -1790,7 +1790,7 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
/* If we got dimensions and dtype instead of an array */
if (arr == NULL) {
- if (flags&NPY_ARRAY_UPDATEIFCOPY) {
+ if (flags & NPY_ARRAY_UPDATEIFCOPY) {
Py_XDECREF(newtype);
PyErr_SetString(PyExc_TypeError,
"UPDATEIFCOPY used for non-array input.");
@@ -2058,16 +2058,17 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
if (ret == NULL) {
return NULL;
}
- if (PyArray_CopyInto(ret, arr) == -1) {
+ if (PyArray_CopyInto(ret, arr) < 0) {
Py_DECREF(ret);
return NULL;
}
if (flags & NPY_ARRAY_UPDATEIFCOPY) {
+ /*
+ * Don't use PyArray_SetBase, because that compresses
+ * the chain of bases.
+ */
Py_INCREF(arr);
- if (PyArray_SetBase(ret, (PyObject *)arr) < 0) {
- Py_DECREF(ret);
- return NULL;
- }
+ ((PyArrayObject_fieldaccess *)ret)->base = (PyObject *)arr;
PyArray_ENABLEFLAGS(ret, NPY_ARRAY_UPDATEIFCOPY);
PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEABLE);
}
@@ -2135,11 +2136,12 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
return NULL;
}
if (flags & NPY_ARRAY_UPDATEIFCOPY) {
+ /*
+ * Don't use PyArray_SetBase, because that compresses
+ * the chain of bases.
+ */
Py_INCREF(arr);
- if (PyArray_SetBase(ret, (PyObject *)arr) < 0) {
- Py_DECREF(ret);
- return NULL;
- }
+ ((PyArrayObject_fieldaccess *)ret)->base = (PyObject *)arr;
PyArray_ENABLEFLAGS(ret, NPY_ARRAY_UPDATEIFCOPY);
PyArray_CLEARFLAGS(arr, NPY_ARRAY_WRITEABLE);
}
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index 672260e70..c4154501e 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -25,14 +25,13 @@
*/
NPY_NO_EXPORT PyObject *
PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
- PyArrayObject *ret, NPY_CLIPMODE clipmode)
+ PyArrayObject *out, NPY_CLIPMODE clipmode)
{
PyArray_FastTakeFunc *func;
- PyArrayObject *self, *indices;
+ PyArrayObject *obj, *self, *indices;
intp nd, i, j, n, m, max_item, tmp, chunk, nelem;
intp shape[MAX_DIMS];
char *src, *dest;
- int copyret = 0;
int err;
indices = NULL;
@@ -44,7 +43,6 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
PyArray_INTP,
1, 0);
if (indices == NULL) {
- Py_XINCREF(ret);
goto fail;
}
n = m = chunk = 1;
@@ -65,28 +63,25 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
}
}
}
- Py_INCREF(PyArray_DESCR(self));
- if (!ret) {
- ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(self),
+ if (!out) {
+ Py_INCREF(PyArray_DESCR(self));
+ obj = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(self),
PyArray_DESCR(self),
nd, shape,
NULL, NULL, 0,
(PyObject *)self);
- if (ret == NULL) {
+ if (obj == NULL) {
goto fail;
}
}
else {
- PyArrayObject *obj;
int flags = NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY;
- if ((PyArray_NDIM(ret) != nd) ||
- !PyArray_CompareLists(PyArray_DIMS(ret), shape, nd)) {
+ if ((PyArray_NDIM(out) != nd) ||
+ !PyArray_CompareLists(PyArray_DIMS(out), shape, nd)) {
PyErr_SetString(PyExc_ValueError,
"bad shape in output array");
- ret = NULL;
- Py_DECREF(PyArray_DESCR(self));
goto fail;
}
@@ -98,22 +93,19 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
*/
flags |= NPY_ARRAY_ENSURECOPY;
}
- obj = (PyArrayObject *)PyArray_FromArray(ret, PyArray_DESCR(self),
+ Py_INCREF(PyArray_DESCR(self));
+ obj = (PyArrayObject *)PyArray_FromArray(out, PyArray_DESCR(self),
flags);
- if (obj != ret) {
- copyret = 1;
- }
- ret = obj;
- if (ret == NULL) {
+ if (obj == NULL) {
goto fail;
}
}
max_item = PyArray_DIMS(self)[axis];
nelem = chunk;
- chunk = chunk * PyArray_DESCR(ret)->elsize;
+ chunk = chunk * PyArray_DESCR(obj)->elsize;
src = PyArray_DATA(self);
- dest = PyArray_DATA(ret);
+ dest = PyArray_DATA(obj);
func = PyArray_DESCR(self)->f->fasttake;
if (func == NULL) {
@@ -183,20 +175,17 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
}
}
- PyArray_INCREF(ret);
Py_XDECREF(indices);
Py_XDECREF(self);
- if (copyret) {
- PyObject *obj;
- obj = PyArray_BASE(ret);
+ if (out != NULL && out != obj) {
+ Py_DECREF(obj);
+ obj = out;
Py_INCREF(obj);
- Py_DECREF(ret);
- ret = (PyArrayObject *)obj;
}
- return (PyObject *)ret;
+ return (PyObject *)obj;
fail:
- PyArray_XDECREF_ERR(ret);
+ PyArray_XDECREF_ERR(obj);
Py_XDECREF(indices);
Py_XDECREF(self);
return NULL;
@@ -388,6 +377,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
{
PyArray_FastPutmaskFunc *func;
PyArrayObject *mask, *values;
+ PyArray_Descr *dtype;
intp i, chunk, ni, max_item, nv, tmp;
char *src, *dest;
int copied = 0;
@@ -401,17 +391,17 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
values = NULL;
if (!PyArray_Check(self)) {
PyErr_SetString(PyExc_TypeError,
- "putmask: first argument must "\
+ "putmask: first argument must "
"be an array");
return NULL;
}
if (!PyArray_ISCONTIGUOUS(self)) {
PyArrayObject *obj;
- int flags = NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY;
- Py_INCREF(PyArray_DESCR(self));
- obj = (PyArrayObject *)PyArray_FromArray(self,
- PyArray_DESCR(self), flags);
+ dtype = PyArray_DESCR(self);
+ Py_INCREF(dtype);
+ obj = (PyArrayObject *)PyArray_FromArray(self, dtype,
+ NPY_ARRAY_CARRAY | NPY_ARRAY_UPDATEIFCOPY);
if (obj != self) {
copied = 1;
}
@@ -421,22 +411,22 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
max_item = PyArray_SIZE(self);
dest = PyArray_DATA(self);
chunk = PyArray_DESCR(self)->elsize;
- mask = (PyArrayObject *)\
- PyArray_FROM_OTF(mask0, PyArray_BOOL,
- NPY_ARRAY_CARRAY | NPY_ARRAY_FORCECAST);
+ mask = (PyArrayObject *)PyArray_FROM_OTF(mask0, NPY_BOOL,
+ NPY_ARRAY_CARRAY | NPY_ARRAY_FORCECAST);
if (mask == NULL) {
goto fail;
}
ni = PyArray_SIZE(mask);
if (ni != max_item) {
PyErr_SetString(PyExc_ValueError,
- "putmask: mask and data must be "\
+ "putmask: mask and data must be "
"the same size");
goto fail;
}
- Py_INCREF(PyArray_DESCR(self));
- values = (PyArrayObject *)\
- PyArray_FromAny(values0, PyArray_DESCR(self), 0, 0, NPY_ARRAY_CARRAY, NULL);
+ dtype = PyArray_DESCR(self);
+ Py_INCREF(dtype);
+ values = (PyArrayObject *)PyArray_FromAny(values0, dtype,
+ 0, 0, NPY_ARRAY_CARRAY, NULL);
if (values == NULL) {
goto fail;
}
@@ -449,7 +439,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
}
if (PyDataType_REFCHK(PyArray_DESCR(self))) {
for (i = 0; i < ni; i++) {
- tmp = ((Bool *)(PyArray_DATA(mask)))[i];
+ tmp = ((npy_bool *)(PyArray_DATA(mask)))[i];
if (tmp) {
src = PyArray_DATA(values) + chunk * (i % nv);
PyArray_Item_INCREF(src, PyArray_DESCR(self));
@@ -462,7 +452,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
func = PyArray_DESCR(self)->f->fastputmask;
if (func == NULL) {
for (i = 0; i < ni; i++) {
- tmp = ((Bool *)(PyArray_DATA(mask)))[i];
+ tmp = ((npy_bool *)(PyArray_DATA(mask)))[i];
if (tmp) {
src = PyArray_DATA(values) + chunk*(i % nv);
memmove(dest + i*chunk, src, chunk);
@@ -599,16 +589,17 @@ PyArray_Repeat(PyArrayObject *aop, PyObject *op, int axis)
/*NUMPY_API
*/
NPY_NO_EXPORT PyObject *
-PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *ret,
+PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *out,
NPY_CLIPMODE clipmode)
{
+ PyArrayObject *obj = NULL;
+ PyArray_Descr *dtype;
int n, elsize;
intp i;
char *ret_data;
PyArrayObject **mps, *ap;
PyArrayMultiIterObject *multi = NULL;
intp mi;
- int copyret = 0;
ap = NULL;
/*
@@ -635,27 +626,27 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *ret,
goto fail;
}
/* Set-up return array */
- if (!ret) {
- Py_INCREF(PyArray_DESCR(mps[0]));
- ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(ap),
- PyArray_DESCR(mps[0]),
+ if (out == NULL) {
+ dtype = PyArray_DESCR(mps[0]);
+ Py_INCREF(dtype);
+ obj = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(ap),
+ dtype,
multi->nd,
multi->dimensions,
NULL, NULL, 0,
(PyObject *)ap);
}
else {
- PyArrayObject *obj;
int flags = NPY_ARRAY_CARRAY |
NPY_ARRAY_UPDATEIFCOPY |
NPY_ARRAY_FORCECAST;
- if ((PyArray_NDIM(ret) != multi->nd)
- || !PyArray_CompareLists(
- PyArray_DIMS(ret), multi->dimensions, multi->nd)) {
+ if ((PyArray_NDIM(out) != multi->nd)
+ || !PyArray_CompareLists(PyArray_DIMS(out),
+ multi->dimensions,
+ multi->nd)) {
PyErr_SetString(PyExc_TypeError,
- "invalid shape for output array.");
- ret = NULL;
+ "choose: invalid shape for output array.");
goto fail;
}
if (clipmode == NPY_RAISE) {
@@ -666,19 +657,16 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *ret,
*/
flags |= NPY_ARRAY_ENSURECOPY;
}
- Py_INCREF(PyArray_DESCR(mps[0]));
- obj = (PyArrayObject *)PyArray_FromArray(ret, PyArray_DESCR(mps[0]), flags);
- if (obj != ret) {
- copyret = 1;
- }
- ret = obj;
+ dtype = PyArray_DESCR(mps[0]);
+ Py_INCREF(dtype);
+ obj = (PyArrayObject *)PyArray_FromArray(out, dtype, flags);
}
- if (ret == NULL) {
+ if (obj == NULL) {
goto fail;
}
- elsize = PyArray_DESCR(ret)->elsize;
- ret_data = PyArray_DATA(ret);
+ elsize = PyArray_DESCR(obj)->elsize;
+ ret_data = PyArray_DATA(obj);
while (PyArray_MultiIter_NOTDONE(multi)) {
mi = *((intp *)PyArray_MultiIter_DATA(multi, n));
@@ -716,21 +704,19 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *ret,
PyArray_MultiIter_NEXT(multi);
}
- PyArray_INCREF(ret);
+ PyArray_INCREF(obj);
Py_DECREF(multi);
for (i = 0; i < n; i++) {
Py_XDECREF(mps[i]);
}
Py_DECREF(ap);
PyDataMem_FREE(mps);
- if (copyret) {
- PyObject *obj;
- obj = PyArray_BASE(ret);
+ if (out != NULL && out != obj) {
+ Py_DECREF(obj);
+ obj = out;
Py_INCREF(obj);
- Py_DECREF(ret);
- ret = (PyArrayObject *)obj;
}
- return (PyObject *)ret;
+ return (PyObject *)obj;
fail:
Py_XDECREF(multi);
@@ -739,7 +725,7 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *ret,
}
Py_XDECREF(ap);
PyDataMem_FREE(mps);
- PyArray_XDECREF_ERR(ret);
+ PyArray_XDECREF_ERR(obj);
return NULL;
}
diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c
index 6acbca4b7..ecf57b465 100644
--- a/numpy/core/src/multiarray/iterators.c
+++ b/numpy/core/src/multiarray/iterators.c
@@ -1183,11 +1183,12 @@ iter_array(PyArrayIterObject *it, PyObject *NPY_UNUSED(op))
Py_DECREF(ret);
return NULL;
}
+ /*
+ * Don't use PyArray_SetBase, because that compresses
+ * the chain of bases.
+ */
Py_INCREF(it->ao);
- if (PyArray_SetBase(ret, (PyObject *)it->ao) < 0) {
- Py_DECREF(ret);
- return NULL;
- }
+ ((PyArrayObject_fieldaccess *)ret)->base = (PyObject *)it->ao;
PyArray_ENABLEFLAGS(ret, NPY_ARRAY_UPDATEIFCOPY);
PyArray_CLEARFLAGS(it->ao, NPY_ARRAY_WRITEABLE);
}
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index 2644ee2db..feecb6480 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -2862,11 +2862,13 @@ npyiter_allocate_arrays(NpyIter *iter,
}
/* If the data will be written to, set UPDATEIFCOPY */
if (op_itflags[iop] & NPY_OP_ITFLAG_WRITE) {
+ /*
+ * Don't use PyArray_SetBase, because that compresses
+ * the chain of bases.
+ */
Py_INCREF(op[iop]);
- if (PyArray_SetBase(temp, (PyObject *)op[iop]) < 0) {
- Py_DECREF(temp);
- return 0;
- }
+ ((PyArrayObject_fieldaccess *)temp)->base =
+ (PyObject *)op[iop];
PyArray_ENABLEFLAGS(temp, NPY_ARRAY_UPDATEIFCOPY);
PyArray_CLEARFLAGS(op[iop], NPY_ARRAY_WRITEABLE);
}
diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py
index d0161b366..d7136db51 100644
--- a/numpy/core/tests/test_einsum.py
+++ b/numpy/core/tests/test_einsum.py
@@ -71,7 +71,8 @@ class TestEinSum(TestCase):
def test_einsum_views(self):
# pass-through
- a = np.arange(6).reshape(2,3)
+ a = np.arange(6)
+ a.shape = (2,3)
b = np.einsum("...", a)
assert_(b.base is a)
@@ -88,7 +89,8 @@ class TestEinSum(TestCase):
assert_equal(b, a)
# transpose
- a = np.arange(6).reshape(2,3)
+ a = np.arange(6)
+ a.shape = (2,3)
b = np.einsum("ji", a)
assert_(b.base is a)
@@ -99,7 +101,8 @@ class TestEinSum(TestCase):
assert_equal(b, a.T)
# diagonal
- a = np.arange(9).reshape(3,3)
+ a = np.arange(9)
+ a.shape = (3,3)
b = np.einsum("ii->i", a)
assert_(b.base is a)
@@ -110,7 +113,8 @@ class TestEinSum(TestCase):
assert_equal(b, [a[i,i] for i in range(3)])
# diagonal with various ways of broadcasting an additional dimension
- a = np.arange(27).reshape(3,3,3)
+ a = np.arange(27)
+ a.shape = (3,3,3)
b = np.einsum("...ii->...i", a)
assert_(b.base is a)
@@ -173,7 +177,8 @@ class TestEinSum(TestCase):
for x in a.transpose(1,0,2)])
# triple diagonal
- a = np.arange(27).reshape(3,3,3)
+ a = np.arange(27)
+ a.shape = (3,3,3)
b = np.einsum("iii->i", a)
assert_(b.base is a)
@@ -184,7 +189,8 @@ class TestEinSum(TestCase):
assert_equal(b, [a[i,i,i] for i in range(3)])
# swap axes
- a = np.arange(24).reshape(2,3,4)
+ a = np.arange(24)
+ a.shape = (2,3,4)
b = np.einsum("ijk->jik", a)
assert_(b.base is a)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 6821fbe49..03f1b10c6 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -1056,8 +1056,12 @@ class TestPutmask(object):
dtype=[('x', '<f8'), ('y', '>f8'), ('z', '<f8')])
np.putmask(rec['x'],[True,False],10)
assert_array_equal(rec['x'],[10,5])
- np.putmask(rec['y'],[True,False],10)
- assert_array_equal(rec['y'],[10,4])
+ assert_array_equal(rec['y'],[2,4])
+ assert_array_equal(rec['z'],[3,3])
+ np.putmask(rec['y'],[True,False],11)
+ assert_array_equal(rec['x'],[10,5])
+ assert_array_equal(rec['y'],[11,4])
+ assert_array_equal(rec['z'],[3,3])
def test_masked_array(self):
## x = np.array([1,2,3])
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 974a6d6f8..9117b9ac8 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -458,8 +458,8 @@ class TestUfunc(TestCase):
for s2 in slice_3:
a1 = d1.transpose(p1)[s1]
a2 = d2.transpose(p2)[s2]
- ref = ref and a1.base != None and a1.base.base != None
- ref = ref and a2.base != None and a2.base.base != None
+ ref = ref and a1.base != None
+ ref = ref and a2.base != None
if broadcastable(a1.shape[-1], a2.shape[-2]) and \
broadcastable(a1.shape[0], a2.shape[0]):
assert_array_almost_equal(