File Coverage

blib/lib/Math/NumSeq/PolignacObstinate.pm
Criterion Covered Total %
statement 69 70 98.5
branch 11 12 91.6
condition 7 9 77.7
subroutine 16 16 100.0
pod 3 3 100.0
total 106 110 96.3


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              
19             # cf
20             # http://mathworld.wolfram.com/dePolignacsConjecture.html
21             # consecutive primes difference is every even number infinitely many times
22              
23             # 1,
24             # 127, 149, 251, 331,
25             # 337, 373, 509, 599,
26             # 701, 757, 809, 877,
27             # 905, 907, 959, 977,
28             # 997,
29              
30             package Math::NumSeq::PolignacObstinate;
31 2     2   7250 use 5.004;
  2         5  
32 2     2   6 use strict;
  2         3  
  2         42  
33              
34 2     2   7 use vars '$VERSION', '@ISA';
  2         2  
  2         98  
35             $VERSION = 72;
36 2     2   344 use Math::NumSeq;
  2         3  
  2         64  
37             @ISA = ('Math::NumSeq');
38             *_is_infinite = \&Math::NumSeq::_is_infinite;
39              
40 2     2   330 use Math::NumSeq::Primes; # for primes_list()
  2         3  
  2         41  
41 2     2   8 use Math::Prime::XS 'is_prime';
  2         2  
  2         97  
42              
43             # uncomment this to run the ### lines
44             #use Smart::Comments;
45              
46              
47             # use constant name => Math::NumSeq::__('Polignac Obstinate');
48 2     2   8 use constant description => Math::NumSeq::__('Odd integers N not representable as prime+2^k.');
  2         16  
  2         7  
49 2     2   7 use constant values_min => 1;
  2         2  
  2         70  
50 2     2   6 use constant characteristic_increasing => 1;
  2         2  
  2         71  
51 2     2   7 use constant characteristic_integer => 1;
  2         2  
  2         67  
52 2     2   6 use constant i_start => 1;
  2         2  
  2         63  
53              
54             # cf A133122 - demanding k>0, so 1,3,127,... as 3 no longer representable
55             # A065381 - primes not p+2^k k>=0, filtering from odds to primes
56             #
57 2     2   6 use constant oeis_anum => 'A006285'; # with k>=0 so 1,127,...
  2         3  
  2         711  
58              
59              
60             sub rewind {
61 6     6 1 353 my ($self) = @_;
62 6         26 $self->{'i'} = $self->i_start;
63 6         10 $self->{'string'} = '';
64 6         21 vec($self->{'string'},3/2,1) = 1; # 2+2^0=3
65 6         10 $self->{'done'} = -1;
66 6         16 _resieve ($self, 20);
67             }
68              
69             sub _resieve {
70 45     45   63 my ($self, $hi) = @_;
71             ### _resieve() ...
72              
73 45         48 $self->{'hi'} = $hi;
74 45         45 my $sref = \$self->{'string'};
75 45         168 vec($$sref,$hi,1) = 0; # pre-extend
76 45         196 my @primes = Math::NumSeq::Primes::_primes_list (3, $hi-1);
77 45         5310 for (my $power = 2; $power < $hi; $power *= 2) {
78 390         379 foreach my $p (@primes) {
79 347606 100       307901 if ((my $v = $p + $power) > $hi) {
80 344         1067 last;
81             } else {
82 347262         392626 vec($$sref,$v/2,1) = 1;
83             }
84             }
85             }
86             }
87              
88             sub next {
89 3004     3004 1 7814 my ($self) = @_;
90             ### Obstinate next(): $self->{'i'}
91              
92 3004         2059 my $v = $self->{'done'};
93 3004         1941 my $sref = \$self->{'string'};
94 3004         1860 my $hi = $self->{'hi'};
95              
96 3004         1716 for (;;) {
97             ### consider: "v=".($v+1)." cf done=$self->{'done'}"
98 48041 100       48941 if (($v+=2) > $hi) {
99             _resieve ($self,
100 39         73 $hi = ($self->{'hi'} *= 2));
101             }
102 48041 100       54658 unless (vec($$sref,$v/2,1)) {
103             return ($self->{'i'}++,
104 3004         4472 $self->{'done'} = $v);
105             }
106             }
107             }
108              
109             sub pred {
110 96078     96078 1 312374 my ($self, $value) = @_;
111             ### Obstinate pred(): $value
112              
113 96078 50 33     228374 unless ($value >= 0 && $value <= 0xFFFF_FFFF) {
114 0         0 return undef;
115             }
116 96078 100 100     337981 if ($value != int($value)
      100        
117             || $value < 127
118             || ($value % 2) == 0) {
119 48352         58873 return ($value == 1);
120             }
121 47726         30627 $value = "$value"; # numize Math::BigInt for speed
122              
123             # Maybe an is_any_prime(...)
124 47726         66867 for (my $power = 2; $power < $value; $power *= 2) {
125 216735 100       439228 if (is_prime($value - $power)) {
126 44727         45025 return 0;
127             }
128             }
129 2999         2839 return 1;
130             }
131              
132             1;
133             __END__