From: Tels Date: Sat, 3 Feb 2007 13:10:57 +0000 (+0100) Subject: Integrate BigRat 0.17 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b8884ce4af9d0f622732315808561f174bd9be0c;p=p5sagit%2Fp5-mst-13.2.git Integrate BigRat 0.17 Message-Id: <200702031310.58656@bloodgate.com> p4raw-id: //depot/perl@30359 --- diff --git a/lib/Math/BigRat.pm b/lib/Math/BigRat.pm index d18ea07..c4c131b 100644 --- a/lib/Math/BigRat.pm +++ b/lib/Math/BigRat.pm @@ -13,7 +13,8 @@ package Math::BigRat; -require 5.005_03; +# anythig older is untested, and unlikely to work +use 5.006002; use strict; use Math::BigFloat; @@ -22,7 +23,7 @@ use vars qw($VERSION @ISA $upgrade $downgrade @ISA = qw(Math::BigFloat); -$VERSION = '0.15'; +$VERSION = '0.17'; use overload; # inherit overload from Math::BigFloat @@ -228,13 +229,13 @@ sub new $self->{sign} = '+'; # no sign => '+' $self->{_n} = undef; $self->{_d} = undef; - if ($n =~ /^([+-]?)0*(\d+)\z/) # first part ok? + if ($n =~ /^([+-]?)0*([0-9]+)\z/) # first part ok? { $self->{sign} = $1 || '+'; # no sign => '+' $self->{_n} = $MBI->_new($2 || 0); } - if ($d =~ /^([+-]?)0*(\d+)\z/) # second part ok? + if ($d =~ /^([+-]?)0*([0-9]+)\z/) # second part ok? { $self->{sign} =~ tr/+-/-+/ if ($1 || '') eq '-'; # negate if second part neg. $self->{_d} = $MBI->_new($2 || 0); @@ -290,7 +291,7 @@ sub new else { # for simple forms, use $MBI directly - if ($n =~ /^([+-]?)0*(\d+)\z/) + if ($n =~ /^([+-]?)0*([0-9]+)\z/) { $self->{sign} = $1 || '+'; $self->{_n} = $MBI->_new($2 || 0); @@ -1308,6 +1309,44 @@ sub as_hex $s . $MBI->_as_hex($x->{_n}); } +sub as_oct + { + my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_); + + return $x unless $x->is_int(); + + my $s = $x->{sign}; $s = '' if $s eq '+'; + $s . $MBI->_as_oct($x->{_n}); + } + +############################################################################## + +sub from_hex + { + my $class = shift; + + $class->new(@_); + } + +sub from_bin + { + my $class = shift; + + $class->new(@_); + } + +sub from_oct + { + my $class = shift; + + my @parts; + for my $c (@_) + { + push @parts, Math::BigInt->from_oct($c); + } + $class->new ( @parts ); + } + ############################################################################## # import @@ -1316,6 +1355,7 @@ sub import my $self = shift; my $l = scalar @_; my $lib = ''; my @a; + my $try = 'try'; for ( my $i = 0; $i < $l ; $i++) { @@ -1336,9 +1376,10 @@ sub import $downgrade = $_[$i+1]; # or undef to disable $i++; } - elsif ($_[$i] eq 'lib') + elsif ($_[$i] =~ /^(lib|try|only)\z/) { $lib = $_[$i+1] || ''; # default Calc + $try = $1; # lib, try or only $i++; } elsif ($_[$i] eq 'with') @@ -1365,7 +1406,7 @@ sub import $lib = join(",", @c); } my @import = ('objectify'); - push @import, lib => $lib if $lib ne ''; + push @import, $try => $lib if $lib ne ''; # MBI already loaded, so feed it our lib arguments Math::BigInt->import( @import ); @@ -1410,33 +1451,27 @@ for arbitrary big rational numbers. =head2 MATH LIBRARY -Math with the numbers is done (by default) by a module called -Math::BigInt::Calc. This is equivalent to saying: - - use Math::BigRat lib => 'Calc'; +You can change the underlying module that does the low-level +math operations by using: -You can change this by using: + use Math::BigRat try => 'GMP'; - use Math::BigRat lib => 'BitVect'; +Note: This needs Math::BigInt::GMP installed. The following would first try to find Math::BigInt::Foo, then Math::BigInt::Bar, and when this also fails, revert to Math::BigInt::Calc: - use Math::BigRat lib => 'Foo,Math::BigInt::Bar'; + use Math::BigRat try => 'Foo,Math::BigInt::Bar'; -Calc.pm uses as internal format an array of elements of some decimal base -(usually 1e7, but this might be different for some systems) with the least -significant digit first, while BitVect.pm uses a bit vector of base 2, most -significant bit first. Other modules might use even different means of -representing the numbers. See the respective module documentation for further -details. +If you want to get warned when the fallback occurs, replace "try" with +"lib": -Currently the following replacement libraries exist, search for them at CPAN: + use Math::BigRat lib => 'Foo,Math::BigInt::Bar'; - Math::BigInt::BitVect - Math::BigInt::GMP - Math::BigInt::Pari - Math::BigInt::FastCalc +If you want the code to die instead, replace "try" with +"only": + + use Math::BigRat only => 'Foo,Math::BigInt::Bar'; =head1 METHODS @@ -1485,7 +1520,21 @@ Returns a copy of the denominator (the part under the line) as positive BigInt. Return a list consisting of (signed) numerator and (unsigned) denominator as BigInts. -=head2 as_int() +=head2 numify() + + my $y = $x->numify(); + +Returns the object as a scalar. This will lose some data if the object +cannot be represented by a normal Perl scalar (integer or float), so +use as_int() instead. + +This routine is automatically used whenever a scalar is required: + + my $x = Math::BigRat->new('3/1'); + @array = (1,2,3); + $y = $array[$x]; # set $y to 3 + +=head2 as_int()/as_number() $x = Math::BigRat->new('13/7'); print $x->as_int(),"\n"; # '1' @@ -1508,6 +1557,42 @@ Returns the BigRat as hexadecimal string. Works only for integers. Returns the BigRat as binary string. Works only for integers. +=head2 as_oct() + + $x = Math::BigRat->new('13'); + print $x->as_oct(),"\n"; # '015' + +Returns the BigRat as octal string. Works only for integers. + +=head2 from_hex()/from_bin()/from_oct() + + my $h = Math::BigRat->from_hex('0x10'); + my $b = Math::BigRat->from_bin('0b10000000'); + my $o = Math::BigRat->from_oct('020'); + +Create a BigRat from an hexadecimal, binary or octal number +in string form. + +=head2 length() + + $len = $x->length(); + +Return the length of $x in digitis for integer values. + +=head2 digit() + + print Math::BigRat->new('123/1')->digit(1); # 1 + print Math::BigRat->new('123/1')->digit(-1); # 3 + +Return the N'ths digit from X when X is an integer value. + +=head2 bnorm() + + $x->bnorm(); + +Reduce the number to the shortest form. This routine is called +automatically whenever it is needed. + =head2 bfac() $x->bfac(); @@ -1536,6 +1621,12 @@ Are not yet implemented. Set $x to the remainder of the division of $x by $y. +=head2 bneg() + + $x->bneg(); + +Used to negate the object in-place. + =head2 is_one() print "$x is 1\n" if $x->is_one(); @@ -1548,7 +1639,7 @@ Return true if $x is exactly one, otherwise false. Return true if $x is exactly zero, otherwise false. -=head2 is_pos() +=head2 is_pos()/is_positive() print "$x is >= 0\n" if $x->is_positive(); @@ -1557,7 +1648,7 @@ false. Please note that '+inf' is also positive, while 'NaN' and '-inf' aren't. C is an alias for C. -=head2 is_neg() +=head2 is_neg()/is_negative() print "$x is < 0\n" if $x->is_negative(); @@ -1604,7 +1695,53 @@ Truncate $x to an integer value. Calculate the square root of $x. -=head2 config +=head2 broot() + + $x->broot($n); + +Calculate the N'th root of $x. + +=head2 badd()/bmul()/bsub()/bdiv()/bdec()/binc() + +Please see the documentation in L. + +=head2 copy() + + my $z = $x->copy(); + +Makes a deep copy of the object. + +Please see the documentation in L for further details. + +=head2 bstr()/bsstr() + + my $x = Math::BigInt->new('8/4'); + print $x->bstr(),"\n"; # prints 1/2 + print $x->bsstr(),"\n"; # prints 1/2 + +Return a string representating this object. + +=head2 bacmp()/bcmp() + +Used to compare numbers. + +Please see the documentation in L for further details. + +=head2 blsft()/brsft() + +Used to shift numbers left/right. + +Please see the documentation in L for further details. + +=head2 bpow() + + $x->bpow($y); + +Compute $x ** $y. + +Please see the documentation in L for further details. + +=head2 config() use Data::Dumper; @@ -1683,6 +1820,6 @@ may contain more documentation and examples as well as testcases. =head1 AUTHORS -(C) by Tels L 2001 - 2005. +(C) by Tels L 2001 - 2007. =cut diff --git a/lib/Math/BigRat/t/bigrat.t b/lib/Math/BigRat/t/bigrat.t index 8310325..adab326 100755 --- a/lib/Math/BigRat/t/bigrat.t +++ b/lib/Math/BigRat/t/bigrat.t @@ -8,7 +8,7 @@ BEGIN $| = 1; chdir 't' if -d 't'; unshift @INC, '../lib'; # for running manually - plan tests => 185; + plan tests => 193; } # basic testing of Math::BigRat @@ -250,12 +250,12 @@ $x = $cr->new('NaN'); ok ($x->numify(), 'NaN'); $x = $cr->new('4/3'); ok ($x->numify(), 4/3); ############################################################################## -# as_hex(), as_bin() +# as_hex(), as_bin(), as_oct() $x = $cr->new('8/8'); -ok ($x->as_hex(), '0x1'); ok ($x->as_bin(), '0b1'); +ok ($x->as_hex(), '0x1'); ok ($x->as_bin(), '0b1'); ok ($x->as_oct(), '01'); $x = $cr->new('80/8'); -ok ($x->as_hex(), '0xa'); ok ($x->as_bin(), '0b1010'); +ok ($x->as_hex(), '0xa'); ok ($x->as_bin(), '0b1010'); ok ($x->as_oct(), '012'); ############################################################################## # broot(), blog(), bmodpow() and bmodinv() @@ -294,6 +294,24 @@ $x = $cr->new(12*12*12); ok ($x->copy()->broot('3'), 12, '(12*12*12) ** 1/3 = 12'); ############################################################################## +# from_hex(), from_bin(), from_oct() + +$x = Math::BigRat->from_hex('0x100'); +ok ($x, '256', 'from_hex'); +$x = $cr->from_hex('0x100'); +ok ($x, '256', 'from_hex'); + +$x = Math::BigRat->from_bin('0b100'); +ok ($x, '4', 'from_bin'); +$x = $cr->from_bin('0b100'); +ok ($x, '4', 'from_bin'); + +$x = Math::BigRat->from_oct('0100'); +ok ($x, '64', 'from_oct'); +$x = $cr->from_oct('0100'); +ok ($x, '64', 'from_oct'); + +############################################################################## # done 1;