File Coverage

blib/lib/Math/NumSeq/MephistoWaltz.pm
Criterion Covered Total %
statement 55 58 94.8
branch 5 6 83.3
condition 0 3 0.0
subroutine 13 14 92.8
pod 4 4 100.0
total 77 85 90.5


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              
19             # Fractal turn sequence:
20              
21             # "Infinite streams", Jorg Endrullis, Clemens Grabmayer, Dimitri Hendriks,
22             # Jan Willem Klop, www.phil.uu.nl/~clemens/linkedfiles/NVTI2009.pdf
23              
24              
25             package Math::NumSeq::MephistoWaltz;
26 1     1   22436 use 5.004;
  1         7  
  1         81  
27 1     1   12 use strict;
  1         3  
  1         69  
28              
29 1     1   11 use vars '$VERSION', '@ISA';
  1         3  
  1         112  
30             $VERSION = 71;
31 1     1   1068 use Math::NumSeq;
  1         4  
  1         102  
32             @ISA = ('Math::NumSeq');
33             *_is_infinite = \&Math::NumSeq::_is_infinite;
34              
35             # uncomment this to run the ### lines
36             #use Smart::Comments;
37              
38              
39             # use constant name => Math::NumSeq::__('Mephisto Waltz');
40 1     1   10 use constant description => Math::NumSeq::__('Mephisto waltz sequence.');
  1         2  
  1         5  
41 1     1   6 use constant i_start => 0;
  1         2  
  1         51  
42 1     1   5 use constant values_min => 0;
  1         1  
  1         37  
43 1     1   5 use constant values_max => 1;
  1         3  
  1         38  
44 1     1   5 use constant characteristic_integer => 1;
  1         2  
  1         46  
45              
46             # cf A189658 - positions of 0
47             # A189659 - positions of 1
48             # A189660 - cumulative 0/1
49             # A156595 - xor diffs, OFFSET=0 so a(n) = m(n) xor m(n+1)
50             #
51 1     1   6 use constant oeis_anum => 'A064990'; # mephisto waltz 0/1 values
  1         3  
  1         438  
52              
53             sub rewind {
54 2     2 1 4 my ($self) = @_;
55 2         10 $self->{'i'} = $self->i_start;
56 2         4 $self->{'value'} = 1;
57 2         5 $self->{'low'} = -1;
58 2         6 $self->{'digits'} = [];
59             }
60              
61             my @table = (0,0,1, 0,0,1, 1,1,0,
62             0,0,1, 0,0,1, 1,1,0,
63             1,1,0, 1,1,0, 0,0,1);
64             my @delta = (map {$table[$_]^$table[($_+26)%27]} 0 .. $#table);
65              
66             sub next {
67 2187     2187 1 8860 my ($self) = @_;
68             ### MephistoWaltz next(): $self->{'i'}
69             ### at: "low=$self->{'low'} value=$self->{'value'}"
70              
71 2187         1832 my $low;
72 2187 100       3575 if (($low = ++$self->{'low'}) >= 27) {
73 80         83 $low = $self->{'low'} = 0;
74 80         70 my $i = 0;
75 80         69 for (;;) {
76 82         93 my $digit = ++$self->{'digits'}->[$i];
77             ### carry to digit: $digit
78 82 100       101 if ($digit >= 27) {
79 2         5 $self->{'digits'}->[$i++] = 0;
80 2         4 $self->{'value'} ^= 1; # three 2s have become 0s
81             } else {
82 80         81 $self->{'value'} ^= $delta[$digit];
83 80         100 last;
84             }
85             }
86             }
87              
88             ### apply: "low=$low delta=$delta[$low]"
89 2187         3936 return ($self->{'i'}++,
90             ($self->{'value'} ^= $delta[$low]));
91             }
92              
93             sub ith {
94 2673     2673 1 8969 my ($self, $i) = @_;
95             ### ith(): $i
96              
97 2673 50       4292 if (_is_infinite($i)) {
98 0         0 return $i;
99             }
100 2673         2867 my $ret = 0;
101 2673         3745 while ($i) {
102 6720         6022 $ret ^= $table[$i % 27];
103 6720         9855 $i = int($i/27);
104             }
105 2673         3673 return $ret;
106             }
107              
108             sub pred {
109 0     0 1   my ($self, $value) = @_;
110 0   0       return ($value == 0 || $value == 1);
111             }
112              
113             1;
114             __END__