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':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can "?" be tested? Can format starting with "@" be tested? Can the null format be tested?

with self.subTest(format=int_format):
a = array.array(int_format, [1, 2, 3])
m = memoryview(a)
self.assertTrue(m == m)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test also !=.


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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test also !=.


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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that format can starts with "@".

&& 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