Ticket #715: trac_715-modulo.patch

File trac_715-modulo.patch, 5.3 KB (added by jpflori, 8 years ago)

C modulo operator

  • sage/structure/coerce_dict.pyx

    # HG changeset patch
    # User Jean-Pierre Flori <jean-pierre.flor@ssi.gouv.fr>
    # Date 1334152948 -7200
    # Node ID 526c2d3fd326668b7462015f58fc0f80718ed51c
    # Parent  93441f72762981dddd4991ba23ff46cd9a98aafa
    #715: the C % operator can return negative results.
    
    diff --git a/sage/structure/coerce_dict.pyx b/sage/structure/coerce_dict.pyx
    a b  
    9999        # We remove that unique triple from self.D
    100100        cdef Py_ssize_t k1,k2,k3
    101101        k1,k2,k3 = r.key
    102         cdef int h = (k1 + 13*k2 ^ 503*k3) % PyList_GET_SIZE(self.D.buckets)
    103         cdef list bucket = <object>PyList_GET_ITEM(self.D.buckets,h)
     102        cdef Py_ssize_t h = (k1 + 13*k2 ^ 503*k3)
     103        # Beware that the C "%" operator returns negative values if the input
     104        # is negative, which is not the case of the Python "%" operator
     105        if h < 0: h = -h
     106        h = h % PyList_GET_SIZE(self.D.buckets)
     107        cdef list bucket = <object>PyList_GET_ITEM(self.D.buckets, h)
    104108        cdef int i
    105109        for i from 0 <= i < PyList_GET_SIZE(bucket) by 4:
    106             if <Py_ssize_t><object>PyList_GET_ITEM(bucket,i)==k1 and \
    107                <Py_ssize_t><object>PyList_GET_ITEM(bucket,i+1)==k2 and \
    108                <Py_ssize_t><object>PyList_GET_ITEM(bucket,i+2)==k3:
     110            if <Py_ssize_t><object>PyList_GET_ITEM(bucket, i)==k1 and \
     111               <Py_ssize_t><object>PyList_GET_ITEM(bucket, i+1)==k2 and \
     112               <Py_ssize_t><object>PyList_GET_ITEM(bucket, i+2)==k3:
    109113                del bucket[i:i+4]
    110114                self.D._size -= 1
    111115                break
     
    352356        except (TypeError,ValueError):
    353357            raise KeyError, k
    354358        return self.get(k1, k2, k3)
    355            
     359       
    356360    cdef get(self, object k1, object k2, object k3):
    357361        cdef Py_ssize_t h = (<Py_ssize_t><void *>k1 + 13*<Py_ssize_t><void *>k2 ^ 503*<Py_ssize_t><void *>k3)
    358         #if h < 0: h = -h  # shouldn't "%" result in a positive number anyway?
     362        # Beware that the C "%" operator returns negative values if the input
     363        # is negative, which is not the case of the Python "%" operator
     364        if h < 0: h = -h
    359365        cdef Py_ssize_t i
    360366        cdef list all_buckets = self.buckets
    361         cdef list bucket = <object>PyList_GET_ITEM(all_buckets, h % PyList_GET_SIZE(all_buckets))
     367        h = h % PyList_GET_SIZE(all_buckets)
     368        cdef list bucket = <object>PyList_GET_ITEM(all_buckets, h)
    362369        cdef object tmp
    363370        for i from 0 <= i < PyList_GET_SIZE(bucket) by 4:
    364371            tmp = <object>PyList_GET_ITEM(bucket, i)
     
    396403        cdef Py_ssize_t h3 = <Py_ssize_t><void *>k3
    397404       
    398405        cdef Py_ssize_t h = (h1 + 13*h2 ^ 503*h3)
    399         #if h < 0: h = -h   # shouldn't "%" return a positive number anyway?
     406        # Beware that the C "%" operator returns negative values if the input
     407        # is negative, which is not the case of the Python "%" operator
     408        if h < 0: h = -h
     409        h = h % PyList_GET_SIZE(self.buckets)
    400410        cdef Py_ssize_t i
    401         cdef list bucket = <object>PyList_GET_ITEM(self.buckets, h % PyList_GET_SIZE(self.buckets))
     411        cdef list bucket = <object>PyList_GET_ITEM(self.buckets, h)
    402412        cdef object tmp
    403413        for i from 0 <= i < PyList_GET_SIZE(bucket) by 4:
    404414            tmp = <object>PyList_GET_ITEM(bucket, i)
     
    450460        except (TypeError,ValueError):
    451461            raise KeyError, k
    452462        cdef Py_ssize_t h = (<Py_ssize_t><void *>k1 + 13*<Py_ssize_t><void *>k2 ^ 503*<Py_ssize_t><void *>k3)
    453         #if h < 0: h = -h
     463        # Beware that the C "%" operator returns negative values if the input
     464        # is negative, which is not the case of the Python "%" operator
     465        if h < 0: h = -h
     466        h = h % PyList_GET_SIZE(self.buckets)
    454467        cdef Py_ssize_t i
    455         cdef list bucket = <object>PyList_GET_ITEM(self.buckets, h % PyList_GET_SIZE(self.buckets))
     468        cdef list bucket = <object>PyList_GET_ITEM(self.buckets, h)
    456469        for i from 0 <= i < PyList_GET_SIZE(bucket) by 4:
    457470            if <Py_ssize_t><object>PyList_GET_ITEM(bucket, i) == <Py_ssize_t><void *>k1 and \
    458471               <Py_ssize_t><object>PyList_GET_ITEM(bucket, i+1) == <Py_ssize_t><void *>k2 and \
     
    492505        cdef object v
    493506        for bucket in old_buckets:
    494507            for i from 0 <= i < PyList_GET_SIZE(bucket) by 4:
    495                 k1 = <Py_ssize_t><object>PyList_GET_ITEM(bucket,i)
    496                 k2 = <Py_ssize_t><object>PyList_GET_ITEM(bucket,i+1)
    497                 k3 = <Py_ssize_t><object>PyList_GET_ITEM(bucket,i+2)
    498                 v  = <object>PyList_GET_ITEM(bucket,i+3)
    499                 h = (k1 + 13*k2 ^ 503*k3) % buckets # the new hash
     508                k1 = <Py_ssize_t><object>PyList_GET_ITEM(bucket, i)
     509                k2 = <Py_ssize_t><object>PyList_GET_ITEM(bucket, i+1)
     510                k3 = <Py_ssize_t><object>PyList_GET_ITEM(bucket, i+2)
     511                v  = <object>PyList_GET_ITEM(bucket, i+3)
     512                h = (k1 + 13*k2 ^ 503*k3)
     513                # Beware that the C "%" operator returns negative values if the input
     514                # is negative, which is not the case of the Python "%" operator
     515                if h < 0: h = -h
     516                h = h % buckets # the new hash
    500517                self.buckets[h] += [k1,k2,k3,v]
    501518
    502519    def iteritems(self):