File Coverage

blib/lib/Math/NumSeq/PolignacObstinate.pm
Criterion Covered Total %
statement 70 71 98.5
branch 11 12 91.6
condition 7 9 77.7
subroutine 16 16 100.0
pod 3 3 100.0
total 107 111 96.4


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   18921 use 5.004;
  2         11  
  2         105  
32 2     2   14 use strict;
  2         4  
  2         82  
33              
34 2     2   11 use vars '$VERSION', '@ISA';
  2         5  
  2         140  
35             $VERSION = 71;
36 2     2   889 use Math::NumSeq;
  2         4  
  2         235  
37             @ISA = ('Math::NumSeq');
38             *_is_infinite = \&Math::NumSeq::_is_infinite;
39              
40 2     2   677 use Math::NumSeq::Primes; # for primes_list()
  2         6  
  2         79  
41 2     2   13 use Math::Prime::XS 'is_prime';
  2         5  
  2         151  
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   11 use constant description => Math::NumSeq::__('Odd integers N not representable as prime+2^k.');
  2         26  
  2         12  
49 2     2   11 use constant values_min => 1;
  2         9  
  2         85  
50 2     2   11 use constant characteristic_increasing => 1;
  2         3  
  2         88  
51 2     2   11 use constant characteristic_integer => 1;
  2         3  
  2         101  
52 2     2   9 use constant i_start => 1;
  2         4  
  2         89  
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   10 use constant oeis_anum => 'A006285'; # with k>=0 so 1,127,...
  2         4  
  2         1574  
58              
59              
60             sub rewind {
61 6     6 1 245 my ($self) = @_;
62 6         46 $self->{'i'} = $self->i_start;
63 6         16 $self->{'string'} = '';
64 6         26 vec($self->{'string'},3/2,1) = 1; # 2+2^0=3
65 6         19 $self->{'done'} = -1;
66 6         21 _resieve ($self, 20);
67             }
68              
69             sub _resieve {
70 45     45   82 my ($self, $hi) = @_;
71             ### _resieve() ...
72              
73 45         78 $self->{'hi'} = $hi;
74 45         88 my $sref = \$self->{'string'};
75 45         242 vec($$sref,$hi,1) = 0; # pre-extend
76 45         248 my @primes = Math::NumSeq::Primes::_primes_list (3, $hi-1);
77 45         11104 for (my $power = 2; $power < $hi; $power *= 2) {
78 390         686 foreach my $p (@primes) {
79 347606 100       569969 if ((my $v = $p + $power) > $hi) {
80 344         2268 last;
81             } else {
82 347262         803005 vec($$sref,$v/2,1) = 1;
83             }
84             }
85             }
86             }
87              
88             sub next {
89 3004     3004 1 15051 my ($self) = @_;
90             ### Obstinate next(): $self->{'i'}
91              
92 3004         8530 my $v = $self->{'done'};
93 3004         4602 my $sref = \$self->{'string'};
94 3004         3722 my $hi = $self->{'hi'};
95              
96 3004         2847 for (;;) {
97             ### consider: "v=".($v+1)." cf done=$self->{'done'}"
98 48041 100       82433 if (($v+=2) > $hi) {
99 39         153 _resieve ($self,
100             $hi = ($self->{'hi'} *= 2));
101             }
102 48041 100       85587 unless (vec($$sref,$v/2,1)) {
103 3004         18018 return ($self->{'i'}++,
104             $self->{'done'} = $v);
105             }
106             }
107             }
108              
109             sub pred {
110 96078     96078 1 612121 my ($self, $value) = @_;
111             ### Obstinate pred(): $value
112              
113 96078 50 33     418654 unless ($value >= 0 && $value <= 0xFFFF_FFFF) {
114 0         0 return undef;
115             }
116 96078 100 100     12628560 if ($value != int($value)
      100        
117             || $value < 127
118             || ($value % 2) == 0) {
119 48352         3781244 return ($value == 1);
120             }
121 47726         74128 $value = "$value"; # numize Math::BigInt for speed
122              
123             # Maybe an is_any_prime(...)
124 47726         124526 for (my $power = 2; $power < $value; $power *= 2) {
125 216735 100       13623922 if (is_prime($value - $power)) {
126 44727         114378 return 0;
127             }
128             }
129 2999         6616 return 1;
130             }
131              
132             1;
133             __END__