File Coverage

blib/lib/Math/NumSeq/Multiples.pm
Criterion Covered Total %
statement 79 87 90.8
branch 10 16 62.5
condition n/a
subroutine 25 26 96.1
pod 13 16 81.2
total 127 145 87.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::Multiples;
19 2     2   13377 use 5.004;
  2         9  
  2         82  
20 2     2   12 use strict;
  2         4  
  2         75  
21 2     2   1013 use POSIX 'ceil';
  2         9173  
  2         17  
22              
23 2     2   2437 use vars '$VERSION', '@ISA';
  2         11  
  2         131  
24             $VERSION = 71;
25 2     2   742 use Math::NumSeq;
  2         5  
  2         151  
26             @ISA = ('Math::NumSeq');
27              
28             # uncomment this to run the ### lines
29             #use Devel::Comments;
30              
31              
32             # use constant name => Math::NumSeq::__('Multiples of a given K');
33 2     2   10 use constant description => Math::NumSeq::__('The multiples K, 2*K, 3*K, 4*K, etc of a given number.');
  2         4  
  2         8  
34 2     2   9 use constant default_i_start => 0;
  2         4  
  2         547  
35              
36             sub values_min {
37 2     2 1 19 my ($self) = @_;
38 2 50       11 if ((my $multiples = $self->{'multiples'}) >= 0) {
39 2         9 return $multiples * $self->i_start;
40             } else {
41 0         0 return undef;
42             }
43             }
44             sub values_max {
45 0     0 1 0 my ($self) = @_;
46 0 0       0 if ((my $multiples = $self->{'multiples'}) <= 0) {
47 0         0 return $multiples * $self->i_start;
48             } else {
49 0         0 return undef;
50             }
51             }
52             sub characteristic_non_decreasing {
53 2     2 0 4 my ($self) = @_;
54 2         10 return ($self->{'multiples'} >= 0);
55             }
56             sub characteristic_increasing {
57 4     4 0 9 my ($self) = @_;
58 4         19 return ($self->{'multiples'} > 0);
59             }
60             sub characteristic_integer {
61 3     3 0 5 my ($self) = @_;
62 3         16 return (int($self->{'multiples'}) == $self->{'multiples'});
63             }
64              
65 2         10 use constant parameter_info_array =>
66             [ { name => 'multiples',
67             type => 'float',
68             width => 10,
69             decimals => 4,
70             page_increment => 10,
71             step_increment => 1,
72             minimum => 0,
73             default => 29,
74             description => Math::NumSeq::__('Display multiples of this number. For example 6 means show 6,12,18,24,30,etc.'),
75             },
76 2     2   11 ];
  2         6  
77              
78             #------------------------------------------------------------------------------
79              
80             # cf A017173 9n+1
81             my %oeis_anum =
82             (0 => { 0 => 'A000004', # 0, all zeros
83             # OEIS-Catalogue: A000004 multiples=0
84              
85             1 => 'A001477', # 1, integers 0,1,2,...
86             2 => 'A005843', # 2 even 0,2,4,...
87             # OEIS-Other: A001477 multiples=1
88             # OEIS-Other: A005843 multiples=2
89              
90             3 => 'A008585', # 3 starting from i=0
91             4 => 'A008586', # 4 starting from i=0
92             5 => 'A008587', # 5 starting from i=0
93             6 => 'A008588', # 6 starting from i=0
94             7 => 'A008589', # 7 starting from i=0
95             8 => 'A008590', # 8 starting from i=0
96             9 => 'A008591', # 9 starting from i=0
97             10 => 'A008592', # 10 starting from i=0
98             # OEIS-Catalogue: A008585 multiples=3
99             # OEIS-Catalogue: A008586 multiples=4
100             # OEIS-Catalogue: A008587 multiples=5
101             # OEIS-Catalogue: A008588 multiples=6
102             # OEIS-Catalogue: A008589 multiples=7
103             # OEIS-Catalogue: A008590 multiples=8
104             # OEIS-Catalogue: A008591 multiples=9
105             # OEIS-Catalogue: A008592 multiples=10
106             },
107             1 => {
108             3018 => 'A086746', # multiples of 3018, start OFFSET=1 value=3018
109             # OEIS-Catalogue: A086746 multiples=3018 i_start=1
110             },
111             );
112             sub oeis_anum {
113 2     2 1 9 my ($self) = @_;
114 2         7 my $i_start = $self->i_start;
115 2 50       8 if ($i_start < 0) { return undef; }
  0         0  
116 2         10 return $oeis_anum{$i_start}->{$self->{'multiples'}};
117             }
118              
119             #------------------------------------------------------------------------------
120              
121             sub rewind {
122 12     12 1 1029 my ($self) = @_;
123 12         41 $self->{'i'} = $self->i_start;
124             }
125             sub seek_to_i {
126 14     14 1 234 my ($self, $i) = @_;
127             # if ($i >= $self->{'uv_i_limit'}) {
128             # $i = Math::NumSeq::_to_bigint($i);
129             # }
130 14         31 $self->{'i'} = $i;
131             }
132             sub seek_to_value {
133 14     14 1 86 my ($self, $value) = @_;
134 14         25 $self->{'i'} = $self->value_to_i_ceil($value);
135             }
136             sub next {
137 98     98 1 1726 my ($self) = @_;
138 98         162 my $i = $self->{'i'}++;
139 98         254 return ($i, $i * $self->{'multiples'});
140             }
141             sub ith {
142 218     218 1 317 my ($self, $i) = @_;
143 218         538 return $i * $self->{'multiples'};
144             }
145             sub pred {
146 484     484 1 2012 my ($self, $value) = @_;
147 484         593 my $multiples = $self->{'multiples'};
148 484 50       3909 if ($multiples == 0) {
149 0         0 return ($value == 0);
150             }
151 484         563 my $i = int($value / $multiples);
152 484         969 return ($value == $i*$multiples);
153             }
154              
155             use constant::defer _INFINITY => sub {
156 1         90 require POSIX;
157 1         4 return 2 * POSIX::DBL_MAX();
158 2     2   14 };
  2         9  
  2         21  
159              
160             sub value_to_i_estimate {
161 34     34 1 897 my ($self, $value) = @_;
162 34         50 my $multiples = $self->{'multiples'};
163 34 100       60 if ($multiples == 0) {
164 1         5 return _INFINITY;
165             }
166 33         69 return int($value / $multiples);
167             }
168              
169 2     2   6657 use Math::NumSeq::All;
  2         5  
  2         413  
170             *_floor = \&Math::NumSeq::All::_floor;
171              
172             sub value_to_i {
173 76     76 1 275 my ($self, $value) = @_;
174 76         140 my $i = $self->value_to_i_floor($value);
175 76 100       145 if ($value == $self->ith($i)) {
176 29         1766 return $i;
177             }
178 47         86 return undef;
179             }
180             sub value_to_i_floor {
181 277     277 1 597 my ($self, $value) = @_;
182 277         752 return _floor($value/$self->{'multiples'});
183             }
184             sub value_to_i_ceil {
185 94     94 1 317 my ($self, $value) = @_;
186 94 50       192 if ($value < 0) { return 0; }
  0         0  
187 94         1632 my $i = $self->value_to_i_floor($value);
188 94 100       186 if ($value > $self->ith($i)) {
189 24         35 $i += 1;
190             }
191 94         2073 return $i;
192             }
193              
194              
195             1;
196             __END__