473,385 Members | 1,942 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

error when porting C code to Python (bitwise manipulation)

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
Jul 10 '08 #1
11 2163
On Wed, 09 Jul 2008 20:56:59 -0700, Jordan 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
What business does a poker hand evaluator have doing that kind of bitwise
arithmetic? One problem with C is not the language itself, but the
culture of using bitwise tricks where they aren't really necessary.

Anyway, I believe in C unsigned bitwise arithmetic, when overflowing an
integer will simply throw away the bits that are "too big". So if python
is converting to a long when overflowing, that would cause a different
result right there.

You could try throwing in "&= 0xffffffff" all over the place if the C
code was written for a 32 bit unsigned int. unsigned int will usually be
32 or 64 bits these days. If it's a 64 bit unsigned int in C, it'd be
"&= 0xffffffffffffffff".

Jul 10 '08 #2
I was actually just going through an example to show what was
happening each step of the way and noticed the overflow!!! bah, stupid
tricks tricks tricks!!!

The problem is def the overflow, I notice that I start to get negative
numbers in the C version, which makes me think that the & 0xffffffff
trick won't work (because it will never evaluate to negative in
python, right?)
Seeing that the problem is the overflow and the bitwise operations
returning a negative, does anyone have any suggestions...I will look
more into C bitwise tricks in the meantime haha.

And in terms of what this is doing in a poker hand evaluator:

http://www.suffecool.net/poker/evaluator.html (an evaluator using
some nice tricks to evaluate for flushes, straights, and highcard with
LU tables then binary search for the rest)

then

http://senzee.blogspot.com/2006/06/s...fect-hash.html (does the
same thing, but uses perfect hashing instead of a binary search)

the function I am having issues with comes up in the hashing
algorithm :)
Jul 10 '08 #3
I realize I did a pretty bad job of explaining the problem. The
problem is the python version is returning an r that is WAAAAY to big.

Here is an example run through that function in each language:

C:

u starts at 1050

u += 0xe91aaa35;

u is now -384127409

u ^= u >16;

u is now -384153771

u += u << 8;

u is now 56728661

u ^= u >4;

u is now 56067472

b = (u >8) & 0x1ff;

b is now 389

a = (u + (u << 2)) >19;

a is now 534

r = a ^ hash_adjust[b];

r is now 6366

Python:

u starts at 1050

u += 0xe91aaa35

u is now 3910839887L

rut roh...
Jul 10 '08 #4
if after the first step (u += 0xe91aaa35) you apply this function:

invert = lambda x: ~int(hex(0xffffffff - x)[0:-1],16)

it returns the correct value (corrected the overflow)

but there is still something wrong, still looking into it, if someone
knows how to do this, feel free to comment :)
Jul 10 '08 #5
Jordan wrote:
C:

u starts at 1050

u += 0xe91aaa35;

u is now -384127409
Hm, a negative unsigned...
Python:

Â* Â*u starts at 1050

Â* Â*u += 0xe91aaa35

Â* Â*u is now Â*3910839887L
Seriously, masking off the leading ones is the way to go:
>>-384127409 & 0xffffffff == 3910839887 & 0xffffffff
True

Peter
Jul 10 '08 #6
Well, I have figured out something that works:

def findit(u):
u += 0xe91aaa35
u1 = ~(0xffffffff - u) ^ u >16
u1 += ((u1 << 8) & 0xffffffff)
u1 ^= (u1 & 0xffffffff) >4
b = (u1 >8) & 0x1ff
a = (u1 + (u1 << 2) & 0xffffffff) >19
r = int(a) ^ hash_adjust[int(b)]
return r
I feel like this cannot possibly be the best way of doing this, but it
does work!!!! haha

If anyone would care to share a more elegant solution, that would be
great :)
Jul 10 '08 #7
On Jul 10, 4:56*am, Jordan <JordanNealB...@gmail.comwrote:
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
Jul 10 '08 #8
On Jul 10, 1:35*pm, MRAB <goo...@mrabarnett.plus.comwrote:
On Jul 10, 4:56*am, Jordan <JordanNealB...@gmail.comwrote:
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 1mask
here
* * r *= a ^ hash_adjust[b]
* * return r

HTH
Well, I guess there are two problems....the masking and the fact the
in C it seems to for some reason overflow and become a negative
value....still not sure why it does it....So the code with just
masking doesn't work, you still need some sort of weird inversion like
the ~(0xFFFFFFFF - u).....weird

anyone?

haha
Jul 10 '08 #9
On Thu, 10 Jul 2008 Jordan wrote:
>On Jul 10, 1:35*pm, MRAB <goo...@mrabarnett.plus.comwrote:
>On Jul 10, 4:56*am, Jordan <JordanNealB...@gmail.comwrote:
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

Well, I guess there are two problems....the masking and the fact the
in C it seems to for some reason overflow and become a negative
value....still not sure why it does it....So the code with just
masking doesn't work, you still need some sort of weird inversion like
the ~(0xFFFFFFFF - u).....weird

anyone?
In C unsigned can not be negative. Why do you believe
the numbers are negative? If your debugger is telling
you this thow away the debugger and use printf.
If printf is telling you this then use the right format.
printf("%u", u); // for unsigned int u
printf("%lu", u); // for unsigned long u
printf("%x", u);
or
printf("0x%08x", u); // to see u in hex

Harald

Jul 10 '08 #10
On Jul 10, 4:04*pm, Harald Luessen <harald.lues...@gmx.dewrote:
On Thu, 10 Jul 2008 Jordan wrote:
On Jul 10, 1:35*pm, MRAB <goo...@mrabarnett.plus.comwrote:
On Jul 10, 4:56*am, Jordan <JordanNealB...@gmail.comwrote:
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 maskhere
* * 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
Well, I guess there are two problems....the masking and the fact the
in C it seems to for some reason overflow and become a negative
value....still not sure why it does it....So the code with just
masking doesn't work, you still need some sort of weird inversion like
the ~(0xFFFFFFFF - u).....weird
anyone?

In C unsigned can not be negative. Why do you believe
the numbers are negative? If your debugger is telling
you this thow away the debugger and use printf.
If printf is telling you this then use the right format.
printf("%u", u); // for unsigned int u
printf("%lu", u); // for unsigned long u
printf("%x", u);
or
printf("0x%08x", u); // to see u in hex

Harald
haha....I was using printf, but for some reason I decided not to use
%u...hmm...looking back over things now...
Jul 10 '08 #11
Well, that about wraps this up...MRAB was 100% correct, that solution
worked...not sure how I managed to mess it up when I tried it early.

Based on the incoming values of u here is the code with the minimal
number of maskings:

def findit(u):
mask = 0xffffffff
u += 0xe91aaa35
u ^= u >16
u = (u + (u << 8)) & mask
u ^= u >4
b = (u >8) & 0x1ff
a = (u + (u << 2) & mask) >19
r = a ^ hash_adjust[b]
return r

Thanks for your help all!
Jul 10 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: dean | last post by:
Hello Group: I obtained a copy ofthe python 2.3.3 depot (binary zipped) from the hp porting archive. I have successfully unzipped the file and installed it using swinstall. I received the...
1
by: Jon | last post by:
I've seen the previous msg about this error, and how it's only been reported once. (Twice now) And I have some other circumstances. I'm also receiving this error, on a windows 2000 platform. ...
1
by: Max | last post by:
I thought restricted mode had been removed from Python but it seems to be active for Python 2.3.5 +. I'm using the JEP product which allows integration of Java with Python (see...
2
by: Anand | last post by:
Hi Are there any tools that would help in porting code from Pyton 2.3 to 2.4 ? I have gone through the whatsnew documents and created a document comparing Python 2.4 to 2.3. But so far has not...
0
by: Raymond L. Buvel | last post by:
I am preparing to release an extension module that interfaces Python to the Class Library for Numbers (http://www.ginac.de/CLN/). This module will provide Python types for arbitrary precision...
1
by: ImamicPH | last post by:
Hi, My first post. How do you resolve linker errors? I have a simple header file that contains one function declaration. This function is used in another file (.cpp) in the definition of a...
2
by: sandip desale | last post by:
Dear All, We have a Tcl/Tk application written using Python 2.2. Using this application we want to call some customizable Java APIs. I tried porting Tcl/Tk application to Jython but not able to do...
45
by: Carramba | last post by:
Hi! I now that I can't do straight forward any bitwise operation on float (double etc..). But I wondering what is the easiest/best way to do this? I was thinking if I have float x=1.1111 so I can...
29
by: Carl Banks | last post by:
Anyone with me here? (I know the deadline for P3 PEPs has passed; this is just talk.) Not many people are bit-fiddling these days. One of the main uses of bit fields is flags, but that's not...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.