require 5.006002;
require Exporter;
-@ISA = qw(Math::BigInt);
+@ISA = qw/Math::BigInt/;
+@EXPORT_OK = qw/bpi/;
use strict;
# $_trap_inf/$_trap_nan are internal and should never be accessed from outside
}
###############################################################################
+# trigonometric functions
+
+# helper function for bpi()
+
+sub _signed_sub
+ {
+ my ($a, $s, $b) = @_;
+
+ if ($s == 0)
+ {
+ # $a and $b are negativ: -> add
+ $MBI->_add($a, $b);
+ }
+ else
+ {
+ my $c = $MBI->_acmp($a,$b);
+ # $a positiv, $b negativ
+ if ($c >= 0)
+ {
+ $MBI->_sub($a,$b);
+ }
+ else
+ {
+ # make negativ
+ $a = $MBI->_sub( $MBI->_copy($b), $a);
+ $s = 0;
+ }
+ }
+
+ ($a,$s);
+ }
+
+sub _signed_add
+ {
+ my ($a, $s, $b) = @_;
+
+ if ($s == 1)
+ {
+ # $a and $b are positiv: -> add
+ $MBI->_add($a, $b);
+ }
+ else
+ {
+ my $c = $MBI->_acmp($a,$b);
+ # $a positiv, $b negativ
+ if ($c >= 0)
+ {
+ $MBI->_sub($a,$b);
+ }
+ else
+ {
+ # make positiv
+ $a = $MBI->_sub( $MBI->_copy($b), $a);
+ $s = 1;
+ }
+ }
+
+ ($a,$s);
+ }
+
+sub bpi
+ {
+ # Calculate PI to N digits (including the 3 before the dot).
+
+ # The basic algorithm is the one implemented in:
+
+ # The Computer Language Shootout
+ # http://shootout.alioth.debian.org/
+ #
+ # contributed by Robert Bradshaw
+ # modified by Ruud H.G.van Tol
+ # modified by Emanuele Zeppieri
+
+ # We re-implement it here by using the low-level library directly. Also,
+ # the functions consume() and extract_digit() were inlined and some
+ # rendundand operations ( like *= 1 ) were removed.
+
+ my ($self,$n) = @_;
+ if (@_ == 1)
+ {
+ # called like Math::BigFloat::bpi(10);
+ $n = $self; $self = $class;
+ }
+ $self = ref($self) if ref($self);
+ $n = 40 if !defined $n || $n < 1;
+
+ my $z0 = $MBI->_one();
+ my $z1 = $MBI->_zero();
+ my $z2 = $MBI->_one();
+ my $ten = $MBI->_ten();
+ my $three = $MBI->_new(3);
+ my ($s, $d, $e, $r); my $k = 0; my $z1_sign = 0;
+
+ # main loop
+ for (1..$n)
+ {
+ while ( 1 < 3 )
+ {
+ if ($MBI->_acmp($z0,$z2) != 1)
+ {
+ # my $o = $z0 * 3 + $z1;
+ my $o = $MBI->_mul( $MBI->_copy($z0), $three);
+ $z1_sign == 0 ? $MBI->_sub( $o, $z1) : $MBI->_add( $o, $z1);
+ ($d,$r) = $MBI->_div( $MBI->_copy($o), $z2 );
+ $d = $MBI->_num($d);
+ $e = $MBI->_num( scalar $MBI->_div( $MBI->_add($o, $z0), $z2 ) );
+ last if $d == $e;
+ }
+ $k++;
+ my $k2 = $MBI->_new( 2*$k+1 );
+ # mul works regardless of the sign of $z1 since $k is always positive
+ $MBI->_mul( $z1, $k2 );
+ ($z1, $z1_sign) = _signed_add($z1, $z1_sign, $MBI->_mul( $MBI->_new(4*$k+2), $z0 ) );
+ $MBI->_mul( $z0, $MBI->_new($k) );
+ $MBI->_mul( $z2, $k2 );
+ }
+ $MBI->_mul( $z1, $ten );
+ ($z1, $z1_sign) = _signed_sub($z1, $z1_sign, $MBI->_mul( $MBI->_new(10*$d), $z2 ) );
+ $MBI->_mul( $z0, $ten );
+ $s .= $d;
+ }
+
+ my $x = $self->new(0);
+ $x->{_es} = '-';
+ $x->{_e} = $MBI->_new(length($s)-1);
+ $x->{_m} = $MBI->_new($s);
+
+ $x;
+ }
+
+###############################################################################
# rounding functions
sub bfround
# 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
- # even if @_ is empty, to give it a chance
- $self->SUPER::import(@a); # for subclasses
- $self->export_to_level(1,$self,@a); # need this, too
+
+ $self->export_to_level(1,$self,@a); # export wanted functions
}
sub bnorm
use Math::BigFloat;
# Number creation
- $x = Math::BigFloat->new($str); # defaults to 0
- $nan = Math::BigFloat->bnan(); # create a NotANumber
- $zero = Math::BigFloat->bzero(); # create a +0
- $inf = Math::BigFloat->binf(); # create a +inf
- $inf = Math::BigFloat->binf('-'); # create a -inf
- $one = Math::BigFloat->bone(); # create a +1
- $one = Math::BigFloat->bone('-'); # create a -1
+ my $x = Math::BigFloat->new($str); # defaults to 0
+ my $y = $x->copy(); # make a true copy
+ my $nan = Math::BigFloat->bnan(); # create a NotANumber
+ my $zero = Math::BigFloat->bzero(); # create a +0
+ my $inf = Math::BigFloat->binf(); # create a +inf
+ my $inf = Math::BigFloat->binf('-'); # create a -inf
+ my $one = Math::BigFloat->bone(); # create a +1
+ my $mone = Math::BigFloat->bone('-'); # create a -1
+
+ my $pi = Math::BigFloat->bpi(100); # PI to 100 digits
# Testing
$x->is_zero(); # true if arg is +0
This method was added in v1.84 of Math::BigInt (April 2007).
+=head2 bpi()
+
+ print Math::BigFloat->bpi(100), "\n";
+
+Calculate PI to N digits (including the 3 before the dot).
+
+This method was added in v1.87 of Math::BigInt (June 2007).
+
=head1 Autocreating constants
After C<use Math::BigFloat ':constant'> all the floating point constants
However, this request is ignored, as the current code now uses the low-level
math libary for directly storing the number parts.
+=head1 EXPORTS
+
+C<Math::BigFloat> exports nothing by default, but can export the C<bpi()> method:
+
+ use Math::BigFloat qw/bpi/;
+
+ print bpi(10), "\n";
+
=head1 BUGS
Please see the file BUGS in the CPAN distribution Math::BigInt for known bugs.
}
###############################################################################
+# trigonometric functions
+
+sub bpi
+ {
+ # Calculate PI to N digits. Unless upgrading is in effect, returns the
+ # result truncated to an integer, that is, always returns '3'.
+ my ($self,$n) = @_;
+ if (@_ == 1)
+ {
+ # called like Math::BigInt::bpi(10);
+ $n = $self; $self = $class;
+ }
+ $self = ref($self) if ref($self);
+
+ return $upgrade->new($n) if defined $upgrade;
+
+ # hard-wired to "3"
+ $self->new(3);
+ }
+
+###############################################################################
# this method returns 0 if the object can be modified, or 1 if not.
# We use a fast constant sub() here, to avoid costly calls. Subclasses
# may override it with special code (f.i. Math::BigInt::Constant does so)
my $n = 1; my $sign = '-';
# Number creation
- $x = Math::BigInt->new($str); # defaults to 0
- $y = $x->copy(); # make a true copy
- $nan = Math::BigInt->bnan(); # create a NotANumber
- $zero = Math::BigInt->bzero(); # create a +0
- $inf = Math::BigInt->binf(); # create a +inf
- $inf = Math::BigInt->binf('-'); # create a -inf
- $one = Math::BigInt->bone(); # create a +1
- $one = Math::BigInt->bone('-'); # create a -1
+ my $x = Math::BigInt->new($str); # defaults to 0
+ my $y = $x->copy(); # make a true copy
+ my $nan = Math::BigInt->bnan(); # create a NotANumber
+ my $zero = Math::BigInt->bzero(); # create a +0
+ my $inf = Math::BigInt->binf(); # create a +inf
+ my $inf = Math::BigInt->binf('-'); # create a -inf
+ my $one = Math::BigInt->bone(); # create a +1
+ my $mone = Math::BigInt->bone('-'); # create a -1
+
+ my $pi = Math::BigInt->bpi(); # returns '3'
+ # see Math::BigFloat::bpi()
$h = Math::BigInt->new('0x123'); # from hexadecimal
$b = Math::BigInt->new('0b101'); # from binary
This method was added in v1.84 of Math::BigInt (April 2007).
+=head2 bpi()
+
+ print Math::BigInt->bpi(100), "\n"; # 3
+
+Returns PI truncated to an integer, with the argument being ignored. that
+is it always returns C<3>.
+
+If upgrading is in effect, returns PI to N digits (including the "3"
+before the dot):
+
+ use Math::BigFloat;
+ use Math::BigInt upgrade => Math::BigFloat;
+ print Math::BigInt->bpi(3), "\n"; # 3.14
+ print Math::BigInt->bpi(100), "\n"; # 3.1415....
+
+This method was added in v1.87 of Math::BigInt (June 2007).
+
=head2 blsft()
$x->blsft($y); # left shift in base 2
arguments are of the class mentioned in $upgrade (This might change in later
versions to a more sophisticated scheme):
+=head1 EXPORTS
+
+C<Math::BigInt> exports nothing by default, but can export the following methods:
+
+ bgcd
+ blcm
+
=head1 BUGS
=over 2