line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Algorithm::GoldenSection; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
32439
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
35
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
37
|
|
5
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
100
|
|
6
|
1
|
|
|
1
|
|
1156
|
use Readonly; |
|
1
|
|
|
|
|
4387
|
|
|
1
|
|
|
|
|
179
|
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
1043
|
use version; our $VERSION = qv('0.0.2'); |
|
1
|
|
|
|
|
2560
|
|
|
1
|
|
|
|
|
21
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Algorithm::GoldenSection - Golden Section Search Algorithm for one-dimensional minimisation. |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
=head1 VERSION |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
This document describes Algorithm::GoldenSection version 0.0.2 |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
20
|
|
|
|
|
|
|
=head1 DESCRIPTION |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
This module is an implementation of the Golden Section Search Algorithm for finding minima of a unimodal function. |
23
|
|
|
|
|
|
|
In order to isolate a minimum of a univariate functions the minimum must first be isolated. |
24
|
|
|
|
|
|
|
Consequently the program first bounds a minimum - i.e. the program initially creates a triplet of points: |
25
|
|
|
|
|
|
|
x_low < x_int < x_high, such that f(x_int) is lower than both f(x_low) and f(x_high). Thus we ensure that there |
26
|
|
|
|
|
|
|
is a local minimum within the interval: x_low-x_high. The program then uses the Golde Section Search algorithm |
27
|
|
|
|
|
|
|
to successively narrow down on the bounded region to find the minimum. |
28
|
|
|
|
|
|
|
See http://en.wikipedia.org/wiki/Golden_section_search and |
29
|
|
|
|
|
|
|
http://www.gnu.org/software/gsl/manual/html_node/One-dimensional-Minimization.html. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
The module provides a Perl5OO interface. Simply construct a Algorithm::GoldenSection object with appropriate parameters |
32
|
|
|
|
|
|
|
- see L. Then call the minimise C. This returns a LIST of the value of x at the minimum, the value of |
33
|
|
|
|
|
|
|
f(x) at the minimum and the number of iterations used to isolate the minimum. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=cut |
36
|
|
|
|
|
|
|
=head1 SYNOPSIS |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
use Algorithm::GoldenSection; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Create a Algorithm::GoldenSection object and pass it a CODE reference to the function to be minimised and initials values for x_low and x_int. |
41
|
|
|
|
|
|
|
$gs = Algorithm::GoldenSection->new( { function => sub { my $x = shift; my $b = $x * sin($x) - 2 * cos($x); return $b }, |
42
|
|
|
|
|
|
|
x_low => 4, |
43
|
|
|
|
|
|
|
x_int => 4.7,} ) ; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# Call minimisation method to bracket and minimise. |
46
|
|
|
|
|
|
|
my ($x_min, $f_min, $iterations) = $gs->minimise; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
print qq{\nMinimisation results: x a minimum = $x_min, function value at minimum = $f_min. Calculation took $iterations iterations}; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=cut |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# package-scoped lexicals |
53
|
|
|
|
|
|
|
Readonly::Scalar my $ouro => 1.618034 ; |
54
|
|
|
|
|
|
|
Readonly::Scalar my $glimite => 100.0 ; |
55
|
|
|
|
|
|
|
Readonly::Scalar my $pequeninho => 1.0e-20 ; |
56
|
|
|
|
|
|
|
Readonly::Scalar my $tolerancia => 3.0e-8; # tolerance |
57
|
|
|
|
|
|
|
Readonly::Scalar my $C => (3-sqrt(5))/2; |
58
|
|
|
|
|
|
|
Readonly::Scalar my $R => 1-$C; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
#/ I had leaving things for operator precedence. you won´t see A+B*(C-D) whe you mean: A+( B*(C-D) ) - i.e. * binds more tightly that + |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub new { |
63
|
0
|
|
|
0
|
0
|
|
my ( $class, $h_ref ) = @_; |
64
|
0
|
0
|
0
|
|
|
|
croak qq{\nArguments must be passed as HASH reference.} if ( ( $h_ref ) && ( ref $h_ref ne q{HASH} ) ); |
65
|
0
|
|
|
|
|
|
my $self = {}; |
66
|
0
|
|
|
|
|
|
bless $self, $class; |
67
|
0
|
|
|
|
|
|
$self->_check_options($h_ref); |
68
|
0
|
|
|
|
|
|
return $self; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub _check_options { |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
0
|
|
|
my ( $self, $h_ref ) = @_; |
74
|
|
|
|
|
|
|
|
75
|
0
|
0
|
0
|
|
|
|
croak qq{\nOption \x27function\x27 is obrigatory and accepts a CODE reference} |
76
|
|
|
|
|
|
|
if ( ( !exists $h_ref->{function} ) || ( ref $h_ref->{function} ne q{CODE} ) ); |
77
|
0
|
0
|
0
|
|
|
|
croak qq{\nOption \x27x_low\x27 requirements a numeric value} |
78
|
|
|
|
|
|
|
if ( ( !exists $h_ref->{x_low} ) || ( $h_ref->{x_low} !~ /\A[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/xms ) ); |
79
|
0
|
0
|
0
|
|
|
|
croak qq{\nOption \x27x_low\x27 requirements a numeric value} |
80
|
|
|
|
|
|
|
if ( ( !exists $h_ref->{x_int} ) || ( $h_ref->{x_int} !~ /\A[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/xms ) ); |
81
|
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
$self->{function} = $h_ref->{function}; |
83
|
0
|
|
|
|
|
|
$self->{x_low} = $h_ref->{x_low}; |
84
|
0
|
|
|
|
|
|
$self->{x_int} = $h_ref->{x_int}; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub _switch { |
89
|
|
|
|
|
|
|
# twat did you usual of forgetting @_ and then you didn´t even return from it! |
90
|
0
|
|
|
0
|
|
|
my ( $a, $b, $f_a, $f_b) = @_; |
91
|
0
|
|
|
|
|
|
my $buf = $a; |
92
|
0
|
|
|
|
|
|
my $f_buf = $f_a; |
93
|
0
|
|
|
|
|
|
$a = $b; |
94
|
0
|
|
|
|
|
|
$f_a = $f_b; |
95
|
0
|
|
|
|
|
|
$b = $buf; |
96
|
0
|
|
|
|
|
|
$f_b = $f_buf; |
97
|
0
|
|
|
|
|
|
return ($a, $b, $f_a, $f_b); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub minimise { |
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
#y bracket interval |
105
|
0
|
|
|
|
|
|
$self->_bracket; |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
my $func = $self->{function}; |
108
|
0
|
|
|
|
|
|
my $a = $self->{x_low}; |
109
|
0
|
|
|
|
|
|
my $b = $self->{x_int}; |
110
|
0
|
|
|
|
|
|
my $c = $self->{x_high}; |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
my $x1; |
113
|
|
|
|
|
|
|
my $x2; |
114
|
|
|
|
|
|
|
# this is not efficient code... |
115
|
0
|
|
|
|
|
|
my $x0 = $self->{x_low}; |
116
|
0
|
|
|
|
|
|
my $x3 = $self->{x_high}; |
117
|
|
|
|
|
|
|
|
118
|
0
|
0
|
|
|
|
|
if ( abs($c-$b) > abs($b-$a) ) { |
119
|
0
|
|
|
|
|
|
$x1 = $b; |
120
|
|
|
|
|
|
|
#y create new point to try |
121
|
0
|
|
|
|
|
|
$x2 = $b + ( $C * ($c-$b) ); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
else { |
124
|
0
|
|
|
|
|
|
$x2 = $b; |
125
|
|
|
|
|
|
|
#y create new point to try |
126
|
0
|
|
|
|
|
|
$x1 = $b - ( $C * ($b-$a) ); |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#y initial function evaluations |
130
|
0
|
|
|
|
|
|
my $f1 = $func->($x1); |
131
|
0
|
|
|
|
|
|
my $f2 = $func->($x2); |
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
my $counter = 0; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
#y start iterating... |
136
|
0
|
|
|
|
|
|
while ( abs($x3-$x0) > ( $tolerancia * ( abs($x1) + abs($x2) ) ) ) { |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#y lets increment here just to make it easier - hence start with 0 |
139
|
0
|
|
|
|
|
|
$counter++; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
#y a possible outcome |
142
|
0
|
0
|
|
|
|
|
if ( $f2 < $f1 ) { |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
######################################### |
145
|
|
|
|
|
|
|
#y choose one of the two - but why the fuck-up with $R multiplication?!? |
146
|
|
|
|
|
|
|
######################################### |
147
|
|
|
|
|
|
|
#y the following is identical to: |
148
|
0
|
|
|
|
|
|
$x0 = $x1; |
149
|
0
|
|
|
|
|
|
$x1 = $x2; |
150
|
0
|
|
|
|
|
|
$x2 = ($R*$x2) + ($C*$x3); # |
151
|
0
|
|
|
|
|
|
$f1 = $f2; |
152
|
0
|
|
|
|
|
|
$f2 = $func->($x2); |
153
|
|
|
|
|
|
|
######################################### |
154
|
|
|
|
|
|
|
# my $x_temp = ($R*$x2) + ($C*$x3); |
155
|
|
|
|
|
|
|
# &_shft3(\$x0,\$x1,\$x2,\$x_temp); |
156
|
|
|
|
|
|
|
# my $f_x_temp = $func->($x2); |
157
|
|
|
|
|
|
|
# &_shft2(\$f1,\$f2,\$f_x_temp); |
158
|
|
|
|
|
|
|
######################################### |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
#y other possibility |
161
|
|
|
|
|
|
|
else { |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
######################################### |
164
|
0
|
|
|
|
|
|
$x3 = $x2; |
165
|
0
|
|
|
|
|
|
$x2 = $x1; |
166
|
0
|
|
|
|
|
|
$x1 = ($R*$x1) + ($C*$x0); |
167
|
0
|
|
|
|
|
|
$f2 = $f1; |
168
|
0
|
|
|
|
|
|
$f1 = $func->($x1); |
169
|
|
|
|
|
|
|
######################################### |
170
|
|
|
|
|
|
|
# my $x_temp = ($R*$x1) + ($C*$x0); |
171
|
|
|
|
|
|
|
# &_shft3(\$x3,\$x2,\$x1,\$x_temp); |
172
|
|
|
|
|
|
|
# my $f_x_temp = $func->($x1); |
173
|
|
|
|
|
|
|
# &_shft2(\$f2,\$f1,\$f_x_temp); |
174
|
|
|
|
|
|
|
######################################### |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
my $xmin; |
179
|
|
|
|
|
|
|
my $fmin; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
#y set final values |
182
|
0
|
0
|
|
|
|
|
if ($f1 < $f2) { |
183
|
0
|
|
|
|
|
|
$xmin = $x1; |
184
|
0
|
|
|
|
|
|
$fmin = $f1; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
else { |
187
|
0
|
|
|
|
|
|
$xmin = $x2; |
188
|
0
|
|
|
|
|
|
$fmin = $f2; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
return $xmin, $fmin, $counter; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub _bracket { |
195
|
|
|
|
|
|
|
|
196
|
0
|
|
|
0
|
|
|
my $self = shift; |
197
|
|
|
|
|
|
|
|
198
|
0
|
|
|
|
|
|
my $function = $self->{function}; |
199
|
0
|
|
|
|
|
|
$a = $self->{x_low}; |
200
|
0
|
|
|
|
|
|
$b = $self->{x_int}; |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
my $f_u; |
203
|
0
|
|
|
|
|
|
my $f_a = $function->($a); |
204
|
0
|
|
|
|
|
|
my $f_b = $function->($b); |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
#y that is downhill |
207
|
0
|
0
|
|
|
|
|
if ($f_b > $f_a ) { |
208
|
|
|
|
|
|
|
#print qq{\n\n**** in this case fb is higher than fa - thus we are going uphill so we need to swap them****\n}; |
209
|
0
|
|
|
|
|
|
print qq{\n\nswitch $a, $b, $f_a and $f_b}; |
210
|
0
|
|
|
|
|
|
( $a, $b, $f_a, $f_b) = _switch( $a, $b, $f_a, $f_b); |
211
|
0
|
|
|
|
|
|
print qq{\n\nswitch $a, $b, $f_a and $f_b}; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# has higher precedence that + thus: $c = $b+$ouro*($b-$a); is the same as $c = $b+($gold*($b-$a)); - same in C/C++ |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
#y WE MAKE A GUESS AT A VALUE OF C |
217
|
0
|
|
|
|
|
|
my $c = $b + ( $ouro * ($b-$a) ); # c 26.18034 and f_c 21.6787847478271 |
218
|
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
my $f_c = $function->($c); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# (1) by SWAPPING we are sure that f(a) > f(b)! - (2) BUT we must also have f(b) < f(c) in order to have _bracketed our MINIMUM |
222
|
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
|
while ( $f_b > $f_c ) { |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
#y compute u by parabolic extrapolation - tiny is there just to stop ilegal divisions by 0 |
226
|
0
|
|
|
|
|
|
my $r = ($b-$a) * ($f_b-$f_c); |
227
|
0
|
|
|
|
|
|
my $q = ($b-$c) * ($f_b-$f_a); |
228
|
0
|
|
|
|
|
|
my $u = $b - ( ( $b - $c ) * $q - ( $b - $a ) * $r ) / ( 2.0 * &_sign ( &_max ( abs ($q-$r), $pequeninho ), $q-$r ) ); |
229
|
0
|
|
|
|
|
|
my $ulim = $b + ( $glimite * ($c-$b) ); |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
#y test the possibilities! |
232
|
|
|
|
|
|
|
|
233
|
0
|
0
|
|
|
|
|
if ( ($b-$u)*($u-$c) > 0.0 ) { #y parabolic u is between b and c |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
$f_u = $function->($u); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
#y have a minimium between b and c - i.e. is f(u) < f(c) - if so: |
237
|
0
|
0
|
|
|
|
|
if ( $f_u < $f_c ) { |
|
|
0
|
|
|
|
|
|
238
|
|
|
|
|
|
|
|
239
|
0
|
|
|
|
|
|
$a = $b; |
240
|
0
|
|
|
|
|
|
$b = $u; |
241
|
0
|
|
|
|
|
|
$f_a = $f_b; |
242
|
0
|
|
|
|
|
|
$f_b = $f_u; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
#/ we´re going to return early here so as we aren´t using any package-scoped vars we will need to feed the object here |
245
|
0
|
|
|
|
|
|
$self->{x_low} = $a; |
246
|
0
|
|
|
|
|
|
$self->{x_int} = $b; |
247
|
0
|
|
|
|
|
|
$self->{x_high} = $c; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
return |
250
|
0
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
elsif ( $f_u > $f_b ) { |
252
|
0
|
|
|
|
|
|
$c = $u; |
253
|
0
|
|
|
|
|
|
$f_c = $f_u; |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
#/ we´re going to return early here so as we aren´t using any package-scoped vars we will need to feed the object here |
256
|
0
|
|
|
|
|
|
$self->{x_low} = $a; |
257
|
0
|
|
|
|
|
|
$self->{x_int} = $b; |
258
|
0
|
|
|
|
|
|
$self->{x_high} = $c; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
return |
261
|
0
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
#y parabolic fit was useless in this case - so we use a default magnification |
264
|
0
|
|
|
|
|
|
$u = $c + ( $ouro * ($c-$b) ); |
265
|
0
|
|
|
|
|
|
$f_u = $function->($u); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
#y parabolic fit is between c and is not allowed |
269
|
|
|
|
|
|
|
elsif ( ($c-$u)*($u-$ulim) > 0 ) { |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
$f_u = $function->($u); |
272
|
|
|
|
|
|
|
|
273
|
0
|
0
|
|
|
|
|
if ( $f_u < $f_c ) { |
274
|
|
|
|
|
|
|
|
275
|
0
|
|
|
|
|
|
my $u_other = $u + ( $ouro * ($u-$c) ); |
276
|
|
|
|
|
|
|
#/ this should make b = c, c = u and u = u_other |
277
|
0
|
|
|
|
|
|
&_shft3(\$b,\$c,\$u,$u_other); |
278
|
|
|
|
|
|
|
#/ so as u is now u_other this shouldn´t be a prob |
279
|
0
|
|
|
|
|
|
my $f_u_other = $function->($u_other); |
280
|
0
|
|
|
|
|
|
&_shft3(\$f_b,\$f_c,\$f_u, \$f_u_other); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
#y limit parabolic u to max allowed |
285
|
|
|
|
|
|
|
elsif ( ($u-$ulim)*($ulim-$c) >= 0.0 ) { |
286
|
0
|
|
|
|
|
|
$u = $ulim; |
287
|
0
|
|
|
|
|
|
$f_u = $function->($u); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
#y reject parabolic u |
291
|
|
|
|
|
|
|
else { |
292
|
0
|
|
|
|
|
|
$u = $c + ( $ouro * ($c-$b) ); |
293
|
0
|
|
|
|
|
|
$f_u = $function->($u); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
#y eliminate oldest points and will continue}; |
297
|
|
|
|
|
|
|
|
298
|
0
|
|
|
|
|
|
&_shft3(\$a,\$b,\$c,\$u); |
299
|
0
|
|
|
|
|
|
&_shft3(\$f_a,\$f_b,\$f_c,\$f_u); |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
0
|
0
|
0
|
|
|
|
croak qq{\nThere is a problem - email dsth\@cantab.net.} if ( !$a || !$b || !$c );#|| ( $b > $a ) || ( $b > $c ) ); |
|
|
|
0
|
|
|
|
|
304
|
0
|
|
|
|
|
|
$self->{x_low} = $a; |
305
|
0
|
|
|
|
|
|
$self->{x_int} = $b; |
306
|
0
|
|
|
|
|
|
$self->{x_high} = $c; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub _sign { |
310
|
0
|
|
|
0
|
|
|
my ($a, $b) = @_; |
311
|
0
|
|
|
|
|
|
my $val = abs $a; |
312
|
0
|
0
|
|
|
|
|
my $sig = $b >= 0 ? q{+} : q{-}; |
313
|
0
|
|
|
|
|
|
my $final = $sig.$val; |
314
|
|
|
|
|
|
|
# force numeric context - no real reason |
315
|
0
|
|
|
|
|
|
return 0+$final; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _max { |
319
|
0
|
|
|
0
|
|
|
my ($a, $b) = @_; |
320
|
0
|
0
|
|
|
|
|
my $ret = $a >= $b ? $a : $b; |
321
|
0
|
|
|
|
|
|
return $ret; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub _shft3 { |
325
|
0
|
|
|
0
|
|
|
my ($a, $b, $c, $d) = @_; |
326
|
0
|
|
|
|
|
|
$$a = $$b; |
327
|
0
|
|
|
|
|
|
$$b = $$c; |
328
|
0
|
|
|
|
|
|
$$c = $$d; |
329
|
0
|
|
|
|
|
|
return; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub _shft2 { |
333
|
0
|
|
|
0
|
|
|
my ($a, $b, $c) = @_; |
334
|
0
|
|
|
|
|
|
$$a = $$b; |
335
|
0
|
|
|
|
|
|
$$b = $$c; |
336
|
0
|
|
|
|
|
|
return; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
1; # Magic true value required at end of module |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
__END__ |