Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Lib/test/test_memoryview.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,27 @@ def test_array_assign(self):
m[:] = new_a
self.assertEqual(a, new_a)

def test_compare_equal(self):
# A memoryview is equal to itself: there is no need to compare
# individual values. This is not true for float values since they can
# be NaN, and NaN is not equal to itself.
for int_format in 'bBhHiIlLqQ':
with self.subTest(format=int_format):
a = array.array(int_format, [1, 2, 3])
m = memoryview(a)
self.assertTrue(m == m)

for float_format in 'fd':
with self.subTest(format=int_format):
a = array.array(float_format, [1.0, 2.0, float('nan')])
m = memoryview(a)
# nan is not equal to nan
self.assertFalse(m == m)

a = array.array(float_format, [1.0, 2.0, 3.0])
m = memoryview(a)
self.assertTrue(m == m)


class BytesMemorySliceTest(unittest.TestCase,
BaseMemorySliceTests, BaseBytesMemoryTests):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to
itself, there is no need to compare values. Patch by Victor Stinner.
23 changes: 23 additions & 0 deletions Objects/memoryobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3122,6 +3122,29 @@ memory_richcompare(PyObject *v, PyObject *w, int op)
}
vv = VIEW_ADDR(v);

// For formats supported by the struct module a memoryview is equal to
// itself: there is no need to compare individual values.
// This is not true for float values since they can be NaN, and NaN
// is not equal to itself. So only use this optimization on format known to
// not use floats.
if (v == w) {
int can_compare_ptr;
const char *format = vv->format;
if (format != NULL) {
// Include only formats known by struct, exclude formats "d" (double),
// "f" (float), "e" (16-bit float) and "P" (void*)
can_compare_ptr = (strchr("bBchHiIlLnNqQ?", format[0]) != NULL
&& format[1] == 0);
}
else {
can_compare_ptr = 1;
}
if (can_compare_ptr) {
equal = 1;
goto result;
}
}

if (PyMemoryView_Check(w)) {
if (BASE_INACCESSIBLE(w)) {
equal = (v == w);
Expand Down
Loading