Ticket #14254: 14254_signed_id.patch

File 14254_signed_id.patch, 6.0 KB (added by jdemeyer, 7 years ago)
  • sage/categories/homset.py

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1363013396 -3600
    # Node ID 8b20a357824aec78a8465200b416824f9c7aef00
    # Parent  6400f8af57137e6d53f4d4462161c88cfbe6643c
    Add a signed_id() function returning an "id" as Py_ssize_t
    
    diff --git a/sage/categories/homset.py b/sage/categories/homset.py
    a b  
    7676# introduced in trac ticket #715
    7777
    7878from weakref import KeyedRef
    79 from sage.structure.coerce_dict import TripleDict
     79from sage.structure.coerce_dict import signed_id, TripleDict
    8080_cache = TripleDict(53)
    8181
    8282def Hom(X, Y, category=None):
     
    263263    H = category.hom_category().parent_class(X, Y, category = category)
    264264           
    265265    ##_cache[key] = weakref.ref(H)
    266     _cache[key] = KeyedRef(H, _cache.eraser, (id(X),id(Y),id(category)))
     266    _cache[key] = KeyedRef(H, _cache.eraser, (signed_id(X),signed_id(Y),signed_id(category)))
    267267    return H
    268268
    269269def hom(X, Y, f):
  • sage/structure/coerce_dict.pyx

    diff --git a/sage/structure/coerce_dict.pyx b/sage/structure/coerce_dict.pyx
    a b  
    4444    PyObject* PyWeakref_GetObject(object ref)
    4545    PyObject* Py_None
    4646
     47cpdef inline Py_ssize_t signed_id(x):
     48    """
     49    A function like Python's :func:`id` returning *signed* integers,
     50    which are guaranteed to fit in a ``Py_ssize_t``.
     51
     52    Theoretically, there is no guarantee that two different Python
     53    objects have different ``signed_id()`` values. However, under the
     54    mild assumption that a C pointer fits in a ``Py_ssize_t``, this
     55    is guaranteed.
     56
     57    TESTS::
     58
     59        sage: a = 1.23e45  # some object
     60        sage: from sage.structure.coerce_dict import signed_id
     61        sage: s = signed_id(a)
     62        sage: id(a) == s or id(a) == s + 2**32 or id(a) == s + 2**64
     63        True
     64        sage: signed_id(a) <= sys.maxsize
     65        True
     66    """
     67    return <Py_ssize_t><void *>(x)
     68
    4769import gc
    4870
    4971############################################
    5072# A note about how to store "id" keys in python structures:
    5173#
    52 # In python a "pointer length integer" (size_t) normally, is encoded
    53 # as a *signed* integer, of type Py_ssize_t. This has an advantage in that
    54 # if the value gets encoded as a *python integer* it can do so in a sign-preserving
    55 # way and still make use of all the bits that python offers to store (small) integers.
     74# We use the type Py_ssize_t to store "id"s generated by the signed_id
     75# function defined above. Assuming that Py_ssize_t is the same as a C
     76# long (which is true on most Unix-like systems), this also has the
     77# advantage that these Py_ssize_t values are stored as a Python "int"
     78# (as opposed to "long"), which allow for fast conversion to/from C
     79# types.
    5680#
    5781# There is one place where we have to be careful about signs:
    5882# Our hash values most naturally live in Py_ssize_t. We convert those into
     
    6084# However, the modulo operator in C preserves the sign of the number we take the
    6185# modulus of, which is not what we want.
    6286# The solution is to always do
    63 # (<size_t) h)% modulus
     87# (<size_t> h) % modulus
    6488# to ensure we're doing an unsigned modulus.
    6589
    6690############################################
     
    528552            sage: 15 in L
    529553            False
    530554        """
    531         cdef Py_ssize_t h = <Py_ssize_t><void *>k
     555        cdef Py_ssize_t h = signed_id(k)
    532556        cdef Py_ssize_t i
    533557        cdef list all_buckets = self.buckets
    534558        cdef list bucket = <object>PyList_GET_ITEM(all_buckets, (<size_t>h)% PyList_GET_SIZE(all_buckets))
     
    571595        return self.get(k)
    572596
    573597    cdef get(self, object k):
    574         cdef Py_ssize_t h =<Py_ssize_t><void *>k
     598        cdef Py_ssize_t h = signed_id(k)
    575599        cdef Py_ssize_t i
    576600        cdef list all_buckets = self.buckets
    577601        cdef list bucket = <object>PyList_GET_ITEM(all_buckets, (<size_t>h) % PyList_GET_SIZE(all_buckets))
     
    608632    cdef set(self,object k, value):
    609633        if self.threshold and self._size > len(self.buckets) * self.threshold:
    610634            self.resize()
    611         cdef Py_ssize_t h = <Py_ssize_t><void *>k
     635        cdef Py_ssize_t h = signed_id(k)
    612636        cdef Py_ssize_t i
    613637        cdef list bucket = <object>PyList_GET_ITEM(self.buckets,(<size_t> h) % PyList_GET_SIZE(self.buckets))
    614638        cdef object r
     
    679703            sage: a in L
    680704            False
    681705        """
    682         cdef Py_ssize_t h = <Py_ssize_t><void *>k
     706        cdef Py_ssize_t h = signed_id(k)
    683707        cdef object r
    684708        cdef Py_ssize_t i
    685709        cdef object tmp
     
    11011125        return self.get(k1, k2, k3)
    11021126
    11031127    cdef get(self, object k1, object k2, object k3):
    1104         cdef Py_ssize_t h1 = <Py_ssize_t><void *>k1
    1105         cdef Py_ssize_t h2 = <Py_ssize_t><void *>k2
    1106         cdef Py_ssize_t h3 = <Py_ssize_t><void *>k3
     1128        cdef Py_ssize_t h1 = signed_id(k1)
     1129        cdef Py_ssize_t h2 = signed_id(k2)
     1130        cdef Py_ssize_t h3 = signed_id(k3)
    11071131        cdef Py_ssize_t h = (h1 + 13*h2 ^ 503*h3)
    11081132
    11091133        cdef object r1,r2,r3
     
    11491173    cdef set(self, object k1, object k2, object k3, value):
    11501174        if self.threshold and self._size > len(self.buckets) * self.threshold:
    11511175            self.resize()
    1152         cdef Py_ssize_t h1 = <Py_ssize_t><void *>k1
    1153         cdef Py_ssize_t h2 = <Py_ssize_t><void *>k2
    1154         cdef Py_ssize_t h3 = <Py_ssize_t><void *>k3
     1176        cdef Py_ssize_t h1 = signed_id(k1)
     1177        cdef Py_ssize_t h2 = signed_id(k2)
     1178        cdef Py_ssize_t h3 = signed_id(k3)
    11551179        cdef Py_ssize_t h = (h1 + 13*h2 ^ 503*h3)
    11561180
    11571181        cdef object r1,r2,r3
     
    12341258            k1, k2, k3 = k
    12351259        except (TypeError,ValueError):
    12361260            raise KeyError, k
    1237         cdef Py_ssize_t h1 = <Py_ssize_t><void *>k1
    1238         cdef Py_ssize_t h2 = <Py_ssize_t><void *>k2
    1239         cdef Py_ssize_t h3 = <Py_ssize_t><void *>k3
     1261        cdef Py_ssize_t h1 = signed_id(k1)
     1262        cdef Py_ssize_t h2 = signed_id(k2)
     1263        cdef Py_ssize_t h3 = signed_id(k3)
    12401264        cdef Py_ssize_t h = (h1 + 13*h2 ^ 503*h3)
    12411265
    12421266        cdef Py_ssize_t i