line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright 2010, 2011, 2012, 2013, 2014 Kevin Ryde |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# This file is part of Math-NumSeq. |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# Math-NumSeq is free software; you can redistribute it and/or modify |
6
|
|
|
|
|
|
|
# it under the terms of the GNU General Public License as published by the |
7
|
|
|
|
|
|
|
# Free Software Foundation; either version 3, or (at your option) any later |
8
|
|
|
|
|
|
|
# version. |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# Math-NumSeq is distributed in the hope that it will be useful, but |
11
|
|
|
|
|
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
12
|
|
|
|
|
|
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
13
|
|
|
|
|
|
|
# for more details. |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License along |
16
|
|
|
|
|
|
|
# with Math-NumSeq. If not, see . |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
package Math::NumSeq::Primes; |
19
|
11
|
|
|
11
|
|
12750
|
use 5.004; |
|
11
|
|
|
|
|
35
|
|
|
11
|
|
|
|
|
435
|
|
20
|
11
|
|
|
11
|
|
58
|
use strict; |
|
11
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
364
|
|
21
|
11
|
|
|
11
|
|
7644
|
use POSIX (); |
|
11
|
|
|
|
|
75666
|
|
|
11
|
|
|
|
|
338
|
|
22
|
11
|
|
|
11
|
|
7755
|
use Math::Prime::XS 0.23 'is_prime'; # version 0.23 fix for 1928099 |
|
11
|
|
|
|
|
981054
|
|
|
11
|
|
|
|
|
706
|
|
23
|
|
|
|
|
|
|
|
24
|
11
|
|
|
11
|
|
97
|
use vars '$VERSION', '@ISA'; |
|
11
|
|
|
|
|
22
|
|
|
11
|
|
|
|
|
641
|
|
25
|
|
|
|
|
|
|
$VERSION = 71; |
26
|
11
|
|
|
11
|
|
1540
|
use Math::NumSeq; |
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
585
|
|
27
|
|
|
|
|
|
|
@ISA = ('Math::NumSeq'); |
28
|
|
|
|
|
|
|
*_is_infinite = \&Math::NumSeq::_is_infinite; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# uncomment this to run the ### lines |
31
|
|
|
|
|
|
|
# use Smart::Comments; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# use constant name => Math::NumSeq::__('Prime Numbers'); |
35
|
11
|
|
|
11
|
|
55
|
use constant description => Math::NumSeq::__('The prime numbers 2, 3, 5, 7, 11, 13, 17, etc.'); |
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
52
|
|
36
|
11
|
|
|
11
|
|
55
|
use constant characteristic_increasing => 1; |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
465
|
|
37
|
11
|
|
|
11
|
|
69
|
use constant characteristic_integer => 1; |
|
11
|
|
|
|
|
19
|
|
|
11
|
|
|
|
|
412
|
|
38
|
11
|
|
|
11
|
|
51
|
use constant values_min => 2; |
|
11
|
|
|
|
|
19
|
|
|
11
|
|
|
|
|
445
|
|
39
|
11
|
|
|
11
|
|
52
|
use constant i_start => 1; |
|
11
|
|
|
|
|
18
|
|
|
11
|
|
|
|
|
501
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
42
|
|
|
|
|
|
|
# cf A010051 - characteristic boolean 0 or 1 according as N is prime |
43
|
|
|
|
|
|
|
# A051006 characteristic as binary fraction, in decimal |
44
|
|
|
|
|
|
|
# A051007 characteristic as binary fraction, continued fraction |
45
|
|
|
|
|
|
|
# A000720 - pi(n) num primes <= n |
46
|
|
|
|
|
|
|
# A018252 - the non-primes |
47
|
|
|
|
|
|
|
# A002476 - primes 3k+1, which is also 6k+1 |
48
|
|
|
|
|
|
|
# |
49
|
11
|
|
|
11
|
|
54
|
use constant oeis_anum => 'A000040'; # primes |
|
11
|
|
|
|
|
23
|
|
|
11
|
|
|
|
|
455
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
52
|
|
|
|
|
|
|
|
53
|
11
|
|
|
11
|
|
57
|
use constant 1.02; # for leading underscore |
|
11
|
|
|
|
|
212
|
|
|
11
|
|
|
|
|
588
|
|
54
|
11
|
|
|
|
|
16
|
use constant _MAX_PRIME_XS => do { |
55
|
11
|
|
|
|
|
18
|
my $umax = POSIX::UINT_MAX() / 2; |
56
|
|
|
|
|
|
|
# if ($umax > 0x8000_0000) { |
57
|
|
|
|
|
|
|
# $umax = 0x8000_0000; |
58
|
|
|
|
|
|
|
# } |
59
|
11
|
|
|
|
|
5368
|
$umax; |
60
|
11
|
|
|
11
|
|
53
|
}; |
|
11
|
|
|
|
|
20
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub rewind { |
63
|
98
|
|
|
98
|
1
|
746
|
my ($self) = @_; |
64
|
98
|
|
|
|
|
622
|
$self->{'i'} = $self->i_start; |
65
|
98
|
|
|
|
|
334
|
$self->{'array_lo'} = 1; |
66
|
98
|
|
|
|
|
161
|
$self->{'array_hi'} = 1; |
67
|
98
|
|
|
|
|
151
|
@{$self->{'array'}} = (); |
|
98
|
|
|
|
|
386
|
|
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
# needs a prime_count() for arbitrary seek |
70
|
|
|
|
|
|
|
# |
71
|
|
|
|
|
|
|
# sub _UNTESTED__seek_to_value { |
72
|
|
|
|
|
|
|
# my ($self, $value) = @_; |
73
|
|
|
|
|
|
|
# my $array = $self->{'array'}; |
74
|
|
|
|
|
|
|
# if (@array) { |
75
|
|
|
|
|
|
|
# if ($value >= $array->[0] && $value <= $array->[-1]) { |
76
|
|
|
|
|
|
|
# # seek forward within $array |
77
|
|
|
|
|
|
|
# while ($value > $array->[0]) { |
78
|
|
|
|
|
|
|
# shift @$array; |
79
|
|
|
|
|
|
|
# $self->{'i'}++; |
80
|
|
|
|
|
|
|
# } |
81
|
|
|
|
|
|
|
# return; |
82
|
|
|
|
|
|
|
# } |
83
|
|
|
|
|
|
|
# } |
84
|
|
|
|
|
|
|
# $value = int($value); |
85
|
|
|
|
|
|
|
# if ($value > _MAX_PRIME_XS) { |
86
|
|
|
|
|
|
|
# # past limit |
87
|
|
|
|
|
|
|
# $self->{'array'} = undef; |
88
|
|
|
|
|
|
|
# return; |
89
|
|
|
|
|
|
|
# } |
90
|
|
|
|
|
|
|
# $self->{'i'} = _primes_count(0,$value); |
91
|
|
|
|
|
|
|
# $self->{'array_lo'} = 0; |
92
|
|
|
|
|
|
|
# $self->{'array_hi'} = $value-1; |
93
|
|
|
|
|
|
|
# @{$self->{'array'}} = (); |
94
|
|
|
|
|
|
|
# } |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub next { |
97
|
1606
|
|
|
1606
|
1
|
5046
|
my ($self) = @_; |
98
|
|
|
|
|
|
|
|
99
|
1606
|
|
|
|
|
2278
|
while (! @{$self->{'array'}}) { |
|
1691
|
|
|
|
|
8015
|
|
100
|
|
|
|
|
|
|
# fill array |
101
|
85
|
|
|
|
|
179
|
my $lo = $self->{'array_lo'}; |
102
|
85
|
|
|
|
|
220
|
my $hi = $self->{'array_hi'}; |
103
|
|
|
|
|
|
|
|
104
|
85
|
|
|
|
|
184
|
$lo = $self->{'array_lo'} = $hi+1; |
105
|
85
|
50
|
|
|
|
243
|
if ($lo > _MAX_PRIME_XS) { |
106
|
0
|
|
|
|
|
0
|
return; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
85
|
|
|
|
|
189
|
my $len = int ($lo / 2); |
110
|
85
|
50
|
|
|
|
203
|
if ($len > 100_000) { |
111
|
0
|
|
|
|
|
0
|
$len = 100_000; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
85
|
|
|
|
|
205
|
$hi = $lo + $len; |
115
|
85
|
100
|
|
|
|
205
|
if ($hi < 500) { |
116
|
73
|
|
|
|
|
1643
|
$hi = 500; |
117
|
|
|
|
|
|
|
} |
118
|
85
|
50
|
|
|
|
212
|
if ($hi > _MAX_PRIME_XS) { |
119
|
0
|
|
|
|
|
0
|
$hi = _MAX_PRIME_XS; |
120
|
|
|
|
|
|
|
} |
121
|
85
|
|
|
|
|
166
|
$self->{'array_hi'} = $hi; |
122
|
|
|
|
|
|
|
|
123
|
85
|
|
|
|
|
249
|
@{$self->{'array'}} = _primes_list ($lo, $hi); |
|
85
|
|
|
|
|
1015165
|
|
124
|
|
|
|
|
|
|
} |
125
|
1606
|
|
|
|
|
3955
|
return ($self->{'i'}++, shift @{$self->{'array'}}); |
|
1606
|
|
|
|
|
7385
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub _primes_list { |
131
|
246
|
|
|
246
|
|
663
|
my ($lo, $hi) = @_; |
132
|
|
|
|
|
|
|
### _my_primes_list: "$lo to $hi" |
133
|
246
|
50
|
|
|
|
703
|
if ($lo < 0) { |
134
|
0
|
|
|
|
|
0
|
$lo = 0; |
135
|
|
|
|
|
|
|
} |
136
|
246
|
50
|
|
|
|
578
|
if ($hi > _MAX_PRIME_XS) { |
137
|
0
|
|
|
|
|
0
|
$hi = _MAX_PRIME_XS; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
246
|
50
|
|
|
|
513
|
if ($hi < $lo) { |
141
|
|
|
|
|
|
|
# Math::Prime::XS errors out if hi
|
142
|
0
|
|
|
|
|
0
|
return; |
143
|
|
|
|
|
|
|
} |
144
|
246
|
|
|
|
|
1200
|
return Math::Prime::XS::sieve_primes ($lo, $hi); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub pred { |
148
|
5271
|
|
|
5271
|
1
|
48328
|
my ($self, $value) = @_; |
149
|
|
|
|
|
|
|
### pred(): "$value" |
150
|
|
|
|
|
|
|
|
151
|
5271
|
100
|
66
|
|
|
14039
|
if (_is_infinite($value) || $value > 0xFFFF_FFFF) { |
152
|
2
|
|
|
|
|
481
|
return undef; |
153
|
|
|
|
|
|
|
} |
154
|
5269
|
100
|
100
|
|
|
22712
|
if ($value != int($value) || $value < 0) { |
155
|
2031
|
|
|
|
|
13668
|
return 0; |
156
|
|
|
|
|
|
|
} |
157
|
3238
|
|
|
|
|
22804
|
return is_prime($value); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# sub ith { |
161
|
|
|
|
|
|
|
# my ($self, $i) = @_; |
162
|
|
|
|
|
|
|
# my $array = $self->{'array'}; |
163
|
|
|
|
|
|
|
# if ($i > $#$array) { |
164
|
|
|
|
|
|
|
# my $hi = int ($i/log($i) * 2 + 5); |
165
|
|
|
|
|
|
|
# do { |
166
|
|
|
|
|
|
|
# $array = $self->{'array'} = [ undef, _my_primes_list (0, $hi) ]; |
167
|
|
|
|
|
|
|
# $hi *= 2; |
168
|
|
|
|
|
|
|
# } while ($i > $#$array); |
169
|
|
|
|
|
|
|
# } |
170
|
|
|
|
|
|
|
# return $array->[$i]; |
171
|
|
|
|
|
|
|
# } |
172
|
|
|
|
|
|
|
|
173
|
11
|
|
|
11
|
|
7551
|
use Math::NumSeq::Fibonacci; |
|
11
|
|
|
|
|
28
|
|
|
11
|
|
|
|
|
1599
|
|
174
|
|
|
|
|
|
|
*_blog2_estimate = \&Math::NumSeq::Fibonacci::_blog2_estimate; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub value_to_i_estimate { |
177
|
235
|
|
|
235
|
1
|
3376
|
my ($self, $value) = @_; |
178
|
|
|
|
|
|
|
### value_to_i_estimate(): "$value" |
179
|
|
|
|
|
|
|
|
180
|
235
|
100
|
|
|
|
498
|
if ($value < 2) { return 0; } |
|
83
|
|
|
|
|
237
|
|
181
|
|
|
|
|
|
|
|
182
|
152
|
|
|
|
|
1227
|
$value = int($value); |
183
|
152
|
100
|
|
|
|
628
|
if (defined (my $blog2 = _blog2_estimate($value))) { |
184
|
|
|
|
|
|
|
# est = v/log(v) |
185
|
|
|
|
|
|
|
# log2(v) = log(v)/log(2) |
186
|
|
|
|
|
|
|
# est = v/((log2(v)*log(2))) |
187
|
|
|
|
|
|
|
# = v/log2(v) * 1/log(2) |
188
|
|
|
|
|
|
|
# ~= v/log2(v) * 13/9 |
189
|
|
|
|
|
|
|
# ~= (13*v) / (9*log2(v)) |
190
|
|
|
|
|
|
|
# using 13/9 as an approximation to 1/log(2) to stay in BigInt |
191
|
|
|
|
|
|
|
# |
192
|
|
|
|
|
|
|
### $blog2 |
193
|
|
|
|
|
|
|
### num: $value*13 |
194
|
|
|
|
|
|
|
### den: 9 * $blog2 |
195
|
12
|
|
|
|
|
4801
|
return ($value * 13) / (9 * $blog2); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
### log: log($value) |
199
|
|
|
|
|
|
|
### div: $value/log($value) |
200
|
140
|
|
|
|
|
718
|
return int($value/log($value)); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
1; |
204
|
|
|
|
|
|
|
__END__ |