summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Math/BigRat.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Math/BigRat.pm')
-rw-r--r--Master/tlpkg/tlperl/lib/Math/BigRat.pm106
1 files changed, 58 insertions, 48 deletions
diff --git a/Master/tlpkg/tlperl/lib/Math/BigRat.pm b/Master/tlpkg/tlperl/lib/Math/BigRat.pm
index 2460d1c7d4e..135645fc43a 100644
--- a/Master/tlpkg/tlperl/lib/Math/BigRat.pm
+++ b/Master/tlpkg/tlperl/lib/Math/BigRat.pm
@@ -6,16 +6,17 @@
# The following hash values are used:
# sign : +,-,NaN,+inf,-inf
# _d : denominator
-# _n : numeraotr (value = _n/_d)
+# _n : numerator (value = _n/_d)
# _a : accuracy
# _p : precision
# You should not look at the innards of a BigRat - use the methods for this.
package Math::BigRat;
-# anythig older is untested, and unlikely to work
+# anything older is untested, and unlikely to work
use 5.006;
use strict;
+use Carp ();
use Math::BigFloat;
use vars qw($VERSION @ISA $upgrade $downgrade
@@ -23,13 +24,22 @@ use vars qw($VERSION @ISA $upgrade $downgrade
@ISA = qw(Math::BigFloat);
-$VERSION = '0.24';
+$VERSION = '0.26_02';
$VERSION = eval $VERSION;
-use overload; # inherit overload from Math::BigFloat
+# inherit overload from Math::BigFloat, but disable the bitwise ops that don't
+# make much sense for rationals unless they're truncated or something first
+
+use overload
+ map {
+ my $op = $_;
+ ($op => sub {
+ Carp::croak("bitwise operation $op not supported in Math::BigRat");
+ });
+ } qw(& | ^ ~ << >> &= |= ^= <<= >>=);
BEGIN
- {
+ {
*objectify = \&Math::BigInt::objectify; # inherit this from BigInt
*AUTOLOAD = \&Math::BigFloat::AUTOLOAD; # can't inherit AUTOLOAD
# we inherit these from BigFloat because currently it is not possible
@@ -86,14 +96,14 @@ sub _new_from_float
{
# something like Math::BigRat->new('0.1');
# 1 / 1 => 1/10
- $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
+ $MBI->_lsft ( $self->{_d}, $f->{_e} ,10);
}
else
{
# something like Math::BigRat->new('10');
# 1 / 1 => 10/1
- $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
- $MBI->_is_zero($f->{_e});
+ $MBI->_lsft ( $self->{_n}, $f->{_e} ,10) unless
+ $MBI->_is_zero($f->{_e});
}
$self;
}
@@ -106,7 +116,7 @@ sub new
my ($n,$d) = @_;
my $self = { }; bless $self,$class;
-
+
# input like (BigInt) or (BigFloat):
if ((!defined $d) && (ref $n) && (!$n->isa('Math::BigRat')))
{
@@ -197,7 +207,7 @@ sub new
local $Math::BigFloat::accuracy = undef;
local $Math::BigFloat::precision = undef;
- # one of them looks like a float
+ # one of them looks like a float
my $nf = Math::BigFloat->new($n,undef,undef);
$self->{sign} = '+';
return $self->bnan() if $nf->is_nan();
@@ -247,7 +257,7 @@ sub new
$n = Math::BigInt->new($n,undef,undef) unless ref $n;
if ($n->{sign} =~ /^[+-]$/ && $d->{sign} =~ /^[+-]$/)
- {
+ {
# both parts are ok as integers (wierd things like ' 1e0'
$self->{_n} = $MBI->_copy($n->{value});
$self->{_d} = $MBI->_copy($d->{value});
@@ -380,7 +390,7 @@ sub bsstr
my $s = $x->{sign}; $s =~ s/^\+//; # +inf => inf
return $s;
}
-
+
my $s = ''; $s = $x->{sign} if $x->{sign} ne '+'; # +3 vs 3
$s . $MBI->_str($x->{_n}) . '/' . $MBI->_str($x->{_d});
}
@@ -416,7 +426,7 @@ sub bnorm
# reduce other numbers
my $gcd = $MBI->_copy($x->{_n});
$gcd = $MBI->_gcd($gcd,$x->{_d});
-
+
if (!$MBI->_is_one($gcd))
{
$x->{_n} = $MBI->_div($x->{_n},$gcd);
@@ -521,14 +531,14 @@ sub badd
return $x->bnan() if ($x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/);
# 1 1 gcd(3,4) = 1 1*3 + 1*4 7
- # - + - = --------- = --
+ # - + - = --------- = --
# 4 3 4*3 12
# we do not compute the gcd() here, but simple do:
# 5 7 5*3 + 7*4 43
- # - + - = --------- = --
+ # - + - = --------- = --
# 4 3 4*3 12
-
+
# and bnorm() will then take care of the rest
# 5 * 3
@@ -563,7 +573,7 @@ sub bsub
$x->{sign} =~ tr/+-/-+/
unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
$x->badd($y,@r); # does norm and round
- $x->{sign} =~ tr/+-/-+/
+ $x->{sign} =~ tr/+-/-+/
unless $x->{sign} eq '+' && $MBI->_is_zero($x->{_n}); # not -0
$x;
}
@@ -571,7 +581,7 @@ sub bsub
sub bmul
{
# multiply two rational numbers
-
+
# set up parameters
my ($self,$x,$y,@r) = (ref($_[0]),@_);
# objectify is costly, so avoid it
@@ -604,7 +614,7 @@ sub bmul
# 1 2 1 * 2 2 1
# - * - = ----- = - = -
# 4 3 4 * 3 12 6
-
+
$x->{_n} = $MBI->_mul( $x->{_n}, $y->{_n});
$x->{_d} = $MBI->_mul( $x->{_d}, $y->{_d});
@@ -640,11 +650,11 @@ sub bdiv
# 1 1 1 3
# - / - == - * -
# 4 3 4 1
-
+
$x->{_n} = $MBI->_mul( $x->{_n}, $y->{_d});
$x->{_d} = $MBI->_mul( $x->{_d}, $y->{_n});
- # compute new sign
+ # compute new sign
$x->{sign} = $x->{sign} eq $y->{sign} ? '+' : '-';
$x->bnorm()->round(@r);
@@ -674,14 +684,14 @@ sub bmod
my $u = bless { sign => '+' }, $self;
$u->{_n} = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d} );
$u->{_d} = $MBI->_mul( $MBI->_copy($x->{_d}), $y->{_n} );
-
+
# compute floor(u)
if (! $MBI->_is_one($u->{_d}))
{
$u->{_n} = $MBI->_div($u->{_n},$u->{_d}); # 22/7 => 3/1 w/ truncate
# no need to set $u->{_d} to 1, since below we set it to $y->{_d} anyway
}
-
+
# now compute $y * $u
$u->{_d} = $MBI->_copy($y->{_d}); # 1 * $y->{_d}, see floor above
$u->{_n} = $MBI->_mul($u->{_n},$y->{_n});
@@ -728,7 +738,7 @@ sub binc
{
# increment value (add 1)
my ($self,$x,@r) = ref($_[0]) ? (ref($_[0]),@_) : objectify(1,@_);
-
+
return $x if $x->{sign} !~ /^[+-]$/; # NaN, inf, -inf
if ($x->{sign} eq '-')
@@ -827,7 +837,7 @@ sub denominator
return Math::BigInt->new($x->{sign}) if $x->{sign} eq 'NaN';
# inf, -inf
return Math::BigInt->bone() if $x->{sign} !~ /^[+-]$/;
-
+
Math::BigInt->new($MBI->_str($x->{_d}));
}
@@ -961,7 +971,7 @@ sub bpow
if ($x->{sign} eq '-')
{
# - * - => +, - * - * - => -
- $x->{sign} = '+' if $MBI->_is_even($y->{_n});
+ $x->{sign} = '+' if $MBI->_is_even($y->{_n});
}
return $x->round(@r);
}
@@ -977,7 +987,7 @@ sub bpow
if ($x->{sign} eq '-')
{
# - * - => +, - * - * - => -
- $x->{sign} = '+' if $MBI->_is_even($y->{_n});
+ $x->{sign} = '+' if $MBI->_is_even($y->{_n});
}
return $x->round(@r);
}
@@ -1230,7 +1240,7 @@ sub bmodinv
}
# $x or $y are NaN or +-inf => NaN
- return $x->bnan()
+ return $x->bnan()
if $x->{sign} !~ /^[+-]$/ || $y->{sign} !~ /^[+-]$/;
if ($x->is_int() && $y->is_int())
@@ -1276,7 +1286,7 @@ sub bsqrt
$x->{_n} = $MBI->_copy( $x->{_n}->{_m} ); # 710/45.1 => 710/451
}
- # convert parts to $MBI again
+ # convert parts to $MBI again
$x->{_n} = $MBI->_lsft( $MBI->_copy( $x->{_n}->{_m} ), $x->{_n}->{_e}, 10)
if ref($x->{_n}) ne $MBI && ref($x->{_n}) ne 'ARRAY';
$x->{_d} = $MBI->_lsft( $MBI->_copy( $x->{_d}->{_m} ), $x->{_d}->{_e}, 10)
@@ -1288,7 +1298,7 @@ sub bsqrt
sub blsft
{
my ($self,$x,$y,$b,@r) = objectify(3,@_);
-
+
$b = 2 unless defined $b;
$b = $self->new($b) unless ref ($b);
$x->bmul( $b->copy()->bpow($y), @r);
@@ -1328,8 +1338,8 @@ sub bfround
sub bcmp
{
- # compare two signed numbers
-
+ # compare two signed numbers
+
# set up parameters
my ($self,$x,$y) = (ref($_[0]),@_);
# objectify is costly, so avoid it
@@ -1358,7 +1368,7 @@ sub bcmp
return 0 if $xz && $yz; # 0 <=> 0
return -1 if $xz && $y->{sign} eq '+'; # 0 <=> +y
return 1 if $yz && $x->{sign} eq '+'; # +x <=> 0
-
+
my $t = $MBI->_mul( $MBI->_copy($x->{_n}), $y->{_d});
my $u = $MBI->_mul( $MBI->_copy($y->{_n}), $x->{_d});
@@ -1370,7 +1380,7 @@ sub bcmp
sub bacmp
{
# compare two numbers (as unsigned)
-
+
# set up parameters
my ($self,$x,$y) = (ref($_[0]),@_);
# objectify is costly, so avoid it
@@ -1400,7 +1410,7 @@ sub numify
{
# convert 17/8 => float (aka 2.125)
my ($self,$x) = ref($_[0]) ? (undef,$_[0]) : objectify(1,@_);
-
+
return $x->bstr() if $x->{sign} !~ /^[+-]$/; # inf, NaN, etc
# N/1 => N
@@ -1416,7 +1426,7 @@ sub as_number
# NaN, inf etc
return Math::BigInt->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
-
+
my $u = Math::BigInt->bzero();
$u->{sign} = $x->{sign};
$u->{value} = $MBI->_div( $MBI->_copy($x->{_n}), $x->{_d}); # 22/7 => 3
@@ -1434,7 +1444,7 @@ sub as_float
# NaN, inf etc
return Math::BigFloat->new($x->{sign}) if $x->{sign} !~ /^[+-]$/;
-
+
my $u = Math::BigFloat->bzero();
$u->{sign} = $x->{sign};
# n
@@ -1571,7 +1581,7 @@ sub import
# register us with MBI to get notified of future lib changes
Math::BigInt::_register_callback( $self, sub { $MBI = $_[0]; } );
-
+
# any non :constant stuff is handled by our parent, Exporter (loaded
# by Math::BigFloat, even if @_ is empty, to give it a chance
$self->SUPER::import(@a); # for subclasses
@@ -1593,7 +1603,7 @@ Math::BigRat - Arbitrary big rational numbers
my $x = Math::BigRat->new('3/7'); $x += '5/9';
print $x->bstr(),"\n";
- print $x ** 2,"\n";
+ print $x ** 2,"\n";
my $y = Math::BigRat->new('inf');
print "$y ", ($y->is_inf ? 'is' : 'is not') , " infinity\n";
@@ -1664,7 +1674,7 @@ Create a new Math::BigRat object. Input can come in various forms:
Returns a copy of the numerator (the part above the line) as signed BigInt.
=head2 denominator()
-
+
$d = $x->denominator();
Returns a copy of the denominator (the part under the line) as positive BigInt.
@@ -1717,21 +1727,21 @@ This method was added in v0.22 of Math::BigRat (April 2008).
$x = Math::BigRat->new('13');
print $x->as_hex(),"\n"; # '0xd'
-Returns the BigRat as hexadecimal string. Works only for integers.
+Returns the BigRat as hexadecimal string. Works only for integers.
=head2 as_bin()
$x = Math::BigRat->new('13');
print $x->as_bin(),"\n"; # '0x1101'
-Returns the BigRat as binary 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.
+Returns the BigRat as octal string. Works only for integers.
=head2 from_hex()/from_bin()/from_oct()
@@ -1746,7 +1756,7 @@ in string form.
$len = $x->length();
-Return the length of $x in digitis for integer values.
+Return the length of $x in digits for integer values.
=head2 digit()
@@ -1849,19 +1859,19 @@ Set $x to the next bigger integer value (e.g. truncate the number to integer
and then increment it by one).
=head2 bfloor()
-
+
$x->bfloor();
Truncate $x to an integer value.
=head2 bsqrt()
-
+
$x->bsqrt();
Calculate the square root of $x.
=head2 broot()
-
+
$x->broot($n);
Calculate the N'th root of $x.
@@ -1884,7 +1894,7 @@ Please see the documentation in L<Math::BigInt> for further details.
print $x->bstr(),"\n"; # prints 1/2
print $x->bsstr(),"\n"; # prints 1/2
-Return a string representating this object.
+Return a string representing this object.
=head2 bacmp()/bcmp()