Skip to content

Commit

Permalink
- Improved the speed of Math.pi() for very large number of digits of PI.
Browse files Browse the repository at this point in the history
Example:
	say Math.pi(10000);	 # is now considerably faster
  • Loading branch information
trizen committed Aug 21, 2015
1 parent e689281 commit 852c857
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion lib/Sidef/Math/Math.pm
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,39 @@ package Sidef::Math::Math {

sub pi {
my ($self, $places) = @_;
Sidef::Types::Number::Number->new(Math::BigFloat->new(0)->bpi(defined($places) ? $places->get_value : ()));

$places = defined($places) ? $places->get_value : undef;

# For large accuracy, the arctan formulas become very inefficient with
# Math::BigFloat. Switch to Brent-Salamin (aka AGM or Gauss-Legendre).
if (defined($places) and $places >= 1000) {

# Code by Dana Jacobsen from RosettaCode
# http://rosettacode.org/wiki/Arithmetic-geometric_mean/Calculate_Pi#Perl

my $acc = $places + 8;
my $HALF = Math::BigFloat->new('0.5');

my $an = Math::BigFloat->bone;
my $bn = $HALF->copy->bsqrt($acc);
my $tn = $HALF->copy->bmul($HALF);
my $pn = Math::BigFloat->bone;

while ($pn < $acc) {
my $prev_an = $an->copy;
$an->badd($bn)->bmul($HALF, $acc);
$bn->bmul($prev_an)->bsqrt($acc);
$prev_an->bsub($an);
$tn->bsub($pn * $prev_an * $prev_an);
$pn->badd($pn);
}
$an->badd($bn);
$an->bmul($an, $acc)->bdiv($tn->bmul(4), $places);

return Sidef::Types::Number::Number->new($an);
}

Sidef::Types::Number::Number->new(Math::BigFloat->bpi(defined($places) ? $places : ()));
}

*PI = \&pi;
Expand Down

0 comments on commit 852c857

Please sign in to comment.