Skip to content

Commit 6b954aa

Browse files
sebergcharris
authored andcommitted
BUG,MAINT: Remove incorrect special case in string to number casts
The string to number casts fall back to using the scalars and the type setitem function to do the cast. However, before calling setitem, they sometimes already called the Python function for string coercion. This is unnecessary. Closes gh-15608
1 parent f314998 commit 6b954aa

2 files changed

Lines changed: 24 additions & 79 deletions

File tree

‎numpy/core/src/multiarray/arraytypes.c.src‎

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,16 +1527,8 @@ OBJECT_to_@TOTYPE@(void *input, void *output, npy_intp n,
15271527
* #oskip = 1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
15281528
* 1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
15291529
* 1*18,(PyArray_DESCR(aop)->elsize)*3,1*2#
1530-
* #convert = 1*18, 0*3, 1*2,
1531-
* 1*18, 0*3, 1*2,
1532-
* 0*23#
1533-
* #convstr = (Int*9, Long*2, Float*4, Complex*3, Tuple*3, Long*2)*3#
15341530
*/
15351531

1536-
#if @convert@
1537-
1538-
#define IS_@from@
1539-
15401532
static void
15411533
@from@_to_@to@(void *input, void *output, npy_intp n,
15421534
void *vaip, void *aop)
@@ -1550,41 +1542,10 @@ static void
15501542
int oskip = @oskip@;
15511543

15521544
for (i = 0; i < n; i++, ip+=skip, op+=oskip) {
1553-
PyObject *new;
15541545
PyObject *temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
15551546
if (temp == NULL) {
15561547
return;
15571548
}
1558-
1559-
#if defined(NPY_PY3K) && defined(IS_STRING)
1560-
/* Work around some Python 3K */
1561-
new = PyUnicode_FromEncodedObject(temp, "ascii", "strict");
1562-
Py_DECREF(temp);
1563-
temp = new;
1564-
if (temp == NULL) {
1565-
return;
1566-
}
1567-
#endif
1568-
/* convert from Python object to needed one */
1569-
{
1570-
PyObject *args;
1571-
1572-
/* call out to the Python builtin given by convstr */
1573-
args = Py_BuildValue("(N)", temp);
1574-
#if defined(NPY_PY3K)
1575-
#define PyInt_Type PyLong_Type
1576-
#endif
1577-
new = Py@convstr@_Type.tp_new(&Py@convstr@_Type, args, NULL);
1578-
#if defined(NPY_PY3K)
1579-
#undef PyInt_Type
1580-
#endif
1581-
Py_DECREF(args);
1582-
temp = new;
1583-
if (temp == NULL) {
1584-
return;
1585-
}
1586-
}
1587-
15881549
if (@to@_setitem(temp, op, aop)) {
15891550
Py_DECREF(temp);
15901551
return;
@@ -1593,36 +1554,6 @@ static void
15931554
}
15941555
}
15951556

1596-
#undef IS_@from@
1597-
1598-
#else
1599-
1600-
static void
1601-
@from@_to_@to@(void *input, void *output, npy_intp n,
1602-
void *vaip, void *aop)
1603-
{
1604-
@fromtyp@ *ip = input;
1605-
@totyp@ *op = output;
1606-
PyArrayObject *aip = vaip;
1607-
1608-
npy_intp i;
1609-
int skip = PyArray_DESCR(aip)->elsize;
1610-
int oskip = @oskip@;
1611-
1612-
for (i = 0; i < n; i++, ip+=skip, op+=oskip) {
1613-
PyObject *temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
1614-
if (temp == NULL) {
1615-
return;
1616-
}
1617-
if (@to@_setitem(temp, op, aop)) {
1618-
Py_DECREF(temp);
1619-
return;
1620-
}
1621-
Py_DECREF(temp);
1622-
}
1623-
}
1624-
1625-
#endif
16261557

16271558
/**end repeat**/
16281559

‎numpy/core/tests/test_longdouble.py‎

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,36 @@ def test_repr_roundtrip():
3939
assert_equal(np.longdouble(repr(o)), o, "repr was %s" % repr(o))
4040

4141

42-
def test_unicode():
43-
np.longdouble(u"1.2")
42+
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
43+
def test_repr_roundtrip_bytes():
44+
o = 1 + LD_INFO.eps
45+
assert_equal(np.longdouble(repr(o).encode("ascii")), o)
4446

4547

46-
def test_string():
47-
np.longdouble("1.2")
48+
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
49+
@pytest.mark.parametrize("strtype", (np.str_, np.bytes_, str, bytes))
50+
def test_array_and_stringlike_roundtrip(strtype):
51+
"""
52+
Test that string representations of long-double roundtrip both
53+
for array casting and scalar coercion, see also gh-15608.
54+
"""
55+
o = 1 + LD_INFO.eps
4856

57+
if strtype in (np.bytes_, bytes):
58+
o_str = strtype(repr(o).encode("ascii"))
59+
else:
60+
o_str = strtype(repr(o))
4961

50-
def test_bytes():
51-
np.longdouble(b"1.2")
62+
# Test that `o` is correctly coerced from the string-like
63+
assert o == np.longdouble(o_str)
5264

65+
# Test that arrays also roundtrip correctly:
66+
o_strarr = np.asarray([o] * 3, dtype=strtype)
67+
assert (o == o_strarr.astype(np.longdouble)).all()
5368

54-
@pytest.mark.skipif(string_to_longdouble_inaccurate, reason="Need strtold_l")
55-
def test_repr_roundtrip_bytes():
56-
o = 1 + LD_INFO.eps
57-
assert_equal(np.longdouble(repr(o).encode("ascii")), o)
69+
# And array coercion and casting to string give the same as scalar repr:
70+
assert (o_strarr == o_str).all()
71+
assert (np.asarray([o] * 3).astype(strtype) == o_str).all()
5872

5973

6074
def test_bogus_string():

0 commit comments

Comments
 (0)