File Coverage

blib/lib/Math/NumSeq/DuffinianNumbers.pm
Criterion Covered Total %
statement 52 54 96.3
branch 8 10 80.0
condition 5 6 83.3
subroutine 15 15 100.0
pod 1 1 100.0
total 81 86 94.1


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::DuffinianNumbers;
19 1     1   1224 use 5.004;
  1         2  
20 1     1   4 use strict;
  1         1  
  1         20  
21 1     1   4 use List::Util 'sum';
  1         1  
  1         73  
22 1     1   4 use Math::Prime::XS 0.23 'is_prime'; # version 0.23 fix for 1928099
  1         12  
  1         38  
23 1     1   5 use Math::Factor::XS 0.40 'factors'; # version 0.40 for factors() on BigInt
  1         16  
  1         32  
24              
25              
26 1     1   3 use vars '$VERSION', '@ISA';
  1         4  
  1         48  
27             $VERSION = 72;
28 1     1   3 use Math::NumSeq;
  1         2  
  1         17  
29 1     1   3 use List::Util 'min';
  1         1  
  1         29  
30 1     1   3 use Math::NumSeq::Base::IteratePred;
  1         2  
  1         52  
31             @ISA = ('Math::NumSeq::Base::IteratePred',
32             'Math::NumSeq');
33             *_is_infinite = \&Math::NumSeq::_is_infinite;
34             *_to_bigint = \&Math::NumSeq::_to_bigint;
35              
36             # uncomment this to run the ### lines
37             #use Smart::Comments;
38              
39              
40             # use constant name => Math::NumSeq::__('Duffinian Numbers');
41 1     1   4 use constant description => Math::NumSeq::__('Duffinian numbers.');
  1         1  
  1         3  
42 1     1   3 use constant i_start => 1;
  1         1  
  1         38  
43              
44 1     1   4 use constant values_min => 4;
  1         1  
  1         33  
45              
46             #------------------------------------------------------------------------------
47              
48 1     1   3 use constant oeis_anum => 'A003624';
  1         1  
  1         173  
49              
50              
51             #------------------------------------------------------------------------------
52              
53             sub pred {
54 265     265 1 456 my ($self, $value) = @_;
55             ### DuffinianNumbers pred(): $value
56              
57 265 50       317 if (_is_infinite($value)) {
58 0         0 return undef;
59             }
60 265 100 66     658 if ($value < 2 || $value != int($value)) {
61 61         52 return 0;
62             }
63 204 50       210 if ($value > 0xFFFF_FFFF) {
64 0         0 return undef;
65             }
66 204         133 $value = "$value"; # numize any Math::BigInt for speed
67              
68 204   100     706 return ! is_prime($value)
69             && _coprime($value, sum(1,factors($value)));
70             }
71              
72             # return true if coprime
73             sub _coprime {
74 156     156   128 my ($x, $y) = @_;
75             ### _coprime(): "$x,$y"
76              
77 156 100       176 if ($y > $x) {
78 37         42 ($x,$y) = ($y,$x);
79             }
80 156         108 for (;;) {
81 551 100       583 if ($y <= 1) {
82             ### result: ($y == 1)
83 156         436 return ($y == 1);
84             }
85 395         365 ($x,$y) = ($y, $x % $y);
86             }
87             }
88              
89             1;
90             __END__