error when porting C code to Python (bitwise manipulation)

MRAB google at mrabarnett.plus.com
Thu Jul 10 19:35:33 CEST 2008


On Jul 10, 4:56 am, Jordan <JordanNealB... at gmail.com> wrote:
> I am trying to rewrite some C source code for a poker hand evaluator
> in Python.  Putting aside all of the comments such as just using the C
> code, or using SWIG, etc.  I have been having problems with my Python
> code not responding the same way as the C version.
>
> C verison:
>
> unsigned find_fast(unsigned u)
> {
>     unsigned a, b, r;
>     u += 0xe91aaa35;
>     u ^= u >> 16;
>     u += u << 8;
>     u ^= u >> 4;
>     b  = (u >> 8) & 0x1ff;
>     a  = (u + (u << 2)) >> 19;
>     r  = a ^ hash_adjust[b];
>     return r;
>
> }
>
> my version (Python, hopefully ;)):
>
> def find_fast(u):
>     u += 0xe91aaa35
>     u ^= u >> 16
>     u += u << 8
>     u ^= u >> 4
>     b  = (u >> 8) & 0x1ff
>     a  = (u + (u << 2)) >> 19
>     r  = a ^ hash_adjust[b]
>     return r
>
> As far as I understand the unsigned instructions in C just increase
> amount of bytes the int can hold, and Python automatically converts to
> longs which have infinite size when necessary, so I am not sure why I
> am getting different results.
>
> I assume that I am missing something fairly simple here, so help a
> n00b out if you can :)
>
> Thanks in advance,
>
> jnb

You want to restrict the values to 32 bits. The result of + or << may
exceed 32 bits, so you need to mask off the excess bits afterwards.

def find_fast(u):
    mask = 0xffffffff
    u  = (u + 0xe91aaa35) & mask
    u ^= u >> 16
    u  = (u + (u << 8)) & mask # can get away with only 1 mask here
    u ^= u >> 4
    b  = (u >> 8) & 0x1ff
    a  = ((u + (u << 2)) & mask) >> 19 # can get away with only 1 mask
here
    r  = a ^ hash_adjust[b]
    return r

HTH



More information about the Python-list mailing list