# 50+ bits of arithmetic in a 32-bit bag

Discussion in 'Perl Misc' started by mailbox@cpacker.org, Aug 9, 2006.

1. ### Guest

Our implementation of Perl under AIX
doesn't support 64-bit integer arithmetic;
so says "perl -V".

A search of these newsgroups turned up a
test of this fact as follows:

\$two += 2;
\$x = \$two ** 63 + 25;
\$y = \$two ** 63 + 30;
if(\$x == \$y) {print "64 bits not supported\n"}
else {print "64 bits supported\n"}

I found that it would give an affirmative
result if I used up to 55 instead of 63.
This suggests that a floating-point
format with a seven-byte fraction is
being invoked. Perhaps that's the native
floating-point of the AIX box?
At any rate, barring followups to the
contrary, I'll assume that I can treat
our Perl as having a 55-bit integer
arithmetic capability for accumulating
sums, at least. The code in question
doesn't have to be portable.

--
Charles Packer
mailboxATcpacker.org
http://cpacker.org/whatnews

, Aug 9, 2006

2. ### Guest

wrote:
> Our implementation of Perl under AIX
> doesn't support 64-bit integer arithmetic;
> so says "perl -V".
>
> A search of these newsgroups turned up a
> test of this fact as follows:
>
> \$two += 2;
> \$x = \$two ** 63 + 25;
> \$y = \$two ** 63 + 30;
> if(\$x == \$y) {print "64 bits not supported\n"}
> else {print "64 bits supported\n"}
>
> I found that it would give an affirmative
> result if I used up to 55 instead of 63.
> This suggests that a floating-point
> format with a seven-byte fraction is
> being invoked. Perhaps that's the native
> floating-point of the AIX box?
> At any rate, barring followups to the
> contrary, I'll assume that I can treat
> our Perl as having a 55-bit integer
> arithmetic capability for accumulating
> sums, at least.

That is a poor assumption. Just because the \$x and \$y are not identical
does not mean that they are what they are supposed to be.

On my machine, your test also passes for 55, but a more rigorous test
does not:

\$ perl -le '\$foo=55; print((2**\$foo+30)-(2**\$foo+25))'
8

I'm pretty sure that 5 != 8, so 55 bits is right out. On my machine, 52 is
high as I would go.

\$ perl -le '\$foo=52; foreach (1..1e7) { my \$y =
((2**\$foo+\$_+1)-(2**\$foo+\$_));
die \$_ unless \$y == 1}'

Xho

--
Usenet Newsgroup Service \$9.95/Month 30GB

, Aug 9, 2006

3. ### Guest

wrote:
> On my machine, your test also passes for 55, but a more rigorous test
> does not:
>
> \$ perl -le '\$foo=55; print((2**\$foo+30)-(2**\$foo+25))'
> 8
>
> I'm pretty sure that 5 != 8, so 55 bits is right out. On my machine, 52 is
> high as I would go.
>
> \$ perl -le '\$foo=52; foreach (1..1e7) { my \$y =
> ((2**\$foo+\$_+1)-(2**\$foo+\$_));
> die \$_ unless \$y == 1}'

Thanks for that improvement! It behaves the same on our machine as on
yours. Fortunately, 52 bits is still plenty of magnitude for our
purposes.

--
Charles Packer
mailboxATcpacker.org
http://cpacker.org/whatnews

, Aug 10, 2006
4. ### -berlin.deGuest

<> wrote in comp.lang.perl.misc:
> wrote:
> > Our implementation of Perl under AIX
> > doesn't support 64-bit integer arithmetic;
> > so says "perl -V".
> >
> > A search of these newsgroups turned up a
> > test of this fact as follows:
> >
> > \$two += 2;
> > \$x = \$two ** 63 + 25;
> > \$y = \$two ** 63 + 30;
> > if(\$x == \$y) {print "64 bits not supported\n"}
> > else {print "64 bits supported\n"}
> >
> > I found that it would give an affirmative
> > result if I used up to 55 instead of 63.
> > This suggests that a floating-point
> > format with a seven-byte fraction is
> > being invoked. Perhaps that's the native
> > floating-point of the AIX box?
> > At any rate, barring followups to the
> > contrary, I'll assume that I can treat
> > our Perl as having a 55-bit integer
> > arithmetic capability for accumulating
> > sums, at least.

>
> That is a poor assumption. Just because the \$x and \$y are not identical
> does not mean that they are what they are supposed to be.
>
> On my machine, your test also passes for 55, but a more rigorous test
> does not:
>
> \$ perl -le '\$foo=55; print((2**\$foo+30)-(2**\$foo+25))'
> 8
>
> I'm pretty sure that 5 != 8, so 55 bits is right out. On my machine, 52 is
> high as I would go.
>
> \$ perl -le '\$foo=52; foreach (1..1e7) { my \$y =
> ((2**\$foo+\$_+1)-(2**\$foo+\$_));
> die \$_ unless \$y == 1}'

That happens to coincide with the 53 bit mantissa in IEEE-something
floats. One bit is the sign bit, so 52 bits are safe.

Anno

-berlin.de, Aug 10, 2006
5. ### Uri GuttmanGuest

>>>>> "m" == mailbox <> writes:

m> wrote:
>> On my machine, your test also passes for 55, but a more rigorous test
>> does not:
>>
>> \$ perl -le '\$foo=55; print((2**\$foo+30)-(2**\$foo+25))'
>> 8
>>
>> I'm pretty sure that 5 != 8, so 55 bits is right out. On my machine, 52 is
>> high as I would go.
>>
>> \$ perl -le '\$foo=52; foreach (1..1e7) { my \$y =
>> ((2**\$foo+\$_+1)-(2**\$foo+\$_));
>> die \$_ unless \$y == 1}'

m> Thanks for that improvement! It behaves the same on our machine as on
m> yours. Fortunately, 52 bits is still plenty of magnitude for our
m> purposes.

it would be hard to use a cpu today that doesn't use ieee float formats
(any perl vax users around? . so that mantissa size for double floats
(64 bits) will be the same for almost any common box today.

and this one liner also shows the transition from integers to float:

perl -le "print '2**', \\$_, ': ', 2**\\$_, ' - 1 = ', 2**\\$_ - 1 for 47 .. 52"

notice that the -1 stops working after 49 bits so that is the largest
integer you can store in a double. note that this is a decimal issue so
even if the mantissa is 53 bits, you can't operate with a 1 (decimal)
because it takes 4 bits to hold a decimal digit. this is why this shows
49 usable (in decimal) integer bits but the ieee format has 53 bits in
the mantissa.

uri

--
Uri Guttman ------ -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Uri Guttman, Aug 10, 2006
6. ### Ilya ZakharevichGuest

[A complimentary Cc of this posting was sent to
Uri Guttman
<>], who wrote in article <>:
> perl -le "print '2**', \\$_, ': ', 2**\\$_, ' - 1 = ', 2**\\$_ - 1 for 47 .. 52"

Converting to version which has a better chance to work in the shells' maze:

perl -le 'print q(2**), \$_, q ), 2**\$_, q( - 1 = ), 2**\$_ - 1 for 47 .. 52'
2**47: 140737488355328 - 1 = 140737488355327
2**48: 281474976710656 - 1 = 281474976710655
2**49: 562949953421312 - 1 = 562949953421311
2**50: 1.12589990684262e+15 - 1 = 1.12589990684262e+15
2**51: 2.25179981368525e+15 - 1 = 2.25179981368525e+15
2**52: 4.5035996273705e+15 - 1 = 4.5035996273705e+15

> notice that the -1 stops working after 49 bits so that is the largest
> integer you can store in a double.

Nope. 53 bits is OK.

> note that this is a decimal issue so even if the mantissa is 53
> bits, you can't operate with a 1 (decimal) because it takes 4 bits
> to hold a decimal digit.

Nope, this is just a buggy Perl's convertion to string.

perl -le 'print q(2**), \$_, q ), sprintf(q(%.0f), 2**\$_), q( - 1 = ), sprintf(q(%.f), 2**\$_ - 1) for 47 .. 55'
2**47: 140737488355328 - 1 = 140737488355327
2**48: 281474976710656 - 1 = 281474976710655
2**49: 562949953421312 - 1 = 562949953421311
2**50: 1125899906842624 - 1 = 1125899906842623
2**51: 2251799813685248 - 1 = 2251799813685247
2**52: 4503599627370496 - 1 = 4503599627370495
2**53: 9007199254740992 - 1 = 9007199254740991
2**54: 18014398509481984 - 1 = 18014398509481984
2**55: 36028797018963968 - 1 = 36028797018963968

Hope this helps,
Ilya

Ilya Zakharevich, Aug 10, 2006