File Coverage

blib/lib/Math/NumSeq/LiouvilleFunction.pm
Criterion Covered Total %
statement 48 54 88.8
branch 4 4 100.0
condition 2 9 22.2
subroutine 15 18 83.3
pod 5 7 71.4
total 74 92 80.4


line stmt bran cond sub pod time code
1             # Copyright 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::LiouvilleFunction;
19 1     1   12409 use 5.004;
  1         6  
  1         64  
20 1     1   7 use strict;
  1         2  
  1         47  
21 1     1   5 use List::Util 'max','min';
  1         3  
  1         160  
22              
23 1     1   6 use vars '$VERSION','@ISA';
  1         3  
  1         75  
24             $VERSION = 71;
25              
26 1     1   6 use Math::NumSeq;
  1         2  
  1         27  
27 1     1   5 use Math::NumSeq::Base::IterateIth;
  1         3  
  1         55  
28             @ISA = ('Math::NumSeq::Base::IterateIth',
29             'Math::NumSeq');
30              
31 1     1   8 use Math::NumSeq::PrimeFactorCount;
  1         3  
  1         48  
32             *_prime_factors = \&Math::NumSeq::PrimeFactorCount::_prime_factors;
33              
34             # uncomment this to run the ### lines
35             #use Smart::Comments;
36              
37              
38             # use constant name => Math::NumSeq::__('Liouville Function');
39 1     1   6 use constant default_i_start => 1;
  1         3  
  1         153  
40              
41 1         8 use constant parameter_info_array =>
42             [ {
43             name => 'values_type',
44             share_key => 'values_type_1-1_01_10',
45             type => 'enum',
46             default => '1,-1',
47             choices => ['1,-1',
48             '0,1',
49             '1,0',
50             ],
51             # TRANSLATORS: "1,-1" offered for translation of the "," if that might look like a decimal point, otherwise can be left unchanged
52             choices_display => [Math::NumSeq::__('1,-1'),
53             Math::NumSeq::__('0,1'),
54             Math::NumSeq::__('1,0'),
55             ],
56             description => Math::NumSeq::__('The values to give for even or odd parity.'),
57             },
58 1     1   7 ];
  1         2  
59              
60             sub description {
61 6     6 1 25 my ($self) = @_;
62 6 100       21 my ($even,$odd) = (ref $self ? @{$self->{'values'}} : (1,-1));
  3         7  
63             # ENHANCE-ME: use __x(), maybe
64 6         17 return sprintf(Math::NumSeq::__('The Liouville function, being %s for an even number of prime factors or %s for an odd number.'),
65             $even, $odd);
66             }
67              
68 1     1   9 use constant characteristic_increasing => 0;
  1         3  
  1         615  
69             sub characteristic_integer {
70 0     0 0 0 my ($self) = @_;
71 0   0     0 return (_is_integer($self->{'values_min'})
72             && _is_integer($self->{'values_max'}));
73             }
74             sub characteristic_pn1 {
75 0     0 0 0 my ($self) = @_;
76 0   0     0 return ($self->{'values_min'} == -1 && $self->{'values_max'} == 1);
77             }
78              
79             #------------------------------------------------------------------------------
80             # cf A026424 the -1 positions, odd number of primes
81             # A028260 the 1 positions, even number of primes
82             # A072203 cumulative +/-1
83             # A055038 cumulative 1=odd
84             # A028488 where cumulative==0
85             # A051470 first cumulative==n
86              
87             my %oeis_anum = ('1,-1' => 'A008836', # liouville 1,-1
88             '0,1' => 'A066829', # 0 and 1
89             '1,0' => 'A065043', # 1 and 0
90             # OEIS-Catalogue: A008836
91             # OEIS-Catalogue: A066829 values_type=0,1
92             # OEIS-Catalogue: A065043 values_type=1,0
93             );
94             sub oeis_anum {
95 3     3 1 15 my ($self) = @_;
96 3         5 return $oeis_anum{join(',',@{$self->{'values'}})};
  3         15  
97             }
98              
99              
100             #------------------------------------------------------------------------------
101              
102             sub new {
103 3     3 1 778 my $self = shift->SUPER::new(@_);
104              
105 3         16 my @values = split /,/, $self->{'values_type'};
106 3         9 $self->{'values'} = \@values;
107 3         31 $self->{'values_min'} = min(@values);
108 3         10 $self->{'values_max'} = max(@values);
109 3         11 return $self;
110             }
111              
112             sub ith {
113 237     237 1 453 my ($self, $i) = @_;
114             ### LiouvilleFunction ith(): $i
115              
116 237         585 my ($good, @primes) = _prime_factors($i);
117 237 100       1378 return ($good
118             ? $self->{'values'}->[scalar(@primes) & 1]
119             : undef);
120             }
121              
122             sub pred {
123 24     24 1 213 my ($self, $value) = @_;
124 24   66     149 return ($value == $self->{'values'}->[0]
125             || $value == $self->{'values'}->[1]);
126             }
127              
128             #------------------------------------------------------------------------------
129             # generic
130              
131             sub _is_integer {
132 0     0     my ($n) = @_;
133 0           return ($n == int($n));
134             }
135              
136             1;
137             __END__