Difference between revisions of "Math::BigInt"

From HalfgeekKB
Jump to navigation Jump to search
Line 1: Line 1:
 +
=In-place vs. Copy Modification=
  
 +
Whether Math::BigInt does its thing in-place or not depends on whether you use the methods or the overloaded operators.
 +
 +
==Methods Work In-Place==
 +
 +
If you use the methods, modification is in-place, regardless of context.  A new object is not created for a result.
 +
 +
<nowiki>
 +
use Math::BigInt;
 +
 +
# This reblessing isn't fail-safe
 +
# but it works for this example
 +
sub same_object ($$) {
 +
    my $pa = ref($_[0]) or return undef;
 +
    my $pb = ref($_[1]) or return undef;
 +
    my $v;
 +
    bless $_[0], 'Xana::Fake';
 +
    bless $_[1], 'Xana::Fake';
 +
    $v = $_[0] == $_[1];
 +
    bless $_[1], $pb;
 +
    bless $_[0], $pa;
 +
    $v;
 +
}
 +
 +
# Void context
 +
my $a = new Math::BigInt '27';
 +
 +
$a->badd(3);
 +
$a == '30'
 +
    or die "a=$a";
 +
 +
# Scalar context
 +
my $b = new Math::BigInt '27';
 +
my $c = $b->badd(3);
 +
$b == '30'
 +
    or die "b=$b";
 +
same_object($b,$c)
 +
    or die "b and c are not the same object";
 +
</nowiki>
 +
 +
==Overloads Use Copies==
 +
 +
Meanwhile, overloaded operators treat the objects like regular scalars; nothing is modified in place unless an assignment operator (including <code>+=</code>, <code>*=</code>, ''etc.'', but not <code>=</code> for Perl reasons) is used.
 +
 +
# Void context using overloads
 +
# does not work in-place
 +
my $d = new Math::BigInt '57';
 +
$d + 3;
 +
$d == '57'
 +
    or die "d=$d";
 +
 +
# Scalar context using overloads
 +
# does not work in-place
 +
my $e = new Math::BigInt '97';
 +
my $f = $e + 4;
 +
$e == '97'
 +
    or die "e=$e";
 +
$f == '101'
 +
    or die "f=$f";
 +
 +
=Converting a binary string to a BigInt=
 +
 +
This code conveniently reinterprets raw bytes as [[hexadecimals|hexadecimal]] digits, big-endian style, so that the data may be cast into a bigint.  This code doesn't do any buffering; for that, try my new Xana::Math::RawDataUtil module in [[Xana]].
 +
 +
# Unsigned
 +
my $a = "ZYXWVUT";
 +
my $ba = new Math::BigInt '0x' . unpack('H*',$a);
 +
# Test
 +
$ba == '25430983861228884'
 +
    or die "ba=$ba";
 +
 +
# Signed
 +
sub raw_to_signed_bigint ($) {
 +
    # The MSB is the sign bit.
 +
    if(unpack('C',substr($_[0],0,1)) & 0x80) {
 +
        my $hex = unpack('H*',$_[0]);
 +
        # Invert the hex digits.
 +
        $hex =~ tr/0123456789aAbBcCdDeEfF/fedcba9876554433221100/;
 +
        my $bigint = new Math::BigInt "0x$hex";
 +
        # Then, the ones complement is the right answer.
 +
        return $bigint->bnot();
 +
    } else {
 +
        # The normal unsigned thing.
 +
        return Math::BigInt->new( '0x' . unpack('H*',$_[0]) );
 +
    }
 +
}
 +
 +
# Tests
 +
my $bb = raw_to_signed_bigint "\xFF\x54\xAB\x56\x73\x14\xE0\xF5\x2E";
 +
$bb == '-12345678901234567890'
 +
    or die "bb=$bb";
 +
 +
my $bc = raw_to_signed_bigint "\xFF";
 +
$bc == '-1'
 +
    or die "bc=$bc";
 +
 +
my $bd = raw_to_signed_bigint "ZYXWVUT";
 +
$bd == '25430983861228884'
 +
    or die "bd=$bd";
 +
 +
=See Also=
 +
 +
* [http://search.cpan.org/~tels/Math-BigInt-1.75/lib/Math/BigInt.pm CPAN]

Revision as of 11:11, 2 June 2005

In-place vs. Copy Modification

Whether Math::BigInt does its thing in-place or not depends on whether you use the methods or the overloaded operators.

Methods Work In-Place

If you use the methods, modification is in-place, regardless of context. A new object is not created for a result.

use Math::BigInt;

# This reblessing isn't fail-safe
# but it works for this example
sub same_object ($$) {
    my $pa = ref($_[0]) or return undef;
    my $pb = ref($_[1]) or return undef;
    my $v;
    bless $_[0], 'Xana::Fake';
    bless $_[1], 'Xana::Fake';
    $v = $_[0] == $_[1];
    bless $_[1], $pb;
    bless $_[0], $pa;
    $v;
}

# Void context
my $a = new Math::BigInt '27';

$a->badd(3);
$a == '30'
    or die "a=$a";

# Scalar context
my $b = new Math::BigInt '27';
my $c = $b->badd(3);
$b == '30'
    or die "b=$b";
same_object($b,$c)
    or die "b and c are not the same object";

Overloads Use Copies

Meanwhile, overloaded operators treat the objects like regular scalars; nothing is modified in place unless an assignment operator (including +=, *=, etc., but not = for Perl reasons) is used.

# Void context using overloads
# does not work in-place
my $d = new Math::BigInt '57';
$d + 3;
$d == '57'
    or die "d=$d";

# Scalar context using overloads
# does not work in-place
my $e = new Math::BigInt '97';
my $f = $e + 4;
$e == '97'
    or die "e=$e";
$f == '101'
    or die "f=$f";

Converting a binary string to a BigInt

This code conveniently reinterprets raw bytes as hexadecimal digits, big-endian style, so that the data may be cast into a bigint. This code doesn't do any buffering; for that, try my new Xana::Math::RawDataUtil module in Xana.

# Unsigned
my $a = "ZYXWVUT";
my $ba = new Math::BigInt '0x' . unpack('H*',$a);
# Test
$ba == '25430983861228884'
    or die "ba=$ba";

# Signed
sub raw_to_signed_bigint ($) {
    # The MSB is the sign bit.
    if(unpack('C',substr($_[0],0,1)) & 0x80) {
        my $hex = unpack('H*',$_[0]);
        # Invert the hex digits.
        $hex =~ tr/0123456789aAbBcCdDeEfF/fedcba9876554433221100/;
        my $bigint = new Math::BigInt "0x$hex";
        # Then, the ones complement is the right answer.
        return $bigint->bnot();
    } else {
        # The normal unsigned thing.
        return Math::BigInt->new( '0x' . unpack('H*',$_[0]) );
    }
}

# Tests
my $bb = raw_to_signed_bigint "\xFF\x54\xAB\x56\x73\x14\xE0\xF5\x2E";
$bb == '-12345678901234567890'
    or die "bb=$bb";

my $bc = raw_to_signed_bigint "\xFF";
$bc == '-1'
    or die "bc=$bc";

my $bd = raw_to_signed_bigint "ZYXWVUT";
$bd == '25430983861228884'
    or die "bd=$bd";

See Also