1package Math::Prime::Util::PrimeIterator;
2use strict;
3use warnings;
4
5BEGIN {
6  $Math::Prime::Util::PrimeIterator::AUTHORITY = 'cpan:DANAJ';
7  $Math::Prime::Util::PrimeIterator::VERSION = '0.73';
8}
9
10use base qw( Exporter );
11our @EXPORT_OK = qw( );
12our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
13
14
15use Math::Prime::Util qw/next_prime prev_prime is_prime prime_count nth_prime/;
16
17# We're going to use a scalar rather than a hash because there is currently
18# only one data object (the current value) and this makes it little faster.
19
20sub new {
21  my ($class, $start) = @_;
22  my $p = 2;
23  my $self = bless \$p, $class;
24  $self->rewind($start) if defined $start;
25  return $self;
26}
27
28# To make Iterator::Simple happy.
29sub __iter__ {
30  my $self = shift;
31  require Iterator::Simple;
32  return Iterator::Simple::iterator(sub { $self->iterate });
33  $self;
34}
35
36sub value { ${$_[0]}; }
37sub next {
38  #my $self = shift;  $$self = next_prime($$self);  return $self;
39  ${$_[0]} = next_prime(${$_[0]});
40  return $_[0];
41}
42sub prev {
43  my $self = shift;
44  my $p = $$self;
45  $$self = ($p <= 2) ? 2 : prev_prime($p);
46  return $self;
47}
48sub iterate {
49  #my $self = shift;  my $p = $$self;  $$self = next_prime($p);  return $p;
50  my $p = ${$_[0]};
51  ${$_[0]} = next_prime(${$_[0]});
52  return $p;
53}
54
55sub rewind {
56  my ($self, $start) = @_;
57  $$self = 2;
58  if (defined $start && $start ne '2') {
59    Math::Prime::Util::_validate_num($start)
60      || Math::Prime::Util::_validate_positive_integer($start);
61    $$self = next_prime($start-1) if $start > 2;
62  }
63  return $self;
64}
65
66sub peek {
67  return next_prime(${$_[0]});
68}
69
70# Some methods to match Math::NumSeq
71sub tell_i {
72  return prime_count(${$_[0]});
73}
74sub pred {
75  my($self, $n) = @_;
76  return is_prime($n);
77}
78sub ith {
79  my($self, $n) = @_;
80  return nth_prime($n);
81}
82sub seek_to_i {
83  my($self, $n) = @_;
84  $self->rewind( nth_prime($n) );
85}
86sub seek_to_value {
87  my($self, $n) = @_;
88  $self->rewind($n);
89}
90sub value_to_i {
91  my($self, $n) = @_;
92  return unless is_prime($n);
93  return prime_count($n);
94}
95sub value_to_i_ceil {
96  my($self, $n) = @_;
97  return prime_count(next_prime($n-1));
98}
99sub value_to_i_floor {
100  my($self, $n) = @_;
101  return prime_count($n);
102}
103sub value_to_i_estimate {
104  my($self, $n) = @_;
105  return Math::Prime::Util::prime_count_approx($n);
106}
107sub i_start     { 1 }
108sub description { "The prime numbers 2, 3, 5, 7, 11, 13, 17, etc." }
109sub values_min  { 2 }
110sub values_max  { undef }
111sub oeis_anum   { "A000040" }
1121;
113
114__END__
115
116
117# ABSTRACT: An object iterator for primes
118
119=pod
120
121=for stopwords prev pred ith i'th
122
123=for test_synopsis use v5.14;  my ($i,$n) = (2,2);
124
125=head1 NAME
126
127Math::Prime::Util::PrimeIterator - An object iterator for primes
128
129
130=head1 VERSION
131
132Version 0.73
133
134
135=head1 SYNOPSIS
136
137  use Math::Prime::Util::PrimeIterator;
138  my $it = Math::Prime::Util::PrimeIterator->new();
139
140  # Simple use: return current value and move forward.
141  my $sum = 0;  $sum += $it->iterate() for 1..10000;
142
143  # Methods
144  my $v = $it->value();     # Return current value
145  $it->next();              # Move to next prime (returns self)
146  $it->prev();              # Move to prev prime (returns self)
147  $v = $it->iterate();      # Returns current value; moves to next prime
148  $it->rewind();            # Resets position to 2
149  $it->rewind($n);          # Resets position to next_prime($n-1)
150
151  # Methods similar to Math::NumSeq, do not change iterator
152  $it->tell_i();            # Returns the index of the current position
153  $it->pred($n);            # Returns true if $n is prime
154  $it->ith($i);             # Returns the $ith prime
155  $it->value_to_i($n);      # Returns the index of the first prime >= $n
156  $it->value_to_i_estimate($n);  # Approx index of value $n
157
158  # Methods similar to Math::NumSeq, changes iterator
159  $it->seek_to_i($i);       # Resets position to the $ith prime
160  $it->seek_to_value($i);   # Resets position to next_prime($i-1)
161
162=head1 DESCRIPTION
163
164An iterator over the primes.  L</new> returns an iterator object and takes
165an optional starting position (the initial value will be the least prime
166greater than or equal to the argument).  BigInt objects will be returned if
167the value overflows a Perl unsigned integer value.
168
169=head1 METHODS
170
171=head2 new
172
173Creates an iterator object with initial value of 2.  If an argument is
174given, the initial value will be the least prime greater than or equal
175to the argument.
176
177=head2 value
178
179Returns the value at the current position.  Will always be a prime.  If
180the value is greater than ~0, it will be a L<Math::BigInt> object.
181
182=head2 next
183
184Moves the current position to the next prime.
185Returns self so calls can be chained.
186
187=head2 prev
188
189Moves the current position to the previous prime, unless the current
190value is 2, in which case the value remains 2.
191Returns self so calls can be chained.
192
193=head2 iterate
194
195Returns the value at the current position and also moves the position to
196the next prime.
197
198=head2 rewind
199
200Resets the current position to either 2 or, if given an integer argument,
201the least prime not less than the argument.
202
203=head2 peek
204
205Returns the value at the next position without moving the iterator.
206
207=head2 tell_i
208
209Returns the index of the current position, starting at 1 (corresponding to
210the value 2).
211The iterator is unchanged after this call.
212
213=head2 pred
214
215Returns true if the argument is a prime, false otherwise.
216The iterator is unchanged after this call.
217
218=head2 ith
219
220Returns the i'th prime, where the first prime is 2.
221The iterator is unchanged after this call.
222
223=head2 value_to_i_estimate
224
225Returns an estimate of the index corresponding to the argument.  That is,
226given a value C<n>, we expect a prime approximately equal to C<n> to occur
227at this index.
228
229The estimate is performed using L<Math::Prime::Util/prime_count_approx>,
230which uses the estimates of Dusart 2010 (or better for small values).
231
232=head2 value_to_i
233
234If the argument is prime, returns the corresponding index, such that:
235
236  ith( value_to_i( $n ) ) == $n
237
238Returns C<undef> if the argument is not prime.
239
240=head2 value_to_i_floor
241
242=head2 value_to_i_ceil
243
244Returns the index corresponding to the first prime less than or equal
245to the argument, or greater than or equal to the argument, respectively.
246
247=head2 seek_to_i
248
249Resets the position to the prime corresponding to the given index.
250
251=head2 seek_to_value
252
253An alias for L</rewind>.
254
255=head2 i_start
256=head2 description
257=head2 values_min
258=head2 values_max
259=head2 oeis_anum
260
261Methods to match Math::NumSeq::Primes.
262
263=head1 SEE ALSO
264
265L<Math::Prime::Util>
266
267L<Math::Prime::Util/forprimes>
268
269L<Math::Prime::Util/prime_iterator>
270
271L<Math::Prime::Util/prime_iterator_object>
272
273L<Math::Prime::Util::PrimeArray>
274
275L<Math::NumSeq::Primes>
276
277L<List::Gen>
278
279=head1 AUTHORS
280
281Dana Jacobsen E<lt>dana@acm.orgE<gt>
282
283
284=head1 COPYRIGHT
285
286Copyright 2013 by Dana Jacobsen E<lt>dana@acm.orgE<gt>
287
288This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
289
290=cut
291