File Coverage

blib/lib/Math/NumSeq/DigitLength.pm
Criterion Covered Total %
statement 60 65 92.3
branch 5 6 83.3
condition 1 3 33.3
subroutine 17 18 94.4
pod 6 6 100.0
total 89 98 90.8


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::DigitLength;
19 1     1   1769 use 5.004;
  1         3  
20 1     1   5 use strict;
  1         1  
  1         22  
21              
22 1     1   3 use vars '$VERSION','@ISA';
  1         1  
  1         59  
23             $VERSION = 72;
24 1     1   4 use Math::NumSeq;
  1         1  
  1         46  
25             @ISA = ('Math::NumSeq');
26             *_is_infinite = \&Math::NumSeq::_is_infinite;
27              
28              
29             # uncomment this to run the ### lines
30             #use Smart::Comments;
31              
32             # use constant name => Math::NumSeq::__('Digit Length');
33 1     1   4 use constant description => Math::NumSeq::__('How many digits the number requires in the given radix. For example binary 1,1,2,2,3,3,3,3,4, etc.');
  1         1  
  1         3  
34 1     1   3 use constant values_min => 1;
  1         1  
  1         39  
35 1     1   3 use constant i_start => 0;
  1         2  
  1         31  
36 1     1   3 use constant characteristic_count => 1;
  1         1  
  1         36  
37 1     1   3 use constant characteristic_smaller => 1;
  1         1  
  1         32  
38 1     1   3 use constant characteristic_increasing => 1;
  1         0  
  1         38  
39              
40             use Math::NumSeq::Base::Digits
41 1     1   3 'parameter_info_array'; # radix parameter
  1         2  
  1         380  
42              
43             #------------------------------------------------------------------------------
44             # cf A000523 - floor(log2(n)), is bitlength-1
45             # A036786 - roman numeral length < decimal length
46             # A036787 - roman numeral length == decimal length
47             # A036788 - roman numeral length <= decimal length
48             #
49             my @oeis_anum = (
50             # OEIS-Catalogue array begin
51             undef, # 0
52             undef, # 1
53             'A070939', # radix=2
54             'A081604', # radix=3 # ternary
55             'A110591', # radix=4
56             'A110592', # radix=5
57             undef, # 6
58             undef, # 7
59             undef, # 8
60             undef, # 9
61             'A055642', # radix=10
62             # OEIS-Catalogue array end
63             );
64             sub oeis_anum {
65 3     3 1 11 my ($self) = @_;
66 3         6 return $oeis_anum[$self->{'radix'}];
67             }
68              
69             #------------------------------------------------------------------------------
70              
71              
72             sub rewind {
73 9     9 1 1363 my ($self) = @_;
74 9         26 $self->{'i'} = $self->i_start;
75 9         8 $self->{'length'} = 1;
76 9         27 $self->{'limit'} = $self->{'radix'};
77             }
78             sub _UNTESTED__seek_to_i {
79 0     0   0 my ($self, $i) = @_;
80 0         0 $self->{'i'} = $i;
81 0         0 my $length = $self->{'length'} = $self->ith($i);
82 0         0 $self->{'limit'} = $self->{'radix'} ** ($length+1);
83             }
84             sub next {
85 158     158 1 1140 my ($self) = @_;
86             ### DigitLength next(): $self
87             ### count: $self->{'count'}
88             ### bits: $self->{'bits'}
89              
90 158         132 my $i = $self->{'i'}++;
91 158 100       205 if ($i >= $self->{'limit'}) {
92 18         19 $self->{'limit'} *= $self->{'radix'};
93 18         16 $self->{'length'}++;
94             ### step to
95             ### length: $self->{'length'}
96             ### remaining: $self->{'limit'}
97             }
98 158         146 return ($i, $self->{'length'});
99             }
100              
101             sub ith {
102 246     246 1 294 my ($self, $i) = @_;
103 246 50       282 if (_is_infinite($i)) {
104 0         0 return $i; # don't loop forever if $i is +infinity
105             }
106 246         189 my $length = 1;
107 246         168 my $radix = $self->{'radix'};
108 246         164 my $power = $i*0 + $radix; # inherit possible $i bignum
109 246         284 while ($i >= $power) {
110 489         255 $length++;
111 489         517 $power *= $radix;
112             }
113 246         297 return $length;
114             }
115              
116             sub pred {
117 79     79 1 186 my ($self, $value) = @_;
118 79   33     172 return ($value >= 1 && $value == int($value));
119             }
120              
121             # not actually documented yet ...
122             sub value_to_i_floor {
123 285     285 1 285720 my ($self, $value) = @_;
124              
125             # radix**(value-1) is the first of length $value, except 0 is the first
126             # length 1
127 285         311 $value = int($value)-1;
128 285 100       9192 if ($value <= 0) {
129 97         1358 return 0;
130             }
131 188         5658 return $self->{'radix'} ** $value;
132             }
133             *value_to_i_estimate = \&value_to_i_floor;
134              
135             1;
136             __END__