File Coverage

blib/lib/Math/NumSeq/MoranNumbers.pm
Criterion Covered Total %
statement 53 55 96.3
branch 10 12 83.3
condition 2 3 66.6
subroutine 13 13 100.0
pod 3 3 100.0
total 81 86 94.1


line stmt bran cond sub pod time code
1             # Copyright 2012, 2013, 2014, 2016 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::MoranNumbers;
19 1     1   1077 use 5.004;
  1         3  
20 1     1   5 use strict;
  1         1  
  1         29  
21 1     1   4 use Math::Prime::XS 0.23 'is_prime'; # version 0.23 fix for 1928099
  1         16  
  1         49  
22              
23 1     1   4 use vars '$VERSION', '@ISA';
  1         1  
  1         55  
24             $VERSION = 72;
25              
26 1     1   8 use Math::NumSeq;
  1         1  
  1         16  
27 1     1   3 use Math::NumSeq::Base::IteratePred;
  1         2  
  1         44  
28             @ISA = ('Math::NumSeq::Base::IteratePred',
29             'Math::NumSeq');
30             *_is_infinite = \&Math::NumSeq::_is_infinite;
31              
32             # uncomment this to run the ### lines
33             #use Devel::Comments;
34              
35 1     1   4 use constant name => Math::NumSeq::__('Moran Numbers');
  1         1  
  1         4  
36 1     1   3 use constant description => Math::NumSeq::__('Moran numbers, divisible by the sum of their digits and that division resulting in a prime.');
  1         1  
  1         7  
37 1     1   3 use constant i_start => 1;
  1         1  
  1         37  
38              
39             use Math::NumSeq::Base::Digits
40 1     1   4 'parameter_info_array'; # radix parameter
  1         1  
  1         250  
41              
42             sub values_min {
43 4     4 1 8 my ($self) = @_;
44 4 100       8 if (! $self->{'values_min'}) {
45 1         2 for (my $value = $self->{'radix'}; ; $value++) {
46 9 100       12 if ($self->pred($value)) {
47 1         2 $self->{'values_min'} = $value;
48 1         1 last;
49             }
50             }
51             }
52 4         8 return $self->{'values_min'};
53             }
54              
55             #------------------------------------------------------------------------------
56             # cf A007953 digit sum (in Math::NumSeq::DigitSum)
57             # A085775 both n/digitsum(n) and (n+1)/digitsum(n+1) prime
58             # A108780 n/digitsum(n) is a golden semiprime
59             # A130338 primes not occurring as n/digitsum(n)
60             # A003635 inconsummate, quotients not occurring as n/digitsum(n)
61             #
62             my @oeis_anum;
63             $oeis_anum[10] = 'A001101'; # OFFSET=1
64             # OEIS-Catalogue: A001101
65              
66             sub oeis_anum {
67 1     1 1 2 my ($self) = @_;
68 1         2 return $oeis_anum[$self->{'radix'}];
69             }
70              
71             #------------------------------------------------------------------------------
72              
73             sub pred {
74 578     578 1 899 my ($self, $value) = @_;
75             ### MoranNumbers pred(): $value
76              
77 578 100 66     1410 if ($value <= 0 || $value != int($value)) {
78 138         138 return 0;
79             }
80 440 50       500 if (_is_infinite($value)) {
81 0         0 return undef;
82             }
83              
84 440         349 my $radix = $self->{'radix'};
85 440         241 my $sum = 0;
86 440         256 my $v = $value;
87 440         473 while ($v) {
88 1058         634 $sum += ($v % $radix);
89 1058         1221 $v = int($v/$radix);
90             }
91 440 100       495 if ($value % $sum) {
92 303         473 return 0;
93             }
94 137         109 $value /= $sum;
95 137 50       155 if ($value > 0xFFFF_FFFF) {
96 0         0 return undef;
97             }
98 137         274 return is_prime($value);
99             }
100              
101             1;
102             __END__