File Coverage

blib/lib/Math/NumSeq/Emirps.pm
Criterion Covered Total %
statement 52 53 98.1
branch 6 8 75.0
condition 6 6 100.0
subroutine 15 15 100.0
pod 5 5 100.0
total 84 87 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   370493 use 5.004;
  2         12  
  2         121  
20 2     2   18 use strict;
  2         7  
  2         297  
21              
22 2     2   16 use vars '$VERSION', '@ISA';
  2         5  
  2         186  
23             $VERSION = 71;
24 2     2   1587 use Math::NumSeq;
  2         7  
  2         71  
25 2     2   1174 use Math::NumSeq::Primes;
  2         5  
  2         126  
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   12 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         3  
  2         9  
35              
36             use Math::NumSeq::Base::Digits
37 2     2   523 'parameter_info_array'; # radix parameter
  2         6  
  2         108  
38              
39 2     2   9 use constant characteristic_increasing => 1;
  2         10  
  2         85  
40 2     2   8 use constant characteristic_integer => 1;
  2         4  
  2         1207  
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 12 my ($self) = @_;
48 1         6 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 5 my ($self) = @_;
62 1         4 return $oeis_anum[$self->{'radix'}];
63             }
64              
65             #------------------------------------------------------------------------------
66              
67             sub rewind {
68 4     4 1 2013 my ($self) = @_;
69 4         30 $self->{'i'} = $self->i_start;
70 4         32 $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 1695 my ($self) = @_;
81              
82 100         348 my $primes_seq = $self->{'primes_seq'};
83              
84 100         112 for (;;) {
85 392 50       1508 (undef, my $prime) = $primes_seq->next
86             or return;
87 392         1169 my $rev = _reverse_in_radix($prime,$self->{'radix'});
88              
89             ### consider: $prime
90             ### $rev
91              
92 392 100 100     3079 if ($rev != $prime && $self->Math::NumSeq::Primes::pred($rev)) {
93             ### yes ...
94 100         411 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 11479 my ($self, $value) = @_;
103 2007 50       5433 if (_is_infinite($value)) {
104 0         0 return 0;
105             }
106 2007         5582 my $rev = _reverse_in_radix($value,$self->{'radix'});
107 2007   100     13069 return ($rev != $value
108             && $self->Math::NumSeq::Primes::pred($value)
109             && $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   4863 my ($n, $radix) = @_;
115              
116 2599 100       5901 if ($radix == 10) {
117 2597         10902 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         15 $ret = $ret * $radix + ($n % $radix);
123             } while ($n = int($n/$radix));
124             # ### ret: sprintf '%#X %d', $ret, $ret
125 2         7 return $ret;
126             }
127             }
128              
129             1;
130             __END__