File Coverage

blib/lib/Math/NumSeq/GolayRudinShapiroCumulative.pm
Criterion Covered Total %
statement 77 83 92.7
branch 18 22 81.8
condition 7 14 50.0
subroutine 17 18 94.4
pod 5 5 100.0
total 124 142 87.3


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::GolayRudinShapiroCumulative;
19 2     2   7027 use 5.004;
  2         4  
20 2     2   8 use strict;
  2         2  
  2         49  
21              
22 2     2   6 use vars '$VERSION', '@ISA';
  2         2  
  2         107  
23             $VERSION = 72;
24              
25 2     2   354 use Math::NumSeq;
  2         4  
  2         72  
26             @ISA = ('Math::NumSeq');
27             *_is_infinite = \&Math::NumSeq::_is_infinite;
28              
29 2     2   336 use Math::NumSeq::GolayRudinShapiro;
  2         2  
  2         58  
30              
31             # uncomment this to run the ### lines
32             #use Smart::Comments;
33              
34              
35             # use constant name => Math::NumSeq::__('Golay-Rudin-Shapiro Cumulative');
36 2     2   8 use constant description => Math::NumSeq::__('Cumulative Golay/Rudin/Shapiro sequence.');
  2         3  
  2         7  
37 2     2   7 use constant values_min => 1;
  2         1  
  2         70  
38 2     2   6 use constant characteristic_integer => 1;
  2         2  
  2         63  
39 2     2   6 use constant characteristic_smaller => 1;
  2         1  
  2         141  
40 2     2   10 use constant i_start => Math::NumSeq::GolayRudinShapiro->default_i_start;
  2         3  
  2         93  
41              
42             #------------------------------------------------------------------------------
43             # cf A020990 - cumulative GRS(2n+1), flips sign at odd i
44             # A051032 - GRS cumulative of 2^n
45             # A212591 - index of first occurrence of k in the partial sums
46             # A020991 - index of last occurrence of k in the partial sums
47             # A093573 - indexes of all positions where k occurs
48              
49 2     2   6 use constant oeis_anum => 'A020986'; # GRS +/-1 cumulative
  2         3  
  2         793  
50              
51             #------------------------------------------------------------------------------
52              
53             sub rewind {
54 7     7 1 431 my ($self) = @_;
55 7         29 $self->{'grs'} = Math::NumSeq::GolayRudinShapiro->new;
56 7         24 $self->{'value'} = 0;
57             }
58             sub tell_i {
59 2     2 1 33 my ($self) = @_;
60 2         11 return $self->{'grs'}->tell_i;
61             }
62             sub _UNTESTED__seek_to_i {
63 0     0   0 my ($self, $i) = @_;
64 0         0 $self->{'grs'}->seek_to_i($i);
65 0   0     0 $self->{'value'} = $self->ith($i-1) || 0;
66             }
67              
68             sub next {
69 20034     20034 1 54683 my ($self) = @_;
70              
71             # doubling up ...
72             # $self->{'grs'}->next;
73             # my ($i, $value) = $self->{'grs'}->next;
74             # return ($i>>1,
75             # ($self->{'value'} += $value));
76              
77 20034         28364 my ($i, $value) = $self->{'grs'}->next;
78             return ($i,
79 20034         26619 ($self->{'value'} += $value));
80             }
81              
82             sub ith {
83 20054     20054 1 53013 my ($self, $i) = @_;
84             ### ith(): $i
85              
86 20054 100       26312 if ($i < 0) {
87 3         8 return undef;
88             }
89 20051 50       23493 if (_is_infinite($i)) {
90 0         0 return $i;
91             }
92              
93 20051 100       25315 if ($i <= 1) {
94 10         18 return $i+1;
95             }
96              
97 20041         18033 my @bits = _bits_low_to_high($i);
98 20041         18424 my $bit = shift @bits;
99 20041         12369 my $ret = 1;
100 20041         14309 my $power = ($i * 0) + 1; # inherit possible bignum 1
101              
102             ### initial bit: $bit
103              
104 20041         12101 for (;;) {
105 118229         68705 my $next = shift @bits;
106 118229 100 100     205889 if ($bit && $next) {
107             ### negate A to: "ret=$ret"
108 28744         20495 $ret = -$ret;
109             }
110 118229 100       119761 if ($bit) {
111 56792         36029 $ret += $power;
112             ### add A: "$power giving ret=$ret"
113             }
114 118229         66466 $power *= 2;
115 118229 100       126165 last unless @bits;
116 109123         62391 $bit = $next;
117              
118 109123         61114 $next = shift @bits;
119 109123         70078 $i = int($i/2);
120 109123 100 100     183746 if ($bit && $next) {
121 28597         18996 $ret = -$ret;
122             }
123 109123 100       113231 if ($bit) {
124             ### add B: "$power to ret=$ret"
125 52479         33032 $ret += $power;
126             }
127 109123 100       118412 last unless @bits;
128 98188         61423 $bit = $next;
129             }
130              
131             ### final add: $power
132 20041         25472 return ($ret + $power);
133             }
134              
135             sub _bits_low_to_high {
136 20041     20041   12400 my ($n) = @_;
137 20041 50       23581 if (ref $n) {
138 0 0 0     0 if ($n->isa('Math::BigInt')
139             && $n->can('as_bin')) {
140 0         0 return reverse split //, substr($n->as_bin,2);
141             }
142             }
143 20041         12627 my @bits;
144 20041         23736 while ($n) {
145 247393         155165 push @bits, $n % 2;
146 247393         270490 $n = int($n/2);
147             }
148 20041         33944 return @bits;
149             }
150              
151             sub pred {
152 17     17 1 44 my ($self, $value) = @_;
153 17   33     40 return ($value >= 1
154             && $value == int($value));
155             }
156              
157             1;
158             __END__