#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use Math::Prime::Util qw/prime_count prime_count_lower prime_count_upper prime_count_approx/;
my %pivals = (
1000 => 168,
10000 => 1229,
100000 => 9592,
1000000 => 78498,
10000000 => 664579,
100000000 => 5761455,
1000000000 => 50847534,
10000000000 => 455052511,
100000000000 => 4118054813,
1000000000000 => 37607912018,
2000000000000 => 73301896139,
3000000000000 => 108340298703,
4000000000000 => 142966208126,
5000000000000 => 177291661649,
6000000000000 => 211381427039,
7000000000000 => 245277688804,
8000000000000 => 279010070811,
9000000000000 => 312600354108,
10000000000000 => 346065536839,
20000000000000 => 675895909271,
30000000000000 => 1000121668853,
40000000000000 => 1320811971702,
50000000000000 => 1638923764567,
60000000000000 => 1955010428258,
70000000000000 => 2269432871304,
80000000000000 => 2582444113487,
90000000000000 => 2894232250783,
100000000000000 => 3204941750802,
200000000000000 => 6270424651315,
300000000000000 => 9287441600280,
400000000000000 => 12273824155491,
500000000000000 => 15237833654620,
600000000000000 => 18184255291570,
700000000000000 => 21116208911023,
800000000000000 => 24035890368161,
900000000000000 => 26944926466221,
1000000000000000 => 29844570422669,
10000000000000000 => 279238341033925,
20000000000000000 => 547863431950008,
40000000000000000 => 1075292778753150,
100000000000000000 => 2623557157654233,
1000000000000000000 => 24739954287740860,
2000000000000000000 => 48645161281738535,
3000000000000000000 => 72254704797687083,
4000000000000000000 => 95676260903887607,
4185296581467695669 => 100000000000000000,
5000000000000000000 => 118959989688273472,
6000000000000000000 => 142135049412622144,
7000000000000000000 => 165220513980969424,
8000000000000000000 => 188229829247429504,
9000000000000000000 => 211172979243258278,
10000000000000000000 => 234057667276344607,
524288 => 43390,
1048576 => 82025,
2097152 => 155611,
4194304 => 295947,
8388608 => 564163,
16777216 => 1077871,
33554432 => 2063689,
67108864 => 3957809,
134217728 => 7603553,
268435456 => 14630843,
536870912 => 28192750,
1073741824 => 54400028,
2147483648 => 105097565,
4294967296 => 203280221,
8589934592 => 393615806,
17179869184 => 762939111,
34359738368 => 1480206279,
68719476736 => 2874398515,
137438953472 => 5586502348,
274877906944 => 10866266172,
549755813888 => 21151907950,
1099511627776 => 41203088796,
2199023255552 => 80316571436,
4398046511104 => 156661034233,
8796093022208 => 305761713237,
17592186044416 => 597116381732,
35184372088832 => 1166746786182,
70368744177664 => 2280998753949,
140737488355328 => 4461632979717,
281474976710656 => 8731188863470,
562949953421312 => 17094432576778,
1125899906842624 => 33483379603407,
2251799813685248 => 65612899915304,
4503599627370496 => 128625503610475,
9007199254740992 => 252252704148404,
18014398509481984 => 494890204904784,
36028797018963968 => 971269945245201,
72057594037927936 => 1906879381028850,
144115188075855872 => 3745011184713964,
288230376151711744 => 7357400267843990,
576460752303423488 => 14458792895301660,
1152921504606846976 => 28423094496953330,
2305843009213693952 => 55890484045084135,
4611686018427387904 => 109932807585469973,
9223372036854775808 => 216289611853439384,
# From http://trac.sagemath.org/ticket/7539 plus sieving
11000000000000000000 => 256890014776557326,
12000000000000000000 => 279675001309887227,
13000000000000000000 => 302416755645383081,
14000000000000000000 => 325118755759814408,
15000000000000000000 => 347783970566657581,
16000000000000000000 => 370414963651223281,
17000000000000000000 => 393013970558176111,
18000000000000000000 => 415582957615112220,
18400000000000000000 => 424602543873663577,
18440000000000000000 => 425504257754137607,
18446700000000000000 => 425655290520421050,
18446740000000000000 => 425656192205366999,
18446744000000000000 => 425656282373661946,
18446744030000000000 => 425656283049924141,
18446744040000000000 => 425656283275356419,
18446744050000000000 => 425656283500787632,
18446744070000000000 => 425656283951611098,
18446744073000000000 => 425656284019227775,
18446744073700000000 => 425656284035002496,
18446744073709000000 => 425656284035205391,
18446744073709550000 => 425656284035217706,
18446744073709551000 => 425656284035217730,
18446744073709551615 => 425656284035217743,
);
use Math::BigInt try=>"GMP,Pari";
plan tests => 3*scalar(keys %pivals);
foreach my $n (sort {$a <=> $b} keys %pivals) {
my $pin = $pivals{$n};
$n = Math::BigInt->new($n) if $n > ~0;
# stringify to work around Math::BigInt::GMP's stupid bug
cmp_ok( ''.prime_count_upper($n), '>=', $pin, "Pi($n) <= upper estimate" );
cmp_ok( ''.prime_count_lower($n), '<=', $pin, "Pi($n) >= lower estimate" );
# Result may be bigint, so turn into float for percentage comparison
my $approx = 0.0 + (''.prime_count_approx($n));
my $percent_limit = ($n > 1000000000000) ? 0.00005
: ($n > 10000000000) ? 0.0002
: ($n > 100000000) ? 0.002
: ($n > 1000000) ? 0.02
: 0.2;
cmp_ok( abs($pin - $approx) * (100.0 / $percent_limit), '<=', $pin, "prime_count_approx($n) within $percent_limit\% of Pi($n)");
}