line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
=head1 NAME
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
Math::Series - Perl extension dealing with mathematic series
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use Math::Series;
|
9
|
|
|
|
|
|
|
my $x_n = Math::Series->new( formula => 'n*x',
|
10
|
|
|
|
|
|
|
start_value => 1,
|
11
|
|
|
|
|
|
|
iteration_var => 'n',
|
12
|
|
|
|
|
|
|
previous_var => 'x',
|
13
|
|
|
|
|
|
|
start_index => 0,
|
14
|
|
|
|
|
|
|
cached => 1 );
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
print $x_n->next(), "\n" foreach 0..5;
|
17
|
|
|
|
|
|
|
# prints 1, 2, 6, 24...
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
print $x_n->at_index(3);
|
20
|
|
|
|
|
|
|
# prints 24
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Math::Series defines a class for simple mathematic series with a
|
25
|
|
|
|
|
|
|
recursive definition such as C. Such a recursive
|
26
|
|
|
|
|
|
|
definition is treated as a sequence whose elements will be added to form
|
27
|
|
|
|
|
|
|
a series. You can refer to the previous sequence element as well as to the
|
28
|
|
|
|
|
|
|
current index in the series. Creation of a
|
29
|
|
|
|
|
|
|
Math::Series object is described below in the paragraph about the
|
30
|
|
|
|
|
|
|
constructor.
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Math::Series uses Math::Symbolic to parse and modify the recursive
|
33
|
|
|
|
|
|
|
sequence definitions. That means you specify the sequence as a string which
|
34
|
|
|
|
|
|
|
is parsed by Math::Symbolic. Alternatively, you can pass the constructor
|
35
|
|
|
|
|
|
|
a Math::Symbolic tree directly.
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Because Math::Series uses Math::Symbolic for its implementation, all results
|
38
|
|
|
|
|
|
|
will be Math::Symbolic objects which may contain other variables than the
|
39
|
|
|
|
|
|
|
sequence variable and the iterator variable.
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Each Math::Series object is an iterator to iterate over the elements of the
|
42
|
|
|
|
|
|
|
series starting at the first element (which was specified by the starting
|
43
|
|
|
|
|
|
|
element, the second argument to the new() constructor). It offers
|
44
|
|
|
|
|
|
|
facilities to cache all calculated elements and access any element directly,
|
45
|
|
|
|
|
|
|
though unless the element has been cached in a previous calculation, this
|
46
|
|
|
|
|
|
|
is just a shortcut for repeated use of the iterator.
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Every element in the series may only access its predecessor, not the elements
|
49
|
|
|
|
|
|
|
before that.
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=cut
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
package Math::Series;
|
54
|
|
|
|
|
|
|
|
55
|
1
|
|
|
1
|
|
997
|
use 5.006;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
42
|
|
56
|
1
|
|
|
1
|
|
6
|
use strict;
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
38
|
|
57
|
1
|
|
|
1
|
|
20
|
use warnings;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
45
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
our $VERSION = '1.01';
|
60
|
|
|
|
|
|
|
|
61
|
1
|
|
|
1
|
|
5
|
use Carp;
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
79
|
|
62
|
|
|
|
|
|
|
|
63
|
1
|
|
|
1
|
|
859
|
use Math::Symbolic qw/:all/;
|
|
1
|
|
|
|
|
149181
|
|
|
1
|
|
|
|
|
300
|
|
64
|
1
|
|
|
1
|
|
1055
|
use Math::Sequence;
|
|
1
|
|
|
|
|
2298
|
|
|
1
|
|
|
|
|
36
|
|
65
|
1
|
|
|
1
|
|
7
|
use base 'Math::Sequence';
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1196
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head2 CLASS DATA
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Math::Series defines the following package variables:
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=over 2
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=item $Math::Series::Parser
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
This scalar contains a Parse::RecDescent parser to parse formulas.
|
76
|
|
|
|
|
|
|
It is derived from the Math::Symbolic::Parser grammar.
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=cut
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
our $Parser = Math::Symbolic::Parser->new();
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
#$Parser->Extend(<<'GRAMMAR');
|
83
|
|
|
|
|
|
|
#GRAMMAR
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item $Math::Series::warnings
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This scalar indicates whether Math::Series should warn about the performance
|
88
|
|
|
|
|
|
|
implications of using the back() method on uncached series. It defaults
|
89
|
|
|
|
|
|
|
to true.
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=cut
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
our $warnings = 1;
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=pod
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=back
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 METHODS
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=over 2
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item new()
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
The constructor for Math::Series objects. It takes named parameters. The
|
106
|
|
|
|
|
|
|
following parameters are required:
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=over 2
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item formula
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
The formula is the recursive definition of a sequence whose elements up to
|
113
|
|
|
|
|
|
|
the current element will be summed to form the current element of the series.
|
114
|
|
|
|
|
|
|
The formula may contain various Math::Symbolic variables that are assigned
|
115
|
|
|
|
|
|
|
a value elsewhere in your code, but it may also contain two special variables:
|
116
|
|
|
|
|
|
|
The number of the current iteration step, starting with 0, and the previous
|
117
|
|
|
|
|
|
|
element of the series.
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
The formula may be specified as a string that can be parsed by a Math::Symbolic
|
120
|
|
|
|
|
|
|
parser or as a Math::Symbolic tree directly. Please refer to the Math::Symbolic
|
121
|
|
|
|
|
|
|
and Math::Symbolic::Parser man pages for details.
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=item start_value
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
This parameter defines the starting value for the series. It used as the
|
126
|
|
|
|
|
|
|
element in the series that is defined as the lowest series element by the
|
127
|
|
|
|
|
|
|
start_index parameter.
|
128
|
|
|
|
|
|
|
The starting value may be a string that can be parsed as a valid
|
129
|
|
|
|
|
|
|
Math::Symbolic tree or a preconstructed Math::Symbolic tree.
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=back
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
The following parameters are optional:
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=over 2
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item iteration_var
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
The iteration variable is the name of the variable in the Math::Symbolic tree
|
140
|
|
|
|
|
|
|
that refers to the current iteration step. It defaults to the variable 'n'.
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
It must be a valid Math::Symbolic variable identifier. (That means it is
|
143
|
|
|
|
|
|
|
C[A-Za-z][A-Za-z0-9_]*/>.)
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=item previous_var
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
The previous_var parameter sets the name of the variable that represents the
|
148
|
|
|
|
|
|
|
previous iteration step. It defaults to the name 'x' and must be a valid
|
149
|
|
|
|
|
|
|
Math::Symbolic variable identifier just like the iteration variable.
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item cached
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
This parameter indicates whether or not to cache the calculated series'
|
154
|
|
|
|
|
|
|
elements for faster direct access. It defaults to true. At run-time,
|
155
|
|
|
|
|
|
|
the caching behaviour may be altered using the cached() method.
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item start_index
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
The lower boundary for the series' summation. It defaults to 0, but may be
|
160
|
|
|
|
|
|
|
set to any positive integer or zero.
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=back
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=cut
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub new {
|
167
|
18
|
|
|
18
|
1
|
16476
|
my $proto = shift;
|
168
|
18
|
|
33
|
|
|
108
|
my $class = ref($proto) || $proto;
|
169
|
|
|
|
|
|
|
|
170
|
18
|
50
|
|
|
|
82
|
croak "Invalid number of arguments to Math::Series->new()."
|
171
|
|
|
|
|
|
|
if @_ % 2;
|
172
|
|
|
|
|
|
|
|
173
|
18
|
|
|
|
|
71
|
my %args = @_;
|
174
|
18
|
|
|
|
|
58
|
my $formula = $args{formula};
|
175
|
|
|
|
|
|
|
|
176
|
18
|
50
|
|
|
|
51
|
croak "Math::Series->new() requires a formula parameter."
|
177
|
|
|
|
|
|
|
if not defined $formula;
|
178
|
|
|
|
|
|
|
|
179
|
18
|
|
|
|
|
146
|
my $parsed = $Parser->parse($formula);
|
180
|
18
|
50
|
|
|
|
98146
|
croak "Error parsing formula." if not defined $parsed;
|
181
|
|
|
|
|
|
|
|
182
|
18
|
|
|
|
|
45
|
my $start = $args{start_value};
|
183
|
18
|
50
|
|
|
|
55
|
croak "A starting value must be supplied to Math::Series->new() as\n"
|
184
|
|
|
|
|
|
|
. "second argument."
|
185
|
|
|
|
|
|
|
if not defined $start;
|
186
|
18
|
|
|
|
|
121
|
$start = $Parser->parse($start);
|
187
|
18
|
50
|
|
|
|
20062
|
croak "Error parsing starting value." if not defined $start;
|
188
|
|
|
|
|
|
|
|
189
|
18
|
|
|
|
|
51
|
my $variable = $args{previous_var};
|
190
|
18
|
100
|
|
|
|
55
|
$variable = 'x' if not defined $variable;
|
191
|
|
|
|
|
|
|
|
192
|
18
|
|
|
|
|
46
|
my $iter_var = $args{iteration_var};
|
193
|
18
|
100
|
|
|
|
52
|
$iter_var = 'n' if not defined $iter_var;
|
194
|
|
|
|
|
|
|
|
195
|
18
|
|
|
|
|
32
|
my $cached = 1;
|
196
|
18
|
100
|
|
|
|
64
|
$cached = $args{cached} if exists $args{cached};
|
197
|
|
|
|
|
|
|
|
198
|
18
|
|
|
|
|
37
|
my $start_index = $args{start_index};
|
199
|
|
|
|
|
|
|
|
200
|
18
|
100
|
|
|
|
45
|
$start_index = 0 if not defined $start_index;
|
201
|
|
|
|
|
|
|
|
202
|
18
|
|
|
|
|
167
|
my $self = {
|
203
|
|
|
|
|
|
|
cached => $cached,
|
204
|
|
|
|
|
|
|
var => $variable,
|
205
|
|
|
|
|
|
|
formula => $parsed,
|
206
|
|
|
|
|
|
|
current => $start_index,
|
207
|
|
|
|
|
|
|
current_value => $start,
|
208
|
|
|
|
|
|
|
cache => [$start],
|
209
|
|
|
|
|
|
|
iter_var => $iter_var,
|
210
|
|
|
|
|
|
|
start_index => $start_index,
|
211
|
|
|
|
|
|
|
};
|
212
|
18
|
|
|
|
|
132
|
return bless $self => $class;
|
213
|
|
|
|
|
|
|
}
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item next()
|
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
The next() method returns the next element of the series and advances the
|
218
|
|
|
|
|
|
|
iterator by one. This is the prefered method of walking down a series'
|
219
|
|
|
|
|
|
|
recursion.
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=cut
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub next {
|
224
|
372
|
|
|
372
|
1
|
25022
|
my $self = shift;
|
225
|
372
|
|
|
|
|
699
|
my $current_index = $self->{current};
|
226
|
372
|
|
|
|
|
706
|
my $current_value = $self->{current_value};
|
227
|
372
|
|
|
|
|
699
|
my $next_index = $current_index + 1;
|
228
|
372
|
|
|
|
|
523
|
my $start_index = $self->{start_index};
|
229
|
|
|
|
|
|
|
|
230
|
372
|
100
|
100
|
|
|
1360
|
if ( $self->{cached}
|
231
|
|
|
|
|
|
|
and defined $self->{cache}[ $next_index - $start_index ] )
|
232
|
|
|
|
|
|
|
{
|
233
|
18
|
|
|
|
|
40
|
$self->{current_value} = $self->{cache}[ $next_index - $start_index ];
|
234
|
18
|
|
|
|
|
25
|
$self->{current} = $next_index;
|
235
|
18
|
|
|
|
|
56
|
return $current_value;
|
236
|
|
|
|
|
|
|
}
|
237
|
|
|
|
|
|
|
|
238
|
354
|
|
|
|
|
1039
|
my $next_value = $current_value->new();
|
239
|
354
|
|
|
|
|
9156
|
my $add = $self->{formula}->new();
|
240
|
354
|
|
|
|
|
22256
|
$add->implement(
|
241
|
|
|
|
|
|
|
$self->{var} => $current_value,
|
242
|
|
|
|
|
|
|
$self->{iter_var} => $current_index + 1
|
243
|
|
|
|
|
|
|
);
|
244
|
354
|
|
|
|
|
539464
|
$add = $add->simplify();
|
245
|
354
|
|
|
|
|
164269
|
$next_value += $add;
|
246
|
354
|
|
|
|
|
14644
|
$next_value = $next_value->simplify();
|
247
|
|
|
|
|
|
|
|
248
|
354
|
100
|
|
|
|
143327
|
$self->{cache}[ $next_index - $start_index ] = $next_value
|
249
|
|
|
|
|
|
|
if $self->{cached};
|
250
|
354
|
|
|
|
|
650
|
$self->{current} = $next_index;
|
251
|
354
|
|
|
|
|
816
|
$self->{current_value} = $next_value;
|
252
|
|
|
|
|
|
|
|
253
|
354
|
|
|
|
|
1721
|
return $current_value;
|
254
|
|
|
|
|
|
|
}
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=item cached()
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Returns a true value if the series is currently being cached, false if it
|
259
|
|
|
|
|
|
|
isn't. By default, new objects have caching enabled. It is suggested that you
|
260
|
|
|
|
|
|
|
only disable caching if space is an issue and you will only walk the series
|
261
|
|
|
|
|
|
|
uni-directionally and only once.
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
cached() can be used to change the caching behaviour. If the first argument is
|
264
|
|
|
|
|
|
|
true, caching will be enabled. If it is false, caching will be disabled.
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=cut
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# cached inherited.
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item current_index()
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Returns the index of the current element. That is, the index of the element
|
273
|
|
|
|
|
|
|
that will be returned by the next call to the next() method.
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
This method also allows (re-)setting the element that will be next returned by
|
276
|
|
|
|
|
|
|
the next() method. In that case, the first argument shoudl be the appropriate
|
277
|
|
|
|
|
|
|
index.
|
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Returns undef and doesn't set the current index if the argument is below 0.
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=cut
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub current_index {
|
284
|
234
|
|
|
234
|
1
|
69452
|
my $self = shift;
|
285
|
234
|
100
|
66
|
|
|
991
|
if ( @_ and defined $_[0] ) {
|
286
|
42
|
|
|
|
|
688
|
my $index = shift;
|
287
|
42
|
100
|
|
|
|
157
|
return undef if $index < $self->{start_index};
|
288
|
24
|
|
|
|
|
238
|
$self->{current_value} = $self->at_index($index);
|
289
|
24
|
|
|
|
|
96
|
$self->{current} = $index;
|
290
|
24
|
|
|
|
|
296
|
return $index;
|
291
|
|
|
|
|
|
|
}
|
292
|
|
|
|
|
|
|
else {
|
293
|
192
|
|
|
|
|
764
|
return $self->{current};
|
294
|
|
|
|
|
|
|
}
|
295
|
|
|
|
|
|
|
}
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item at_index()
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
This method returns the series element with the index denoted by the first
|
300
|
|
|
|
|
|
|
argument to the method. It does not change the state of the iterator.
|
301
|
|
|
|
|
|
|
This method is extremely slow for uncached series.
|
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
Returns undef for indices below the starting index.
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=cut
|
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub at_index {
|
308
|
120
|
|
|
120
|
1
|
19527
|
my $self = shift;
|
309
|
120
|
|
|
|
|
168
|
my $index = shift;
|
310
|
120
|
50
|
|
|
|
336
|
croak "Math::Series->at_index() takes an index as argument."
|
311
|
|
|
|
|
|
|
if not defined $index;
|
312
|
120
|
|
|
|
|
264
|
my $start_index = $self->{start_index};
|
313
|
120
|
100
|
|
|
|
335
|
return undef if $index < $start_index;
|
314
|
|
|
|
|
|
|
|
315
|
108
|
100
|
100
|
|
|
839
|
return $self->{cache}[ $index - $start_index ]
|
316
|
|
|
|
|
|
|
if $self->{cached}
|
317
|
|
|
|
|
|
|
and defined $self->{cache}[ $index - $start_index ];
|
318
|
|
|
|
|
|
|
|
319
|
84
|
100
|
|
|
|
258
|
if ( $self->{cached} ) {
|
320
|
6
|
50
|
|
|
|
15
|
if ( $index - $start_index > $#{ $self->{cache} } ) {
|
|
6
|
|
|
|
|
29
|
|
321
|
6
|
|
|
|
|
16
|
my $old_index = $self->{current};
|
322
|
6
|
|
|
|
|
44
|
$self->next() for 1 .. $index - $self->{current};
|
323
|
6
|
|
|
|
|
14
|
my $value = $self->{current_value};
|
324
|
6
|
|
|
|
|
15
|
$self->{current} = $old_index;
|
325
|
6
|
|
|
|
|
18
|
$self->{current_value} =
|
326
|
|
|
|
|
|
|
$self->{cache}[ $old_index - $start_index ];
|
327
|
6
|
|
|
|
|
26
|
return $value;
|
328
|
|
|
|
|
|
|
}
|
329
|
|
|
|
|
|
|
else {
|
330
|
0
|
0
|
|
|
|
0
|
return $self->{cache}[ $index - $start_index ]
|
331
|
|
|
|
|
|
|
if defined $self->{cache}[ $index - $start_index ];
|
332
|
0
|
|
|
|
|
0
|
my $last_defined = $index;
|
333
|
0
|
|
0
|
|
|
0
|
while ( not defined $self->{cache}[ $last_defined - $start_index ]
|
334
|
|
|
|
|
|
|
and $last_defined >= $start_index )
|
335
|
|
|
|
|
|
|
{
|
336
|
0
|
|
|
|
|
0
|
$last_defined--;
|
337
|
|
|
|
|
|
|
}
|
338
|
0
|
0
|
|
|
|
0
|
die "Sanity check!" if $last_defined < $start_index;
|
339
|
0
|
|
|
|
|
0
|
my $old_index = $self->{current};
|
340
|
0
|
|
|
|
|
0
|
$self->{current} = $last_defined;
|
341
|
0
|
|
|
|
|
0
|
$self->{current_value} =
|
342
|
|
|
|
|
|
|
$self->{cache}[ $last_defined - $start_index ];
|
343
|
0
|
|
|
|
|
0
|
$self->next() for 1 .. $index - $last_defined;
|
344
|
0
|
|
|
|
|
0
|
my $value = $self->{current_value};
|
345
|
0
|
|
|
|
|
0
|
$self->{current} = $old_index;
|
346
|
0
|
|
|
|
|
0
|
$self->{current_value} =
|
347
|
|
|
|
|
|
|
$self->{cache}[ $old_index - $start_index ];
|
348
|
0
|
|
|
|
|
0
|
return $value;
|
349
|
|
|
|
|
|
|
}
|
350
|
|
|
|
|
|
|
}
|
351
|
|
|
|
|
|
|
else { # not $self->{cached}
|
352
|
78
|
50
|
|
|
|
218
|
return $self->{current_value} if $index == $self->{current};
|
353
|
78
|
|
|
|
|
141
|
my $old_index = $self->{current};
|
354
|
78
|
|
|
|
|
114
|
my $old_value = $self->{current_value};
|
355
|
78
|
|
|
|
|
111
|
my $value;
|
356
|
78
|
100
|
|
|
|
219
|
if ( $index < $self->{current} ) {
|
357
|
60
|
|
|
|
|
104
|
$self->{current} = $start_index;
|
358
|
60
|
|
|
|
|
153
|
$self->{current_value} = $self->{cache}[0];
|
359
|
60
|
|
|
|
|
292
|
$self->next() for $start_index .. $index - 1;
|
360
|
60
|
|
|
|
|
302
|
$value = $self->{current_value};
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
else {
|
363
|
18
|
|
|
|
|
110
|
$self->next() for 1 .. $index - $old_index;
|
364
|
18
|
|
|
|
|
56
|
$value = $self->{current_value};
|
365
|
|
|
|
|
|
|
}
|
366
|
78
|
|
|
|
|
206
|
$self->{current} = $old_index;
|
367
|
78
|
|
|
|
|
190
|
$self->{current_value} = $old_value;
|
368
|
78
|
|
|
|
|
293
|
return $value;
|
369
|
|
|
|
|
|
|
}
|
370
|
|
|
|
|
|
|
}
|
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=item back()
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
This methods returns the series element previously returned by the next()
|
375
|
|
|
|
|
|
|
method. Since it is extremely slow on uncached series, it warns about this
|
376
|
|
|
|
|
|
|
performance hit by default. To turn this warning off, set the
|
377
|
|
|
|
|
|
|
$Math::Series::warnings scalar to a false value.
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
This method decrements the current iterator series element.
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Returns undef if the current index goes below the starting index.
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub back {
|
386
|
108
|
|
|
108
|
1
|
40054
|
my $self = shift;
|
387
|
108
|
|
|
|
|
241
|
my $current_index = $self->{current};
|
388
|
108
|
|
|
|
|
202
|
my $current_value = $self->{current_value};
|
389
|
108
|
|
|
|
|
174
|
my $prev_index = $current_index - 1;
|
390
|
108
|
|
|
|
|
177
|
my $start_index = $self->{start_index};
|
391
|
108
|
100
|
|
|
|
303
|
return undef if $prev_index < $start_index;
|
392
|
|
|
|
|
|
|
|
393
|
96
|
50
|
66
|
|
|
386
|
carp "Use of the back() method on uncached series is not advised."
|
394
|
|
|
|
|
|
|
if ( not $self->{cached} )
|
395
|
|
|
|
|
|
|
and $Math::Series::warnings;
|
396
|
|
|
|
|
|
|
|
397
|
96
|
100
|
66
|
|
|
507
|
if ( $self->{cached}
|
398
|
|
|
|
|
|
|
and defined $self->{cache}[ $prev_index - $start_index ] )
|
399
|
|
|
|
|
|
|
{
|
400
|
48
|
|
|
|
|
128
|
$self->{current_value} = $self->{cache}[ $prev_index - $start_index ];
|
401
|
48
|
|
|
|
|
96
|
$self->{current} = $prev_index;
|
402
|
48
|
|
|
|
|
251
|
return $self->{current_value};
|
403
|
|
|
|
|
|
|
}
|
404
|
|
|
|
|
|
|
|
405
|
48
|
|
|
|
|
148
|
my $prev_value = $self->at_index($prev_index);
|
406
|
48
|
|
|
|
|
98
|
$self->{current} = $prev_index;
|
407
|
48
|
|
|
|
|
106
|
$self->{current_value} = $prev_value;
|
408
|
|
|
|
|
|
|
|
409
|
48
|
|
|
|
|
248
|
return $prev_value;
|
410
|
|
|
|
|
|
|
}
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
1;
|
413
|
|
|
|
|
|
|
__END__
|