Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 56b5f27

Browse files
committed
Merge pull request #4856 from juliantaylor/elide-testcases
TST: add temporary elision testcases
2 parents aba6adb + 2e83a5d commit 56b5f27

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

numpy/core/src/multiarray/multiarray_tests.c.src

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,42 @@ fail:
556556
return NULL;
557557
}
558558

559+
/* check no elison for avoided increfs */
560+
static PyObject *
561+
incref_elide(PyObject *dummy, PyObject *args)
562+
{
563+
PyObject *arg = NULL, *res, *tup;
564+
if (!PyArg_ParseTuple(args, "O", &arg)) {
565+
return NULL;
566+
}
567+
568+
/* refcount 1 array but should not be elided */
569+
arg = PyArray_NewCopy((PyArrayObject*)arg, NPY_KEEPORDER);
570+
res = PyNumber_Add(arg, arg);
571+
572+
/* return original copy, should be equal to input */
573+
tup = PyTuple_Pack(2, arg, res);
574+
Py_DECREF(arg);
575+
Py_DECREF(res);
576+
return tup;
577+
}
578+
579+
/* check no elison for get from list without incref */
580+
static PyObject *
581+
incref_elide_l(PyObject *dummy, PyObject *args)
582+
{
583+
PyObject *arg = NULL, *r, *res;
584+
if (!PyArg_ParseTuple(args, "O", &arg)) {
585+
return NULL;
586+
}
587+
/* get item without increasing refcount, item may still be on the python
588+
* stack but above the inaccessible top */
589+
r = PyList_GetItem(arg, 4);
590+
res = PyNumber_Add(r, r);
591+
592+
return res;
593+
}
594+
559595

560596
#if !defined(NPY_PY3K)
561597
static PyObject *
@@ -839,6 +875,12 @@ static PyMethodDef Multiarray_TestsMethods[] = {
839875
{"test_inplace_increment",
840876
inplace_increment,
841877
METH_VARARGS, NULL},
878+
{"incref_elide",
879+
incref_elide,
880+
METH_VARARGS, NULL},
881+
{"incref_elide_l",
882+
incref_elide_l,
883+
METH_VARARGS, NULL},
842884
#if !defined(NPY_PY3K)
843885
{"test_int_subclass",
844886
int_subclass,

numpy/core/tests/test_multiarray.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,66 @@ def test_ravel(self):
16951695

16961696

16971697
class TestBinop(object):
1698+
def test_inplace(self):
1699+
# test refcount 1 inplace conversion
1700+
assert_array_almost_equal(np.array([0.5]) * np.array([1.0, 2.0]),
1701+
[0.5, 1.0])
1702+
1703+
d = np.array([0.5, 0.5])[::2]
1704+
assert_array_almost_equal(d * (d * np.array([1.0, 2.0])),
1705+
[0.25, 0.5])
1706+
1707+
a = np.array([0.5])
1708+
b = np.array([0.5])
1709+
c = a + b
1710+
c = a - b
1711+
c = a * b
1712+
c = a / b
1713+
assert_equal(a, b)
1714+
assert_almost_equal(c, 1.)
1715+
1716+
c = a + b * 2. / b * a - a / b
1717+
assert_equal(a, b)
1718+
assert_equal(c, 0.5)
1719+
1720+
# true divide
1721+
a = np.array([5])
1722+
b = np.array([3])
1723+
c = (a * a) / b
1724+
1725+
assert_almost_equal(c, 25 / 3)
1726+
assert_equal(a, 5)
1727+
assert_equal(b, 3)
1728+
1729+
def test_extension_incref_elide(self):
1730+
# test extension (e.g. cython) calling PyNumber_* slots without
1731+
# increasing the reference counts
1732+
#
1733+
# def incref_elide(a):
1734+
# d = input.copy() # refcount 1
1735+
# return d, d + d # PyNumber_Add without increasing refcount
1736+
from numpy.core.multiarray_tests import incref_elide
1737+
d = np.ones(5)
1738+
orig, res = incref_elide(d)
1739+
# the return original should not be changed to an inplace operation
1740+
assert_array_equal(orig, d)
1741+
assert_array_equal(res, d + d)
1742+
1743+
def test_extension_incref_elide_stack(self):
1744+
# scanning if the refcount == 1 object is on the python stack to check
1745+
# that we are called directly from python is flawed as object may still
1746+
# be above the stack pointer and we have no access to the top of it
1747+
#
1748+
# def incref_elide_l(d):
1749+
# return l[4] + l[4] # PyNumber_Add without increasing refcount
1750+
from numpy.core.multiarray_tests import incref_elide_l
1751+
# padding with 1 makes sure the object on the stack is not overwriten
1752+
l = [1, 1, 1, 1, np.ones(5)]
1753+
res = incref_elide_l(l)
1754+
# the return original should not be changed to an inplace operation
1755+
assert_array_equal(l[4], np.ones(5))
1756+
assert_array_equal(res, l[4] + l[4])
1757+
16981758
def test_ufunc_override_rop_precedence(self):
16991759
# Check that __rmul__ and other right-hand operations have
17001760
# precedence over __numpy_ufunc__

0 commit comments

Comments
 (0)