Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^3: Equivalent of unpack 'q' with 32-bit Perl (a8)

by Anonymous Monk
on Sep 06, 2016 at 22:36 UTC ( [id://1171277]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Equivalent of unpack 'q' with 32-bit Perl (a8)
in thread Equivalent of unpack 'q' with 32-bit Perl

No, I mean dont do any conversion if its not possible :) treat it as a string, convert as quad when you can, otherwise its raw bytes ...

There is always bigint which says

print hex("0x1234567890123490"),"\n"; # Perl v5.10.0 or later

So

use constant CAN_PACK_QUADS => !! eval { my $f = pack 'q'; 1 }; use Math::BigInt; print quad('ffffffffffff'), "\n"; sub quad { CAN_PACK_QUADS ? unpack( 'q<', $_[0] ) : Math::BigInt->new( '0x'.$_[0] ) } __END__

Replies are listed 'Best First'.
Re^4: Equivalent of unpack 'q' with 32-bit Perl (a8)
by Limbic~Region (Chancellor) on Sep 06, 2016 at 23:01 UTC
    Anonymous Monk,

    I really appreciate your help and I am not trying to intentionally be obtuse but I am still not following. The code needs to work on the output of Digest::MD5's md5() which according to the docs is This function will concatenate all arguments, calculate the MD5 digest of this "message", and return it in binary form. The returned string will be 16 bytes long.

    The following code works

    #!/usr/bin/perl use strict; use warnings; use Digest::MD5 'md5'; use Math::BigInt; my $thing = 'This is a thing'; my $md5 = md5($thing); print unpack('q', $md5), "\n"; print md5_32bit_sol($md5), "\n"; sub md5_32bit_sol { my ($md5) = @_; return md5_32bit_positive($md5) if vec($md5, 63, 1) == 0; return md5_32bit_negative($md5); } sub md5_32bit_negative { my ($md5) = @_; my $base_2 = ''; for (reverse 0 .. 63) { $base_2 .= abs(vec($md5, $_, 1) - 1); } $base_2 =~ s/^0+//; my $decimal = Math::BigInt->new(); my $power = Math::BigInt->new(2); $power->bpow(length($base_2) - 1); for my $pos (0 .. length($base_2) - 1) { $decimal->badd($power * substr($base_2, $pos, 1)); $power->bdiv(2); } return ($decimal + 1) * -1; } sub md5_32bit_positive { my ($md5) = @_; my $base_2 = ''; for (reverse 0 .. 63) { $base_2 .= vec($md5, $_, 1); } $base_2 =~ s/^0+//; my $decimal = Math::BigInt->new(); my $power = Math::BigInt->new(2); $power->bpow(length($base_2) - 1); for my $pos (0 .. length($base_2) - 1) { $decimal->badd($power * substr($base_2, $pos, 1)); $power->bdiv(2); } return $decimal; }

    I am not sure why the code for handling negative numbers is so weird but it works for everything I tested.

    Cheers - L~R

      well, shouldn't need to involve vec at all, just use md5_hex to get hex version of digest ... you could unpack 'H*' ... and give that to bigint hex ...

      also negatives, yeah I've no idea :)

        Anonymous Monk,
        just use md5_hex to get hex version of digest

        That's a brilliant (obvious) idea. I wish I had thought of it before I wrote the code above (which now handles negative numbers as well). I assume your approach will work but I am not inclined to verify (the guy I am helping should be able to do it himself). Thanks!

        Edit: After thinking about it for a minute, I don't think that would work. Basically, you have an 128 bit integer in binary form and you are then converting the first 64 bits of it into decimal form. I'm pretty sure a hex digest isn't going to help here because you can't simply just cut it in half.

        Cheers - L~R

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-04-18 05:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found