Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

pack 64 bit int ?

by frankied (Beadle)
on Apr 30, 2002 at 16:39 UTC ( #163123=perlquestion: print w/replies, xml ) Need Help??

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

How would you pack a 64 bit int with a perl whose pack() doesn't support 'q' ? I came up with this:
sub pack64bit() { my $i=new Math::BigInt shift(); my $j=abs($i); my($int1,$int2)=(int($j/2**32)%2**32,int($j%2**32)); if ($i<0) { $int1^=-1; $int2^=-1; ++$int2; $int2%=2**32; $int1=($int1+1)%2**32 if $int2==0; } pack('NN',$int1,$int2); # or 'VV',$int2,$int1 }
...but surely there is a more elegant way ?

Replies are listed 'Best First'.
Re: pack 64 bit int ?
by jsprat (Curate) on Apr 30, 2002 at 17:52 UTC
    I'd use left and right shift. I don't know how this would benchmark (and I don't have the time or energy to try ;) against your version, but this looks cleaner, at least to me.

    sub pack64bit { my $i = new Math::BigInt shift(); my $j = new Math::BigInt $i->brsft(32); my $k = $i - $j->blsft(32); return pack('NN', $j, $k); }

    Mine (as well as yours) will break if something unexpected is passed.

    Update:Anonymous Monk, otherwise known as frankied noticed that this breaks for negative numbers.

    Something bothered me anyway about using Math::BigInt to manipulate bits, so I did a rewrite using Bit::Vector:

    sub pack_bv{ use Bit::Vector; my $vec = Bit::Vector->new_Dec(64, shift); return pack 'NN', $vec->Chunk_Read(32, 32), $vec->Chunk_Read(32, 0); }

    This one looks even cleaner - and better yet, it works!
      that won't work for negative numbers (which is why I use that ugly if($i<0){} in my attempt). BigInt (perhaps unfortunately) doesn't seem to use 2's complement.

      (eg. -1 results in 00000000ffffffff instead of ffffffffffffffff)

        (mental note to login before submitting)
(tye)Re: pack 64 bit int ?
by tye (Sage) on Apr 30, 2002 at 18:53 UTC

    I came up with this for unpacking 64-bit integers into Perl's native scalars.

            - tye (but my friends call me "Tye")
      (wondering how I missed that node when searching)

      I did this for unpack:

      my ($int1,$int2)=unpack('NN',shift()); my $sign=($int1&0x80000000); if($sign) { $int1^=-1; $int2^=-1; ++$int2; $int2%=2**32; ++$int1 unless $int2; } my $i=new Math::BigInt $int1; $i*=2**32; $i+=$int2; $i=-$i if $sign;
      your 2's complement conversion looks less painful, though.

      update:
      shamelessly (thank you!) stealing ideas from tye's unpack, I would now write down a pack like:

      my $i=new Math::BigInt shift(); my($int1,$int2)=do { if ($i<0) { $i=-1-$i; (~(int($i/2**32)%2**32),~int($i%2**32)); } else { (int($i/2**32)%2**32,int($i%2**32)); } }; pack('NN',$int1,$int2);
Re: pack 64 bit int ?
by Elian (Parson) on May 01, 2002 at 15:14 UTC
    This has endian issues you'll need to be careful. You've potentially got three, depending on the platform and 64-bit libraries--big and little endian 64-bit numbers, and paired 32-bit little endian.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://163123]
Approved by particle
Front-paged by RMGir
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2020-01-21 21:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?