Difference between revisions of "Math::BigInt"
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
Contents
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";