From: Sal on
I recently implemented a C hashing algorithm in Perl and wasted about
8 hours of my time trying to debug it because of a stupid assumption
on my part. When doing a lot of shifts and bit-wise xor's it's easy
for 32-bit integers to overflow into double precision floating point
values. I recognized this early on and thought I was capturing only
the lowest 32 bits with ($x &= 0xffffffff). That simply does not work!
The way I got around it was with ($x %= 4294967296). In hindsight it's
easy for me now to recognize why the first not only doesn't work but
doesn't even make sense with the mixed number types. I hope this helps
someone else. Happy bit-twiddling!
From: Ben Morrow on

Quoth Sal <here(a)softcom.net>:
> I recently implemented a C hashing algorithm in Perl and wasted about
> 8 hours of my time trying to debug it because of a stupid assumption
> on my part. When doing a lot of shifts and bit-wise xor's it's easy
> for 32-bit integers to overflow into double precision floating point
> values. I recognized this early on and thought I was capturing only
> the lowest 32 bits with ($x &= 0xffffffff). That simply does not work!
> The way I got around it was with ($x %= 4294967296). In hindsight it's
> easy for me now to recognize why the first not only doesn't work but
> doesn't even make sense with the mixed number types. I hope this helps
> someone else. Happy bit-twiddling!

perldoc -f integer

Ben

From: Sal on
On May 18, 1:57 pm, Ben Morrow <b...(a)morrow.me.uk> wrote:
> Quoth Sal <h...(a)softcom.net>:
>
> > I recently implemented a C hashing algorithm in Perl and wasted about
> > 8 hours of my time trying to debug it because of a stupid assumption
> > on my part. When doing a lot of shifts and bit-wise xor's it's easy
> > for 32-bit integers to overflow into double precision floating point
> > values. I recognized this early on and thought I was capturing only
> > the lowest 32 bits with ($x &= 0xffffffff). That simply does not work!
> > The way I got around it was with ($x %= 4294967296). In hindsight it's
> > easy for me now to recognize why the first not only doesn't work but
> > doesn't even make sense with the mixed number types. I hope this helps
> > someone else. Happy bit-twiddling!
>
> perldoc -f integer
>
> Ben

Tried it, didn't work with the integer pragma. The only way I could
get it to work properly was to allow an integer promotion to a C
double and then do the modulo arithmetic to capture the least-
significant 32 bits.
From: Ben Morrow on

Quoth Sal <here(a)softcom.net>:
> On May 18, 1:57�pm, Ben Morrow <b...(a)morrow.me.uk> wrote:
> > Quoth Sal <h...(a)softcom.net>:
> >
> > > I recently implemented a C hashing algorithm in Perl and wasted about
> > > 8 hours of my time trying to debug it because of a stupid assumption
> > > on my part. When doing a lot of shifts and bit-wise xor's it's easy
> > > for 32-bit integers to overflow into double precision floating point
> > > values. I recognized this early on and thought I was capturing only
> > > the lowest 32 bits with ($x &= 0xffffffff). That simply does not work!
> > > The way I got around it was with ($x %= 4294967296). In hindsight it's
> > > easy for me now to recognize why the first not only doesn't work but
> > > doesn't even make sense with the mixed number types. I hope this helps
> > > someone else. Happy bit-twiddling!
> >
> > perldoc -f integer
>
> Tried it, didn't work with the integer pragma. The only way I could
> get it to work properly was to allow an integer promotion to a C
> double and then do the modulo arithmetic to capture the least-
> significant 32 bits.

Depending on what you're doing, promotion to double *should* safely give
you 53 bits of integer precision, but you may want to consider
rebuilding your perl with -Duse64bitint to avoid type conversion all
over the place. The standard FreeBSD build has been built with this
option for a while now, and there is some talk of using it for the
Debian builds of 5.12.

Ben

From: Ilya Zakharevich on
On 2010-05-18, Ben Morrow <ben(a)morrow.me.uk> wrote:
>> > > 8 hours of my time trying to debug it because of a stupid assumption
>> > > on my part. When doing a lot of shifts and bit-wise xor's it's easy
>> > > for 32-bit integers to overflow into double precision floating point
>> > > values. I recognized this early on and thought I was capturing only
>> > > the lowest 32 bits with ($x &= 0xffffffff). That simply does not work!
>> > > The way I got around it was with ($x %= 4294967296). In hindsight it's
>> > > easy for me now to recognize why the first not only doesn't work but
>> > > doesn't even make sense with the mixed number types. I hope this helps
>> > > someone else. Happy bit-twiddling!
>> >
>> > perldoc -f integer
>>
>> Tried it, didn't work with the integer pragma. The only way I could
>> get it to work properly was to allow an integer promotion to a C
>> double and then do the modulo arithmetic to capture the least-
>> significant 32 bits.
>
> Depending on what you're doing, promotion to double *should* safely give
> you 53 bits of integer precision, but you may want to consider
> rebuilding your perl with -Duse64bitint to avoid type conversion all
> over the place. The standard FreeBSD build has been built with this
> option for a while now, and there is some talk of using it for the
> Debian builds of 5.12.

Having int wider than float type is a VERY large can of worms (well,
at least it was the last time I was looking; did things change
recently?). What is reported above (which is, essentially, a bug of
the implementation of `use integer') is a very small can of worms.

Does not look like a fair trade...
Ilya