File Coverage

blib/lib/Math/NumSeq/ErdosSelfridgeClass.pm
Criterion Covered Total %
statement 79 80 98.7
branch 12 14 85.7
condition 9 12 75.0
subroutine 21 21 100.0
pod 5 6 83.3
total 126 133 94.7


line stmt bran cond sub pod time code
1             # Copyright 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::ErdosSelfridgeClass;
19 2     2   212799 use 5.004;
  2         8  
  2         112  
20 2     2   14 use strict;
  2         4  
  2         73  
21 2     2   768 use Math::NumSeq::Primes;
  2         3  
  2         72  
22              
23 2     2   12 use vars '$VERSION', '@ISA';
  2         3  
  2         192  
24             $VERSION = 71;
25              
26 2     2   9 use Math::NumSeq;
  2         4  
  2         90  
27             @ISA = ('Math::NumSeq');
28              
29 2     2   557 use Math::NumSeq::PrimeFactorCount;;
  2         5  
  2         104  
30             *_prime_factors = \&Math::NumSeq::PrimeFactorCount::_prime_factors;
31              
32             # uncomment this to run the ### lines
33             #use Smart::Comments;
34              
35              
36             # use constant name => Math::NumSeq::__('Erdos-Selfridge Class');
37 2     2   11 use constant description => Math::NumSeq::__('Erdos-Selfridge class of a prime.');
  2         4  
  2         10  
38 2     2   9 use constant default_i_start => 1;
  2         4  
  2         82  
39 2     2   8 use constant characteristic_integer => 1;
  2         3  
  2         70  
40 2     2   9 use constant characteristic_increasing => 0;
  2         6  
  2         82  
41 2     2   8 use constant characteristic_non_decreasing => 0;
  2         4  
  2         60  
42 2     2   8 use constant characteristic_smaller => 1;
  2         8  
  2         81  
43 2     2   9 use constant values_min => 0;
  2         4  
  2         417  
44              
45 2         12 use constant parameter_info_array =>
46             [
47             { name => 'p_or_m',
48             display => Math::NumSeq::__('+/-'),
49             type => 'enum',
50             default => '+',
51             choices => ['+','-'],
52             choices_display => [Math::NumSeq::__('+'),
53             Math::NumSeq::__('-')],
54             description => Math::NumSeq::__('Class + or -, factorizing p+1 or p-1 respectively in the classification.'),
55             },
56             { name => 'on_values',
57             share_key => 'on_values_primes',
58             display => Math::NumSeq::__('On Values'),
59             type => 'enum',
60             default => 'all',
61             choices => ['all','primes'],
62             choices_display => [Math::NumSeq::__('All'),
63             Math::NumSeq::__('Primes')],
64             description => Math::NumSeq::__('Values to classify, either all integers or just the primes.'),
65             },
66 2     2   9 ];
  2         3  
67              
68             #------------------------------------------------------------------------------
69              
70             # cf A098661 cumulative class+
71             # A005109 1-, Pierpont
72             # A005110 2-
73             # A005111 3-
74             # A005112 4-
75             # A081424 5-
76             # A081425 6-
77             # A081640 12-
78             # A129248 14-
79             # A129249 15-
80             # A129250 16-
81             # A005105 1+
82             # A005106 2+
83             # A005107 3+
84             # A005108 4+
85             # A081633 5+
86             # ...
87             # A081639 11+
88             # A084071 12+
89             # A090468 13+
90             # A129474 14+
91             # A129475 15+
92             # A178382 in both k+ and k- for some k
93             # A005113 least prime in class n+
94             # A056637 least prime of class n-
95             # A129470 where largest factor of p+1 isn't largest class
96             # A129469 first prime of class n+ in A129470
97             # A129471 3+ with largest factor of p+1 not in 2+
98             # A129472 4+ with largest factor of p+1 not in 3+
99             #
100             my %oeis_anum = ('+' => { 'primes' => 'A126433', # class+ of primes
101             'all' => 'A078442',
102             },
103             '-' => { 'primes' => 'A126805', # class- of primes
104             });
105             # OEIS-Catalogue: A126433 on_values=primes
106             # OEIS-Catalogue: A126805 on_values=primes p_or_m=-
107             sub oeis_anum {
108 3     3 1 14 my ($self) = @_;
109 3         12 return $oeis_anum{$self->{'p_or_m'}}->{$self->{'on_values'}};
110             }
111              
112             #------------------------------------------------------------------------------
113              
114             sub rewind {
115 11     11 1 2716 my ($self) = @_;
116 11         53 $self->{'i'} = $self->i_start;
117 11 100       126 if ($self->{'on_values'} eq 'primes') {
118 3         19 $self->{'seq'} = Math::NumSeq::Primes->new;
119             }
120             }
121             sub next {
122 126     126 1 2149 my ($self) = @_;
123 126         243 my $i = $self->{'i'}++;
124 126         319 my $value;
125 126 100       279 if (my $seq = $self->{'seq'}) {
126 42         165 (undef, $value) = $self->{'seq'}->next;
127             } else {
128 84         106 $value = $i;
129             }
130 126         267 return ($i, _classify($self,$value));
131             }
132              
133             sub ith {
134 134     134 1 404 my ($self, $i) = @_;
135 134 50       325 if ($self->{'on_values'} eq 'primes') {
136 0         0 return undef; # no i'th prime yet
137             }
138 134         262 return _classify($self,$i);
139             }
140             sub can {
141 500     500 0 25279 my ($class_or_self, $method) = @_;
142 500 100 100     2791 if (($method eq 'ith' || $method eq 'seek_to_i')
      66        
      100        
143             && ref $class_or_self
144             && $class_or_self->{'on_values'} eq 'primes') {
145 4         14 return undef;
146             }
147 496         1537 return $class_or_self->SUPER::can($method);
148             }
149              
150             sub _classify {
151 260     260   372 my ($self, $i) = @_;
152              
153 260 100       868 Math::NumSeq::Primes->pred($i)
154             or return 0;
155              
156 124 100       355 my $offset = ($self->{'p_or_m'} eq '+' ? 1 : -1);
157 124         214 my $ret = 0;
158 124         238 my @this = ($i);
159 124         338 while (@this) {
160 171         249 $ret++;
161 171         200 my %next;
162 171         279 foreach my $prime (@this) {
163 175         653 my ($good, @primes) = _prime_factors($prime + $offset);
164 175 50       425 return undef unless $good;
165              
166 175         932 @next{@primes} = (); # hash slice, for uniq
167             }
168 171         414 delete @next{2,3}; # hash slice, not 2 or 3
169 171         690 @this = keys %next;
170             }
171 124         459 return $ret;
172             }
173              
174             sub pred {
175 63     63 1 307 my ($self, $value) = @_;
176 63   33     242 return ($value >= 0
177             && $value == int($value));
178             }
179              
180             1;
181             __END__