Skip to content

Commit

Permalink
Merge 059d559 into 69c459f
Browse files Browse the repository at this point in the history
  • Loading branch information
dtomas committed Nov 16, 2017
2 parents 69c459f + 059d559 commit 7551409
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 6 deletions.
104 changes: 103 additions & 1 deletion performance_suites/pmap.py
Expand Up @@ -163,4 +163,106 @@ def iteration_large_pmap():
@Benchmarked(setup=_large_dict)
def reference_iteration_large_dict():
for k in large_dict:
pass
pass


# #################### Comparison ########################

def _different_pmaps_same_size():
pmap1 = pmap(dict((i, i) for i in range(2000)))
pmap2 = pmap(dict((i, i + 1) for i in range(2000)))


def _different_pmaps_different_size():
pmap1 = pmap(dict((i, i) for i in range(2000)))
pmap2 = pmap(dict((i, i + 1) for i in range(1500)))


def _equal_pmaps():
pmap1 = pmap(dict((i, i) for i in range(2000)))
pmap2 = pmap(dict((i, i) for i in range(2000)))


def _equal_pmap_and_dict():
dict1 = dict((i, i) for i in range(2000))
pmap1 = pmap(dict((i, i) for i in range(2000)))


def _equal_dicts():
dict1 = dict((i, i) for i in range(2000))
dict2 = dict((i, i) for i in range(2000))


def _different_dicts_same_size():
dict1 = dict((i, i) for i in range(2000))
dict2 = dict((i, i + 1) for i in range(2000))


def _different_dicts_different_size():
dict1 = dict((i, i) for i in range(2000))
dict2 = dict((i, i + 1) for i in range(2000))


def _equal_pmaps_different_bucket_size():
pmap1 = pmap(dict((i, i) for i in range(2000)), 1999)
pmap2 = pmap(dict((i, i) for i in range(2000)), 2000)


def _equal_pmaps_same_bucket_size_different_insertion_order():
pmap1 = pmap([(i, i) for i in range(2000)], 1999)
pmap2 = pmap([(i, i) for i in range(1999, -1, -1)], 1999)


@Benchmarked(setup=_large_pmap)
def compare_same_pmap():
large_pmap == large_pmap


@Benchmarked(setup=_large_dict)
def reference_compare_same_dict():
large_dict == large_dict


@Benchmarked(setup=_equal_pmaps)
def compare_equal_pmaps():
pmap1 == pmap2


@Benchmarked(setup=_equal_dicts)
def reference_compare_equal_dicts():
dict1 == dict2


@Benchmarked(setup=_equal_pmap_and_dict)
def compare_equal_pmap_and_dict():
pmap1 == dict1


@Benchmarked(setup=_equal_pmaps_same_bucket_size_different_insertion_order)
def compare_equal_pmaps_different_insertion_order():
pmap1 == pmap2


@Benchmarked(setup=_equal_pmaps_different_bucket_size)
def compare_equal_pmaps_different_bucket_size():
pmap1 == pmap2


@Benchmarked(setup=_different_pmaps_same_size)
def compare_different_pmaps_same_size():
pmap1 == pmap2


@Benchmarked(setup=_different_dicts_same_size)
def reference_compare_different_dicts_same_size():
dict1 == dict2


@Benchmarked(setup=_different_pmaps_different_size)
def compare_different_pmaps_different_size():
pmap1 == pmap2


@Benchmarked(setup=_different_dicts_different_size)
def reference_compare_different_dicts_different_size():
dict1 == dict2
10 changes: 10 additions & 0 deletions pvectorcmodule.c
Expand Up @@ -365,6 +365,16 @@ static PyObject* PVector_richcompare(PyObject *v, PyObject *w, int op) {
vlen = vt->count;
wlen = wt->count;

if (vlen != wlen) {
if (op == Py_EQ) {
Py_INCREF(Py_False);
return Py_False;
} else if (op == Py_NE) {
Py_INCREF(Py_True);
return Py_True;
}
}

/* Search for the first index where items are different. */
PyObject *left = NULL;
PyObject *right = NULL;
Expand Down
19 changes: 18 additions & 1 deletion pyrsistent/_pmap.py
Expand Up @@ -125,7 +125,24 @@ def __len__(self):
def __repr__(self):
return 'pmap({0})'.format(str(dict(self)))

__eq__ = Mapping.__eq__
def __eq__(self, other):
if self is other:
return True
if not isinstance(other, Mapping):
return NotImplemented
if len(self) != len(other):
return False
if isinstance(other, PMap):
if (hasattr(self, '_cached_hash') and hasattr(other, '_cached_hash')
and self._cached_hash != other._cached_hash):
return False
if self._buckets == other._buckets:
return True
return dict(self.iteritems()) == dict(other.iteritems())
elif isinstance(other, dict):
return dict(self.iteritems()) == other
return dict(self.iteritems()) == dict(six.iteritems(other))

__ne__ = Mapping.__ne__

def __lt__(self, other):
Expand Down
72 changes: 68 additions & 4 deletions tests/map_test.py
Expand Up @@ -117,13 +117,11 @@ def test_overwrite_existing_element():
assert map2['a'] == 3


def test_supports_hash_and_equals():
def test_hash():
x = m(a=1, b=2, c=3)
y = m(a=1, b=2, c=3)

assert hash(x) == hash(y)
assert x == y
assert not (x != y)


def test_same_hash_when_content_the_same_but_underlying_vector_size_differs():
Expand Down Expand Up @@ -156,6 +154,72 @@ def test_map_does_not_hash_values_on_second_hash_invocation():
hash(x)


def test_equal():
x = m(a=1, b=2, c=3)
y = m(a=1, b=2, c=3)

assert x == y
assert not (x != y)

assert y == x
assert not (y != x)


def test_equal_to_dict():
x = m(a=1, b=2, c=3)
y = dict(a=1, b=2, c=3)

assert x == y
assert not (x != y)

assert y == x
assert not (y != x)


def test_equal_with_different_bucket_sizes():
x = pmap({'a': 1, 'b': 2}, 50)
y = pmap({'a': 1, 'b': 2}, 10)

assert x == y
assert not (x != y)

assert y == x
assert not (y != x)


def test_equal_with_different_insertion_order():
x = pmap([(i, i) for i in range(50)], 10)
y = pmap([(i, i) for i in range(49, -1, -1)], 10)

assert x == y
assert not (x != y)

assert y == x
assert not (y != x)


def test_not_equal():
x = m(a=1, b=2, c=3)
y = m(a=1, b=2)

assert x != y
assert not (x == y)

assert y != x
assert not (y == x)


def test_not_equal_to_dict():
x = m(a=1, b=2, c=3)
y = dict(a=1, b=2, d=4)

assert x != y
assert not (x == y)

assert y != x
assert not (y == x)


def test_update_with_multiple_arguments():
# If same value is present in multiple sources, the rightmost is used.
x = m(a=1, b=2, c=3)
Expand Down

0 comments on commit 7551409

Please sign in to comment.