—# Copyright 2012, 2013, 2014, 2016, 2019, 2020 Kevin Ryde
# This file is part of Math-NumSeq.
#
# Math-NumSeq is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3, or (at your option) any later
# version.
#
# Math-NumSeq is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Math-NumSeq. If not, see <http://www.gnu.org/licenses/>.
package
Math::NumSeq::LemoineCount;
use
5.004;
use
strict;
$VERSION
= 75;
@ISA
= (
'Math::NumSeq'
);
*_is_infinite
= \
&Math::NumSeq::_is_infinite
;
use
Math::NumSeq::Primes;
# uncomment this to run the ### lines
#use Smart::Comments;
# use constant name => Math::NumSeq::__('Lemoine Count');
use
constant
description
=> Math::NumSeq::__(
'The number of ways i can be represented as P+2*Q for primes P and Q.'
);
[
{
name
=>
'on_values'
,
share_key
=>
'on_values_odd'
,
type
=>
'enum'
,
default
=>
'all'
,
choices
=> [
'all'
,
'odd'
],
choices_display
=> [Math::NumSeq::__(
'All'
),
Math::NumSeq::__(
'Odd'
)],
description
=> Math::NumSeq::__(
'The values to act on, either all integers of just the odd integers.'
),
},
];
#-----------------------------------------------------------------------------
# "one_as_prime" secret undocumented parameter ...
# some sort of odd i only option too maybe ...
#
# A046925 ways 2n+1, including 1 as a prime
# A046927 ways 2n+1, not including 1 as a prime
# A194831 records of A046927
# A194830 positions of records
my
%oeis_anum
= (
all
=> [
'A046924'
,
# ways n, including 1 as a prime
'A046926'
,
# ways n, not including 1 as a prime
],
odd
=> [
'A046925'
,
# ways n, including 1 as a prime
'A046927'
,
# ways n, not including 1 as a prime
],
);
# OEIS-Catalogue: A046926
# OEIS-Catalogue: A046924 one_as_prime=1
# OEIS-Catalogue: A046927 on_values=odd # starting n=0 for odd=1
# OEIS-Catalogue: A046925 on_values=odd one_as_prime=1
sub
oeis_anum {
my
(
$self
) =
@_
;
return
$oeis_anum
{
$self
->{
'on_values'
}}->[!
$self
->{
'one_as_prime'
}];
}
#-----------------------------------------------------------------------------
sub
rewind {
my
(
$self
) =
@_
;
### LemoineCount rewind() ...
$self
->{
'i_start'
} = (
$self
->{
'on_values'
} eq
'odd'
? 0 : 1);
$self
->{
'i'
} =
$self
->i_start;
$self
->{
'a'
} = 1;
$self
->{
'array'
} = [];
$self
->{
'size'
} = 500;
}
sub
next
{
my
(
$self
) =
@_
;
### next(): "i=$self->{'i'}"
for
(;;) {
unless
(@{
$self
->{
'array'
}}) {
$self
->{
'size'
} =
int
(1.08 *
$self
->{
'size'
});
my
$lo
=
$self
->{
'a'
};
my
$hi
=
$lo
+
$self
->{
'size'
};
$self
->{
'next_lo'
} =
$hi
+1;
### range: "lo=$lo to hi=$hi"
my
@array
;
$array
[
$hi
-
$lo
] = 0;
# array size
$self
->{
'array'
} = \
@array
;
my
@primes
= ((
$self
->{
'one_as_prime'
} ? (1) : ()),
Math::NumSeq::Primes::_primes_list (0,
$hi
));
{
my
$qamax
=
$#primes
;
foreach
my
$pa
(0 ..
$#primes
-1) {
foreach
my
$qa
(
reverse
$pa
..
$qamax
) {
my
$sum
=
$primes
[
$pa
] + 2
*$primes
[
$qa
];
### at: "p=$primes[$pa] q=$primes[$qa] sum=$sum incr ".($sum-$lo)
if
(
$sum
>
$hi
) {
$qamax
=
$qa
-1;
}
elsif
(
$sum
<
$lo
) {
last
;
}
else
{
$array
[
$sum
-
$lo
]++;
}
}
}
}
{
my
$qamax
=
$#primes
;
foreach
my
$pa
(0 ..
$#primes
-1) {
foreach
my
$qa
(
reverse
$pa
+1 ..
$qamax
) {
my
$sum
= 2
*$primes
[
$pa
] +
$primes
[
$qa
];
### at: "p=$primes[$pa] q=$primes[$qa] sum=$sum incr ".($sum-$lo)
if
(
$sum
>
$hi
) {
$qamax
=
$qa
-1;
}
elsif
(
$sum
<
$lo
) {
last
;
}
else
{
$array
[
$sum
-
$lo
]++;
}
}
}
}
### @array
}
my
$a
=
$self
->{
'a'
}++;
my
$value
=
shift
@{
$self
->{
'array'
}} || 0;
if
(
$self
->{
'on_values'
} eq
'odd'
&& !(
$a
&1)) {
next
;
}
return
(
$self
->{
'i'
}++,
$value
);
}
}
sub
ith {
my
(
$self
,
$i
) =
@_
;
### ith(): $i
if
(
$self
->{
'on_values'
} eq
'odd'
) {
$i
= 2
*$i
+1;
}
if
(
$i
< 3) {
return
0;
}
unless
(
$i
>= 0 &&
$i
<= 0xFF_FFFF) {
return
undef
;
}
$i
=
"$i"
;
# numize any Math::BigInt for speed
my
$count
= 0;
my
@primes
= ((
$self
->{
'one_as_prime'
} ? (1) : ()),
Math::NumSeq::Primes::_primes_list (0,
$i
-1));
### @primes
{
my
$pa
= 0;
my
$qa
=
$#primes
;
while
(
$pa
<=
$qa
) {
my
$sum
=
$primes
[
$pa
] + 2
*$primes
[
$qa
];
if
(
$sum
<=
$i
) {
### at: "p=$primes[$pa] q=$primes[$qa] count ".($sum == $i)
$count
+= (
$sum
==
$i
);
$pa
++;
}
else
{
$qa
--;
}
}
}
{
my
$pa
= 0;
my
$qa
=
$#primes
;
while
(
$pa
<
$qa
) {
my
$sum
= 2
*$primes
[
$pa
] +
$primes
[
$qa
];
if
(
$sum
<=
$i
) {
### at: "p=$primes[$pa] q=$primes[$qa] count ".($sum == $i)
$count
+= (
$sum
==
$i
);
$pa
++;
}
else
{
$qa
--;
}
}
}
return
$count
;
}
1;
__END__
=for stopwords Ryde Math-NumSeq Lemoine ie
=head1 NAME
Math::NumSeq::LemoineCount -- number of representations as P+2*Q for primes P,Q
=head1 SYNOPSIS
use Math::NumSeq::LemoineCount;
my $seq = Math::NumSeq::LemoineCount->new;
my ($i, $value) = $seq->next;
=head1 DESCRIPTION
This is a count of how many ways i can be represented as P+2*Q for primes
P,Q, starting from i=1.
0, 0, 0, 0, 0, 1, 1, 1, 2, 0, 2, 1, 2, 0, 2, 1, 4, 0, ...
starting i=1
For example i=6 can only be written 2+2*2 so just 1 way. But i=9 is 3+2*3=9
and 5+2*2=9 so 2 ways.
=head2 Odd Numbers
Option C<on_values =E<gt> 'odd'> gives the count on just the odd numbers,
starting i=0 for number of ways "1" can be expressed (none),
0, 0, 0, 1, 2, 2, 2, 2, 4, 2, 3, 3, 3, 4, 4, 2, 5, 3, 4, ...
starting i=0
Lemoine conjectured circa 1894 that all odd i E<gt>= 7 can be represented as
P+2*Q, which would be a count here always E<gt>=1.
=head2 Even Numbers
Even numbers i are not particularly interesting. An even number must have P
even, ie. P=2, so i=2+2*Q for count
count(even i) = 1 if i/2-1 is prime
= 0 if not
=head1 FUNCTIONS
See L<Math::NumSeq/FUNCTIONS> for behaviour common to all sequence classes.
=over 4
=item C<$seq = Math::NumSeq::LemoineCount-E<gt>new ()>
=item C<$seq = Math::NumSeq::LemoineCount-E<gt>new (on_values =E<gt> 'odd')>
Create and return a new sequence object.
=back
=head2 Random Access
=over
=item C<$value = $seq-E<gt>ith($i)>
Return the sequence value at C<$i>, being the number of ways C<$i> can be
represented as P+2*Q for primes P,Q. or with the C<on_values=E<gt>'odd'>
option the number of ways for C<2*$i+1>.
This requires checking all primes up to C<$i> or C<2*$i+1> and the current
code has a hard limit of 2**24 in the interests of not going into a
near-infinite loop.
=back
=head1 SEE ALSO
L<Math::NumSeq>,
L<Math::NumSeq::Primes>,
L<Math::NumSeq::GoldbachCount>
=head1 HOME PAGE
=head1 LICENSE
Copyright 2012, 2013, 2014, 2016, 2019, 2020 Kevin Ryde
Math-NumSeq is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
Math-NumSeq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
Math-NumSeq. If not, see <http://www.gnu.org/licenses/>.
=cut