Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

emulate 32-bit on perl 64

by loofort (Initiate)
on Jan 11, 2012 at 14:44 UTC ( [id://947353]=perlquestion: print w/replies, xml ) Need Help??

loofort has asked for the wisdom of the Perl Monks concerning the following question:

Hi all. My script uses bitwise operation. algorithm assumes that we use 32 bit integer. How can I force it to work correct on perl based 64 ? (we move it from CentOS (32) to new server Debian(64) )

Replies are listed 'Best First'.
Re: emulate 32-bit on perl 64
by Corion (Patriarch) on Jan 11, 2012 at 14:48 UTC

    My recommendation is to use 32-bit bitwise operations instead of using unrestricted bitwise operations, or to operate on 64 bits worth of data instead of 32 bits at a time.

    As you don't show any code, it is hard to give any more concrete advice. Please post a Short, Self Contained, Correct (Compilable), Example so we can see what the cause for your problem might be and suggest appropriate remedies or workarounds.

      I'm not sure that example brings any clearence. I'm not the author and I use it as black box. here is little part::
      for ($h = 16; $h < 80; $h++) { $i[$h] = a2 ($i[$h - 3] ^ $i[$h - 8] ^ $i[$h - 14] ^ $i[$h - 16], +1); } sub a2 { my ($b, $a) = @_; my $c = $b >> 32 - $a; my $e = (1 << 32 - $a) - 1; my $d = $b & $e; return tos($d << $a | $c); } sub tos { my ($num) = @_; $num = $num - 4294967296 if $num > 4294967295; $num = $num + 4294967296 if $num < -2147483648; if ($num >= 0) { $num = $num - 2 ** 32 if ($num >> 31); } return $num; }

        There is no magic to sprinkle over an algorithm that relies on 32-bit integers to make it behave with other integer sizes. The hardcoded numbers here are magic for 32-bit numbers:

        $num = $num - 4294967296 if $num > 4294967295; $num = $num + 4294967296 if $num < -2147483648;

        You will have to understand the algorithm involved to be able to make the required changes. Alternatively, you can run the program under a Perl compiled with 32-bit integers.

        Try this -- 'scuse the formatting, but there's no good way to format it. It produces the same results on 32-bit and 64-bit Perls for one randomly generated set of input data:

        for( my $h = 16; $h < 80; $h++ ) { $i[$h] = a2( ( ( ( ( ( $i[$h - 3] ^ $i[$h - 8] ) & 0xffffffff ) ^ $i[$h - 14] ) & 0xffffffff ) ^ $i[$h - 16] ) & 0xffffffff , 1 ); } print "@i"; sub a2 { my ($b, $a) = @_; my $c = $b >> 32 - $a; my $e = (1 << 32 - $a) - 1; my $d = $b & $e; return tos($d << $a | $c); } sub tos { my ($num) = @_; $num = $num - 4294967296 if $num > 4294967295; $num = $num + 4294967296 if $num < -2147483648; if ($num >= 0) { $num = $num - 2 ** 32 if ($num >> 31); } return $num; }

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

        This is slightly more readable:

        sub fix32{ $_[0] & 0xffffffff } for( my $h = 16; $h < 80; $h++ ) { $i[$h] = a2( fix32( fix32( fix32( $i[$h - 3] ^ $i[$h - 8] ) ^ $i[$h - 14] ) + ^ $i[$h - 16] ) , 1 ); }

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

Re: emulate 32-bit on perl 64
by BrowserUk (Patriarch) on Jan 11, 2012 at 15:16 UTC
    How can I force it to work correct on perl based 64 ?

    It gets very messy.

    Effectively you have to mask the resultant from operation after any operation that might cause the resultant to be promoted to more than 32 bits. eg.

    C:\test>\perl32\bin\perl -le"print 11 | 29 | ~15" 4294967295 C:\test>\perl64\bin\perl -le"print 11 | 29 | ~15" 18446744073709551615 C:\test>\perl64\bin\perl -le"print 11 | 29 | ( ~15 & 0xffffffff )" 4294967295

    And if you are manipulating signed rather than unsigned values it gets really tiresome.

    I don't know of a good solution to this problem.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

Re: emulate 32-bit on perl 64
by moritz (Cardinal) on Jan 11, 2012 at 14:53 UTC
Re: emulate 32-bit on perl 64
by raybies (Chaplain) on Jan 11, 2012 at 16:59 UTC
    Lots of interesting ideas presented already. And I've never used it before, but what about the Bit::Vector module?
Re: emulate 32-bit on perl 64
by sundialsvc4 (Abbot) on Jan 11, 2012 at 15:58 UTC

    Probably the key improvement here is the use of hexadecimal notation:   0xffffffff instead of the corresponding, “magic” decimal.   As long as you are very careful to use unsigned arithmetic and specify bitmasks that are no larger than the integer-size you know that you are using, code like this ought to be transportable.   (It might not be readable, heh, but it ought to be int-length agnostic.)

    I would almost edit my comment to say, don’t use “arithmetic” at all when you are bit-twiddling, as in code like this:

    $num = $num - 4294967296 if $num > 4294967295; $num = $num + 4294967296 if $num < -2147483648;
      That’s nasty...   And I recognize at least one of those numbers, -2147483648, as an old, familiar 32-bit friend.   I also detect the presence of signed arithmetic, dependent upon the thirty-first bit being the sign-bit.   I suggest that this code should be rewritten to use bit-masking operators ... and to do so, perhaps, in a very specific way, as follows:

    If you want to mash-off, say, all but the rightmost 31 bits of an integer quantity, you should take:   qty := qty and ( not 0x7fffffff );.   (I am not using Perl notation here, for clarity.)   The subexpression, (not 0x7fffffff), will evaluate to an int in which all bits are 1 except for the rightmost 31 bits, and it will do so correctly no matter what the sizeof(int) may be.

    So, I suggest that you need to go through code like this (fortunately, it is a small piece of code), work out what it is doing and then rewrite it.   Construct a very thorough set of Test::More cases that you can run on both a 32-bit and a 64-bit system to prove that your rewrite is thoroughly correct.

      As long as you are very careful to use unsigned arithmetic and specify bitmasks that are no larger than the integer-size you know that you are using, code like this ought to be transportable.

      Unfortunately, it's not always quite as simple in the general case.  For example, if the 32-bit code relies on specific overflow/wrap-over effects. Consider the following very simple case:

      my $result = (0xffffffff + 2) & 0xffffffff; print $result;

      Although the result is masked down to 32 bits, it differs depending on the perl being used:

      32-bit perl: 4294967295 64-bit perl: 1

      (I'm not saying it cannot be done, but it requires taking into account the specific overflow behavior, IV/UV to NV conversions of 32-bit perls, etc. — simple 0xffffffff AND-masking isn't enough.)

        Erm, *what*? Why does 32-bit perl (I just tested on MirBSD/i386, it does behave as you said) not wraparound? Urgh!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://947353]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-03-29 15:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found