Skip to content

Commit 81caed6

Browse files
authored
Merge pull request #23746 from mattip/scalar-str
ENH: add fast path for str(scalar_int)
2 parents 25908ca + 5e983f2 commit 81caed6

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

benchmarks/benchmarks/bench_scalar.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,15 @@ def time_add_other_and_int32arr(self, typename):
6565
other + int32
6666
other + int32
6767
other + int32
68+
69+
70+
class ScalarStr(Benchmark):
71+
# Test scalar to str conversion
72+
params = [TYPES1]
73+
param_names = ["type"]
74+
75+
def setup(self, typename):
76+
self.a = np.array([100] * 100, dtype=typename)
77+
78+
def time_str_repr(self, typename):
79+
res = [str(x) for x in self.a]

numpy/core/src/multiarray/scalartypes.c.src

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,43 @@ static PyObject *
279279
genint_type_str(PyObject *self)
280280
{
281281
PyObject *item, *item_str;
282-
item = gentype_generic_method(self, NULL, NULL, "item");
282+
PyArray_Descr *descr = PyArray_DescrFromTypeObject((PyObject *)Py_TYPE(self));
283+
void *val = scalar_value(self, descr);
284+
switch (descr->type_num) {
285+
case NPY_BYTE:
286+
item = PyLong_FromLong(*(int8_t *)val);
287+
break;
288+
case NPY_UBYTE:
289+
item = PyLong_FromUnsignedLong(*(uint8_t *)val);
290+
break;
291+
case NPY_SHORT:
292+
item = PyLong_FromLong(*(int16_t *)val);
293+
break;
294+
case NPY_USHORT:
295+
item = PyLong_FromUnsignedLong(*(uint16_t *)val);
296+
break;
297+
case NPY_INT:
298+
item = PyLong_FromLong(*(int32_t *)val);
299+
break;
300+
case NPY_UINT:
301+
item = PyLong_FromUnsignedLong(*(uint32_t *)val);
302+
break;
303+
case NPY_LONG:
304+
item = PyLong_FromLong(*(int64_t *)val);
305+
break;
306+
case NPY_ULONG:
307+
item = PyLong_FromUnsignedLong(*(uint64_t *)val);
308+
break;
309+
case NPY_LONGLONG:
310+
item = PyLong_FromLongLong(*(long long *)val);
311+
break;
312+
case NPY_ULONGLONG:
313+
item = PyLong_FromUnsignedLongLong(*(unsigned long long *)val);
314+
break;
315+
default:
316+
item = gentype_generic_method(self, NULL, NULL, "item");
317+
break;
318+
}
283319
if (item == NULL) {
284320
return NULL;
285321
}

numpy/core/tests/test_arrayprint.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,7 @@ def _format_function(x):
258258
assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) ==
259259
'[abcabc defdef]')
260260

261-
262-
def test_structure_format(self):
261+
def test_structure_format_mixed(self):
263262
dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
264263
x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
265264
assert_equal(np.array2string(x),
@@ -301,6 +300,7 @@ def test_structure_format(self):
301300
( 'NaT',) ( 'NaT',) ( 'NaT',)]""")
302301
)
303302

303+
def test_structure_format_int(self):
304304
# See #8160
305305
struct_int = np.array([([1, -1],), ([123, 1],)], dtype=[('B', 'i4', 2)])
306306
assert_equal(np.array2string(struct_int),
@@ -310,6 +310,7 @@ def test_structure_format(self):
310310
assert_equal(np.array2string(struct_2dint),
311311
"[([[ 0, 1], [ 2, 3]],) ([[12, 0], [ 0, 0]],)]")
312312

313+
def test_structure_format_float(self):
313314
# See #8172
314315
array_scalar = np.array(
315316
(1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8'))

0 commit comments

Comments
 (0)