File Coverage

blib/lib/Math/NumSeq/Emirps.pm
Criterion Covered Total %
statement 51 52 98.0
branch 6 8 75.0
condition 6 6 100.0
subroutine 15 15 100.0
pod 5 5 100.0
total 83 86 96.5


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             package Math::NumSeq::Emirps;
19 2     2   7115 use 5.004;
  2         5  
20 2     2   7 use strict;
  2         3  
  2         40  
21              
22 2     2   6 use vars '$VERSION', '@ISA';
  2         2  
  2         92  
23             $VERSION = 72;
24 2     2   338 use Math::NumSeq;
  2         3  
  2         35  
25 2     2   359 use Math::NumSeq::Primes;
  2         3  
  2         85  
26             @ISA = ('Math::NumSeq');
27             *_is_infinite = \&Math::NumSeq::_is_infinite;
28              
29              
30             # uncomment this to run the ### lines
31             #use Smart::Comments;
32              
33             # use constant name => Math::NumSeq::__('Emirps');
34 2     2   8 use constant description => Math::NumSeq::__('Numbers which are primes forwards and backwards, eg. 157 because both 157 and 751 are primes. Palindromes like 131 are excluded. Default is decimal, or select a radix.');
  2         2  
  2         5  
35              
36             use Math::NumSeq::Base::Digits
37 2     2   318 'parameter_info_array'; # radix parameter
  2         2  
  2         84  
38              
39 2     2   8 use constant characteristic_increasing => 1;
  2         0  
  2         72  
40 2     2   8 use constant characteristic_integer => 1;
  2         2  
  2         648  
41              
42             # FIXME: find the first value in the sequence ... maybe save it
43             my @values_min;
44             $values_min[2] = 11; # binary 1011 reverse 1101 is decimal 13
45             $values_min[10] = 13; # reverse to 31
46             sub values_min {
47 1     1 1 6 my ($self) = @_;
48 1         13 return $values_min[$self->{'radix'}];
49             }
50              
51             #------------------------------------------------------------------------------
52             # A006567 - decimal reversal is a prime and different
53             # A007500 - decimal reversal is a prime, so palindromes which are primes too
54             #
55             my @oeis_anum;
56             $oeis_anum[2] = 'A080790';
57             $oeis_anum[10] = 'A006567';
58             # OEIS-Catalogue: A080790 radix=2
59             # OEIS-Catalogue: A006567 radix=10
60             sub oeis_anum {
61 1     1 1 3 my ($self) = @_;
62 1         2 return $oeis_anum[$self->{'radix'}];
63             }
64              
65             #------------------------------------------------------------------------------
66              
67             sub rewind {
68 4     4 1 605 my ($self) = @_;
69 4         15 $self->{'i'} = $self->i_start;
70 4         16 $self->{'primes_seq'} = Math::NumSeq::Primes->new;
71             }
72              
73             # ENHANCE-ME: The commented out code below took blocks of primes by radix
74             # powers and filtered. More memory but faster.
75             #
76             # ENHANCE-ME: No need to examine blocks where the high digit is even, or
77             # where it has a common factor with the radix.
78             #
79             sub next {
80 100     100 1 509 my ($self) = @_;
81              
82 100         70 my $primes_seq = $self->{'primes_seq'};
83              
84 100         59 for (;;) {
85 392 50       480 (undef, my $prime) = $primes_seq->next
86             or return;
87 392         384 my $rev = _reverse_in_radix($prime,$self->{'radix'});
88              
89             ### consider: $prime
90             ### $rev
91              
92 392 100 100     824 if ($rev != $prime && $self->Math::NumSeq::Primes::pred($rev)) {
93             ### yes ...
94 100         168 return ($self->{'i'}++, $prime);
95             }
96             }
97             }
98              
99             # ENHANCE-ME: are_all_prime() to look for small divisors in both values
100             # simultaneously, in case the reversal is even etc and easily excluded.
101             sub pred {
102 2007     2007 1 4958 my ($self, $value) = @_;
103 2007 50       2338 if (_is_infinite($value)) {
104 0         0 return 0;
105             }
106 2007         2266 my $rev = _reverse_in_radix($value,$self->{'radix'});
107             return ($rev != $value
108             && $self->Math::NumSeq::Primes::pred($value)
109 2007   100     4799 && $self->Math::NumSeq::Primes::pred(_reverse_in_radix($value,$self->{'radix'})));
110             }
111              
112             # return $n reversed in $radix
113             sub _reverse_in_radix {
114 2599     2599   1821 my ($n, $radix) = @_;
115              
116 2599 100       2742 if ($radix == 10) {
117 2597         4556 return scalar(reverse("$n"));
118             } else {
119 2         3 my $ret = $n*0; # inherit bignum 0
120             # ### _reverse_in_radix(): sprintf '%#X %d', $n, $n
121 2         2 do {
122 5         12 $ret = $ret * $radix + ($n % $radix);
123             } while ($n = int($n/$radix));
124             # ### ret: sprintf '%#X %d', $ret, $ret
125 2         6 return $ret;
126             }
127             }
128              
129             1;
130             __END__