Skip to content

Commit

Permalink
Trac #18215: Huge speed up for hash of quadratic number field elements
Browse files Browse the repository at this point in the history
Before
{{{
sage: L.<a> = QuadraticField(-7)
sage: b = a - 13/7
sage: timeit("hash(b)")
625 loops, best of 3: 54 µs per loop
}}}
After
{{{
sage: L.<a> = QuadraticField(-7)
sage: b = a - 13/7
sage: timeit("hash(b)")
625 loops, best of 3: 97.7 ns per loop
}}}
... looks like a x500 speed up :-)

As a consequence (and with #18213 applied)
Before
{{{
sage: %time gr = polytopes.great_rhombicuboctahedron()
CPU times: user 5.68 s, sys: 68 ms, total: 5.75 s
Wall time: 5.7 s
}}}
After
{{{
sage: %time gr = polytopes.great_rhombicuboctahedron()
CPU times: user 2.71 s, sys: 36 ms, total: 2.75 s
Wall time: 2.69 s
}}}

See also: #18226

URL: http://trac.sagemath.org/18215
Reported by: vdelecroix
Ticket author(s): Vincent Delecroix
Reviewer(s): Nathann Cohen
  • Loading branch information
Release Manager authored and vbraun committed Apr 18, 2015
2 parents 4f541c8 + bee81ef commit 89e53e6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
15 changes: 8 additions & 7 deletions src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,24 +933,25 @@ def _conjugacy_representatives(self, max_block_length=ZZ(0), D=None):
[((4, 1), (3, 1)), ((2, 2),), ((3, 2),), ((3, 1), (1, 1)), ((4, 1), (1, 1)), ((4, 1), (2, 1)), ((3, 1), (2, 1)), ((2, 1), (1, 1))]
sage: [key for key in G._conj_prim]
[0, 15*lam + 6, 33*lam + 21, 9*lam + 5, 7*lam + 6, lam - 3, -4, 4*lam]
[0, lam - 3, 15*lam + 6, 7*lam + 6, 4*lam, 9*lam + 5, 33*lam + 21, -4]
sage: for key in G._conj_prim: print G._conj_prim[key]
[[V(4)]]
[[U], [U]]
[[V(1)*V(3)], [V(2)*V(4)]]
[[V(2)*V(3)]]
[[V(3)*V(4)], [V(1)*V(2)]]
[[V(1)*V(4)]]
[[U], [U]]
[[S], [S]]
[[V(3)], [V(2)]]
[[V(3)*V(4)], [V(1)*V(2)]]
[[V(2)*V(3)]]
[[S], [S]]
sage: [key for key in G._conj_nonprim]
[32*lam + 16, lam - 3, -lam - 2]
[lam - 3, 32*lam + 16, -lam - 2]
sage: for key in G._conj_nonprim: print G._conj_nonprim[key]
[[V(2)^2], [V(3)^2]]
[[U^(-1)], [U^(-1)]]
[[V(2)^2], [V(3)^2]]
[[U^(-2)], [U^2], [U^(-2)], [U^2]]
sage: G.element_repr_method("default")
"""

Expand Down
41 changes: 34 additions & 7 deletions src/sage/rings/number_field/number_field_element_quadratic.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ from sage.rings.number_field.number_field_element import _inverse_mod_generic

import number_field


from sage.libs.gmp.pylong cimport mpz_pythonhash

# TODO: this doesn't belong here, but robert thinks it would be nice
# to have globally available....
#
Expand Down Expand Up @@ -1298,17 +1301,41 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute):

def __hash__(self):
"""
Return hash of this number field element, which is just the
hash of the underlying polynomial.
Return hash of this number field element.
EXAMPLE::
For elements in `\ZZ` or `\QQ` the hash coincides with the one in the
native `\ZZ` or `\QQ`.
EXAMPLES::
sage: L.<a> = QuadraticField(-7)
sage: hash(a)
1505322287 # 32-bit
15360174650385711 # 64-bit
"""
return hash(self.polynomial())
42082631
sage: hash(L(1))
1
sage: hash(L(-3))
-3
sage: hash(L(-32/118))
-53
sage: hash(-32/118)
-53
"""
# 1. compute the hash of a/denom as if it was a rational
# (see the corresponding code in sage/rings/rational.pyx)
cdef long a_hash = mpz_pythonhash(self.a)
cdef long d_hash = mpz_pythonhash(self.denom)
if d_hash != 1:
a_hash ^= d_hash
if a_hash == -1:
a_hash == -2

# 2. mix them together with b
a_hash += 42082631 * mpz_pythonhash(self.b)
if a_hash == -1:
return -2
return a_hash


def __nonzero__(self):
Expand Down

0 comments on commit 89e53e6

Please sign in to comment.