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.
| [reply] |
|
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;
}
| [reply] [d/l] |
|
$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. | [reply] [d/l] |
|
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".
| [reply] [d/l] |
|
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".
| [reply] [d/l] |
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".
| [reply] [d/l] |
Re: emulate 32-bit on perl 64
by moritz (Cardinal) on Jan 11, 2012 at 14:53 UTC
|
You can cut off any 1-bit above the 32nd bit after each interesting operation. See perlop for details.
| [reply] |
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? | [reply] |
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.
| [reply] [d/l] |
|
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.) | [reply] [d/l] [select] |
|
Erm, *what*? Why does 32-bit perl (I just tested on MirBSD/i386, it does behave as you said) not wraparound?
Urgh!
| [reply] |