File Coverage

blib/lib/Math/NumSeq/GolayRudinShapiroCumulative.pm
Criterion Covered Total %
statement 78 84 92.8
branch 18 22 81.8
condition 7 14 50.0
subroutine 17 18 94.4
pod 5 5 100.0
total 125 143 87.4


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   123820 use 5.004;
  2         14  
  2         160  
20 2     2   16 use strict;
  2         4  
  2         105  
21              
22 2     2   15 use vars '$VERSION', '@ISA';
  2         6  
  2         212  
23             $VERSION = 71;
24              
25 2     2   1158 use Math::NumSeq;
  2         6  
  2         118  
26             @ISA = ('Math::NumSeq');
27             *_is_infinite = \&Math::NumSeq::_is_infinite;
28              
29 2     2   1047 use Math::NumSeq::GolayRudinShapiro;
  2         5  
  2         78  
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   17 use constant description => Math::NumSeq::__('Cumulative Golay/Rudin/Shapiro sequence.');
  2         6  
  2         8  
37 2     2   11 use constant values_min => 1;
  2         3  
  2         82  
38 2     2   8 use constant characteristic_integer => 1;
  2         4  
  2         78  
39 2     2   10 use constant characteristic_smaller => 1;
  2         4  
  2         112  
40 2     2   10 use constant i_start => Math::NumSeq::GolayRudinShapiro->default_i_start;
  2         3  
  2         96  
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   11 use constant oeis_anum => 'A020986'; # GRS +/-1 cumulative
  2         3  
  2         1079  
50              
51             #------------------------------------------------------------------------------
52              
53             sub rewind {
54 7     7 1 733 my ($self) = @_;
55 7         38 $self->{'grs'} = Math::NumSeq::GolayRudinShapiro->new;
56 7         38 $self->{'value'} = 0;
57             }
58             sub tell_i {
59 2     2 1 34 my ($self) = @_;
60 2         13 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 95779 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         55327 my ($i, $value) = $self->{'grs'}->next;
78 20034         56003 return ($i,
79             ($self->{'value'} += $value));
80             }
81              
82             sub ith {
83 20054     20054 1 89511 my ($self, $i) = @_;
84             ### ith(): $i
85              
86 20054 100       37015 if ($i < 0) {
87 3         9 return undef;
88             }
89 20051 50       40497 if (_is_infinite($i)) {
90 0         0 return $i;
91             }
92              
93 20051 100       40684 if ($i <= 1) {
94 10         36 return $i+1;
95             }
96              
97 20041         34730 my @bits = _bits_low_to_high($i);
98 20041         29824 my $bit = shift @bits;
99 20041         22842 my $ret = 1;
100 20041         26887 my $power = ($i * 0) + 1; # inherit possible bignum 1
101              
102             ### initial bit: $bit
103              
104 20041         19760 for (;;) {
105 118229         127172 my $next = shift @bits;
106 118229 100 100     320734 if ($bit && $next) {
107             ### negate A to: "ret=$ret"
108 28744         32685 $ret = -$ret;
109             }
110 118229 100       192932 if ($bit) {
111 56792         59179 $ret += $power;
112             ### add A: "$power giving ret=$ret"
113             }
114 118229         119775 $power *= 2;
115 118229 100       203423 last unless @bits;
116 109123         112466 $bit = $next;
117              
118 109123         115178 $next = shift @bits;
119 109123         133539 $i = int($i/2);
120 109123 100 100     287099 if ($bit && $next) {
121 28597         38774 $ret = -$ret;
122             }
123 109123 100       164881 if ($bit) {
124             ### add B: "$power to ret=$ret"
125 52479         55627 $ret += $power;
126             }
127 109123 100       181638 last unless @bits;
128 98188         110794 $bit = $next;
129             }
130              
131             ### final add: $power
132 20041         50967 return ($ret + $power);
133             }
134              
135             sub _bits_low_to_high {
136 20041     20041   21819 my ($n) = @_;
137 20041 50       33820 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         19544 my @bits;
144 20041         37577 while ($n) {
145 247393         278771 push @bits, $n % 2;
146 247393         405796 $n = int($n/2);
147             }
148 20041         2080282 return @bits;
149             }
150              
151             sub pred {
152 17     17 1 98 my ($self, $value) = @_;
153 17   33     84 return ($value >= 1
154             && $value == int($value));
155             }
156              
157             1;
158             __END__