Skip to content

Commit 2294542

Browse files
committed
gh-144995: Optimize memoryview == memoryview
1 parent e84a2cc commit 2294542

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

Lib/test/test_memoryview.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,27 @@ def test_array_assign(self):
575575
m[:] = new_a
576576
self.assertEqual(a, new_a)
577577

578+
def test_compare_equal(self):
579+
# A memoryview is equal to itself: there is no need to compare
580+
# individual values. This is not true for float values since they can
581+
# be NaN, and NaN is not equal to itself.
582+
for int_format in 'bBhHiIlLqQ':
583+
with self.subTest(format=int_format):
584+
a = array.array(int_format, [1, 2, 3])
585+
m = memoryview(a)
586+
self.assertTrue(m == m)
587+
588+
for float_format in 'fd':
589+
with self.subTest(format=int_format):
590+
a = array.array(float_format, [1.0, 2.0, float('nan')])
591+
m = memoryview(a)
592+
# nan is not equal to nan
593+
self.assertFalse(m == m)
594+
595+
a = array.array(float_format, [1.0, 2.0, 3.0])
596+
m = memoryview(a)
597+
self.assertTrue(m == m)
598+
578599

579600
class BytesMemorySliceTest(unittest.TestCase,
580601
BaseMemorySliceTests, BaseBytesMemoryTests):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to
2+
itself, there is no need to compare values. Patch by Victor Stinner.

Objects/memoryobject.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,25 @@ cmp_rec(const char *p, const char *q,
31013101
return 1;
31023102
}
31033103

3104+
static int
3105+
is_float_format(const char *format)
3106+
{
3107+
if (format == NULL) {
3108+
return 0;
3109+
}
3110+
if (strcmp("d", format) == 0) {
3111+
return 1;
3112+
}
3113+
if (strcmp("f", format) == 0) {
3114+
return 1;
3115+
}
3116+
if (strcmp("e", format) == 0) {
3117+
return 1;
3118+
}
3119+
return 0;
3120+
}
3121+
3122+
31043123
static PyObject *
31053124
memory_richcompare(PyObject *v, PyObject *w, int op)
31063125
{
@@ -3122,6 +3141,14 @@ memory_richcompare(PyObject *v, PyObject *w, int op)
31223141
}
31233142
vv = VIEW_ADDR(v);
31243143

3144+
// A memoryview is equal to itself: there is no need to compare individual
3145+
// values. This is not true for float values since they can be NaN, and NaN
3146+
// is not equal to itself.
3147+
if (v == w && !is_float_format(vv->format)) {
3148+
equal = 1;
3149+
goto result;
3150+
}
3151+
31253152
if (PyMemoryView_Check(w)) {
31263153
if (BASE_INACCESSIBLE(w)) {
31273154
equal = (v == w);

0 commit comments

Comments
 (0)