line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Math::Numerical; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
417574
|
use 5.022; |
|
2
|
|
|
|
|
17
|
|
4
|
2
|
|
|
2
|
|
9
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
33
|
|
5
|
2
|
|
|
2
|
|
7
|
use warnings; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
35
|
|
6
|
2
|
|
|
2
|
|
7
|
use utf8; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
10
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = 0.02; |
9
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
84
|
use feature 'signatures'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
321
|
|
11
|
2
|
|
|
2
|
|
12
|
no warnings 'experimental::signatures'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
92
|
|
12
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
11
|
use Carp; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
141
|
|
14
|
2
|
|
|
2
|
|
10
|
use Config; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
91
|
|
15
|
2
|
|
|
2
|
|
8
|
use Exporter 'import'; |
|
2
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
75
|
|
16
|
2
|
|
|
2
|
|
19
|
use POSIX (); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
215
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=pod |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=encoding utf8 |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 NAME |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Math::Numerical |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Numerical analysis and scientific computing related functions. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use Math::Numerical ':all'; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub f { cos($_[0]) * $_[0] ** 2 } # cos(x)·x² |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my $root = find_root(\&f, -1, 1); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 DESCRIPTION |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
This module offers functions to manipulate numerical functions such as root |
39
|
|
|
|
|
|
|
finding (solver), derivatives, etc. Most of the functions of this module can receive a |
40
|
|
|
|
|
|
|
C<$func> argument. This argument should always be a code reference (an anonymous |
41
|
|
|
|
|
|
|
sub or a reference to a named code block). And that referenced function should |
42
|
|
|
|
|
|
|
expect a single scalar (numeric) argument and return a single scalar (numeric) |
43
|
|
|
|
|
|
|
value. For efficiency reason, it is recommended to not name the argument of that |
44
|
|
|
|
|
|
|
function (see the L). |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 FUNCTIONS |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
By default, none of the functions below are exported by this package. They can |
49
|
|
|
|
|
|
|
be selectively imported or you can import them all with the tag C<:all>. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=cut |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
our @EXPORT = (); |
54
|
|
|
|
|
|
|
our @EXPORT_OK = qw(find_root bracket); |
55
|
|
|
|
|
|
|
our %EXPORT_TAGS = (all => \@EXPORT_OK); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# This will need to be adapted if we start using bigfloat. |
58
|
2
|
50
|
|
2
|
|
13
|
use constant _EPS => $Config{uselongdouble} ? POSIX::LDBL_EPSILON : POSIX::DBL_EPSILON; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
326
|
|
59
|
2
|
|
|
2
|
|
12
|
use constant _DEFAULT_TOLERANCE => 0.00001; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
2688
|
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# Wraps the given numerical function in a way where we’re guaranteeing that it’s |
62
|
|
|
|
|
|
|
# called in a scalar context and where we’re trapping its errors. |
63
|
8
|
|
|
8
|
|
10
|
sub _wrap_func($func) { |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
10
|
|
64
|
8
|
50
|
|
|
|
20
|
croak "The passed $func is not a code reference" unless ref($func) eq 'CODE'; |
65
|
|
|
|
|
|
|
return sub { |
66
|
39
|
|
|
39
|
|
45
|
my $r = eval { &$func }; |
|
39
|
|
|
|
|
145
|
|
67
|
39
|
50
|
|
|
|
315
|
return $r if defined $r; |
68
|
0
|
0
|
|
|
|
0
|
croak "The function failed: $@" if $@; |
69
|
0
|
|
|
|
|
0
|
croak "The function returned no value"; |
70
|
|
|
|
|
|
|
} |
71
|
8
|
|
|
|
|
43
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# Returns a value with the same magnitude as $val and the same sign as $sign. |
74
|
|
|
|
|
|
|
sub _sign { # ($val, $sign) |
75
|
3
|
50
|
|
3
|
|
9
|
return $_[0] * $_[1] > 0 ? $_[0] : -$_[0]; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 find_root |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
find_root($func, $x1, $x2, %params) |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Given a function C<$func> assumed to be continuous and a starting interval |
83
|
|
|
|
|
|
|
C<[$x1, $x2]>, tries to find a root of the function (a point where the |
84
|
|
|
|
|
|
|
function’s value is 0). The root found may be either inside or outside the |
85
|
|
|
|
|
|
|
starting interval. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
If the function is successful it returns the root found in scalar context or, in |
88
|
|
|
|
|
|
|
list context, a list with the root and the value of the function at that point |
89
|
|
|
|
|
|
|
(which may not be exactly C<0>). |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
The current implementation of this function is based on the method C |
92
|
|
|
|
|
|
|
from the I> book. |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
The function supports the following parameters: |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=over |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item C |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
How many iterations of our algorithm will be applied at most while trying to |
101
|
|
|
|
|
|
|
find a root for the given function. This gives an order of magnitude of the |
102
|
|
|
|
|
|
|
number of times that C<$func> will be evaluated. Defaults to I<100>. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=item C |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Whether the C> function should be used to bracket a root of the |
107
|
|
|
|
|
|
|
function before finding the root. If this is set to a false value, then the |
108
|
|
|
|
|
|
|
passed C<$x1> and C<$x2> values must already form a bracket (that is, the |
109
|
|
|
|
|
|
|
function must take values of opposite sign at these two points). Note that, when |
110
|
|
|
|
|
|
|
they do, the C> function will immediately return these values. So, |
111
|
|
|
|
|
|
|
if C return a result with C set to a I value, it |
112
|
|
|
|
|
|
|
will return the same result when C is set to a I value. |
113
|
|
|
|
|
|
|
However, if C is set to a I value, then C will |
114
|
|
|
|
|
|
|
immediately C> if the starting interval does not form a bracket |
115
|
|
|
|
|
|
|
of a root of the function. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
When set to a I value, the C> function is called with the |
118
|
|
|
|
|
|
|
same arguments as those given to C, so any parameter supported by |
119
|
|
|
|
|
|
|
C> can also be passed to C. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Defaults to I<1>. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=item C |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Defaults to I<0.00001>. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=back |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
In addition, as noted above, when C is true, any of the parameters |
130
|
|
|
|
|
|
|
supported by the C> function can be passed and they will be |
131
|
|
|
|
|
|
|
forwarded to that function. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=cut |
134
|
|
|
|
|
|
|
|
135
|
4
|
|
|
4
|
1
|
122447
|
sub find_root($func, $x1, $x2, %params) { |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
4
|
|
136
|
4
|
|
100
|
|
|
18
|
my $do_bracket = $params{do_bracket} // 1; |
137
|
4
|
|
50
|
|
|
16
|
my $tol = $params{tolerance} // _DEFAULT_TOLERANCE; |
138
|
4
|
|
50
|
|
|
13
|
my $max_iter = $params{max_iteration} // 100; |
139
|
4
|
|
|
|
|
11
|
my $f = _wrap_func($func); |
140
|
4
|
|
|
|
|
18
|
my ($a, $b, $c, $d, $e); # = ($x1, $x2, $x2); |
141
|
4
|
|
|
|
|
0
|
my ($fa, $fb, $fc); # = ($f->($a), $f->($b)); |
142
|
4
|
|
|
|
|
0
|
my ($p, $q, $r, $s, $tol1, $xm); |
143
|
4
|
100
|
|
|
|
7
|
if ($do_bracket) { |
144
|
3
|
|
|
|
|
10
|
($a, $b, $fa, $fb) = bracket($func, $x1, $x2, %params); |
145
|
3
|
50
|
|
|
|
8
|
croak "Can’t bracket a root of the function" unless defined $a; |
146
|
|
|
|
|
|
|
} else { |
147
|
1
|
|
|
|
|
4
|
($a, $b) = ($x1, $x2); |
148
|
1
|
|
|
|
|
3
|
($fa, $fb) = ($f->($a), $f->($b)); |
149
|
1
|
50
|
33
|
|
|
19
|
croak "A root must be bracketed in [\$x1; \$x2]" |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
150
|
|
|
|
|
|
|
if ($fa > 0 && $fb > 0) || ($fa < 0 && $fb <0); |
151
|
|
|
|
|
|
|
} |
152
|
4
|
|
|
|
|
7
|
($c, $fc) = ($b, $fb); |
153
|
4
|
|
|
|
|
21
|
for my $i (1..$max_iter) { |
154
|
25
|
100
|
100
|
|
|
90
|
if (($fb > 0 && $fc > 0) || ($fb < 0 && $fc < 0)) { |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
155
|
21
|
|
|
|
|
23
|
($c, $fc) = ($a, $fa); |
156
|
21
|
|
|
|
|
34
|
$e = $d = $b - $a; |
157
|
|
|
|
|
|
|
} |
158
|
25
|
100
|
|
|
|
44
|
if (abs($fc) < abs($fb)) { |
159
|
2
|
|
|
|
|
6
|
($a, $b, $c) = ($b, $c, $b); |
160
|
2
|
|
|
|
|
3
|
($fa, $fb, $fc) = ($fb, $fc, $fb); |
161
|
|
|
|
|
|
|
} |
162
|
25
|
|
|
|
|
33
|
$tol1 = 2 * _EPS * abs($b) + 0.5 * $tol; |
163
|
25
|
|
|
|
|
27
|
$xm = 0.5 * ($c - $b); |
164
|
25
|
50
|
66
|
|
|
93
|
return wantarray ? ($b, $fb) : $b if abs($xm) <= $tol1 || $fb == 0; |
|
|
100
|
|
|
|
|
|
165
|
21
|
100
|
66
|
|
|
53
|
if (abs($e) >= $tol1 && abs($fa) > abs($fb)) { |
166
|
19
|
|
|
|
|
23
|
$s = $fb / $fa; |
167
|
19
|
100
|
|
|
|
25
|
if ($a == $c) { |
168
|
17
|
|
|
|
|
19
|
$p = 2 * $xm *$s; |
169
|
17
|
|
|
|
|
19
|
$q = 1 - $s; |
170
|
|
|
|
|
|
|
} else { |
171
|
2
|
|
|
|
|
3
|
$q = $fa / $fc; |
172
|
2
|
|
|
|
|
2
|
$r = $fb / $fc; |
173
|
2
|
|
|
|
|
5
|
$p = $s * (2 * $xm * $q * ($q - $r)- ($b - $a) * ($r - 1)); |
174
|
2
|
|
|
|
|
4
|
$q = ($q - 1) * ($r - 1) * ($s - 1); |
175
|
|
|
|
|
|
|
} |
176
|
19
|
100
|
|
|
|
35
|
$q = -$q if $p > 0; |
177
|
19
|
|
|
|
|
19
|
$p = abs($p); |
178
|
19
|
|
|
|
|
26
|
my $min1 = 3 * $xm * $q - abs($tol1 * $q); |
179
|
19
|
|
|
|
|
22
|
my $min2 = abs($e* $q); |
180
|
19
|
100
|
|
|
|
31
|
if (2 * $p < ($min1 < $min2 ? $min1 : $min2)) { |
|
|
50
|
|
|
|
|
|
181
|
19
|
|
|
|
|
20
|
$e = $d; |
182
|
19
|
|
|
|
|
32
|
$d = $p / $q; |
183
|
|
|
|
|
|
|
} else { |
184
|
0
|
|
|
|
|
0
|
$d = $xm; |
185
|
0
|
|
|
|
|
0
|
$e = $d; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} else { |
188
|
2
|
|
|
|
|
3
|
$d = $xm; |
189
|
2
|
|
|
|
|
4
|
$e = $d; |
190
|
|
|
|
|
|
|
} |
191
|
21
|
|
|
|
|
25
|
($a, $fa) = ($b, $fb); |
192
|
21
|
100
|
|
|
|
26
|
if (abs($d) > $tol1) { |
193
|
18
|
|
|
|
|
20
|
$b +=$d; |
194
|
|
|
|
|
|
|
} else { |
195
|
3
|
|
|
|
|
11
|
$b += _sign($tol1, $xm); |
196
|
|
|
|
|
|
|
} |
197
|
21
|
|
|
|
|
29
|
$fb = $f->($b); |
198
|
|
|
|
|
|
|
} |
199
|
0
|
|
|
|
|
0
|
return; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head2 bracket |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
bracket($func, $x1, $x2, %params) |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
Given a function C<$func> assumed to be continuous and a starting interval |
207
|
|
|
|
|
|
|
C<[$x1, $x2]>, tries to find a pair of point C<($a, $b)> such that the function |
208
|
|
|
|
|
|
|
has a root somewhere between these two points (the root is I by these |
209
|
|
|
|
|
|
|
points). The found points will be either inside or outside the starting |
210
|
|
|
|
|
|
|
interval. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
If the function is successful, it returns a list of four elements with the values |
213
|
|
|
|
|
|
|
C<$a> and C<$b> and then the values of function at these two points. Otherwise |
214
|
|
|
|
|
|
|
it returns an empty list. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
The function will C> if C<$x1> and C<$x2> are equal. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
The current implementation of this method is a mix of the methods C and |
219
|
|
|
|
|
|
|
C from the I> book. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
The function supports the following parameters: |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=over |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=item C |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
How many iterations of our algorithm will be applied at most while trying to |
228
|
|
|
|
|
|
|
bracket the given function. This gives an order of magnitude of the number of |
229
|
|
|
|
|
|
|
times that C<$func> will be evaluated. Defaults to I<100>. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item C |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Whether the function will try to bracket a root in an interval larger than the |
234
|
|
|
|
|
|
|
one given by C<[$x1, $x2]>. Defaults to I<1>. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=item C |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Whether the function will try to bracket a root in an interval smaller than the |
239
|
|
|
|
|
|
|
one given by C<[$x1, $x2]>. Defaults to I<1>. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=item C |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Tuning parameter describing the starting number of intervals into which the |
244
|
|
|
|
|
|
|
starting interval is split when looking inward for a bracket. Defaults to I<3>. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Note that the algorithm may change and this parameter may stop working or may |
247
|
|
|
|
|
|
|
take a different meaning in the future. |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=item C |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Tuning parameter describing a factor by which the inwards interval are split |
252
|
|
|
|
|
|
|
at each iteration. Defaults to I<3>. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
Note that the algorithm may change and this parameter may stop working or may |
255
|
|
|
|
|
|
|
take a different meaning in the future. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=item C |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Tuning parameter describing how much the starting interval is grown at each |
260
|
|
|
|
|
|
|
iteration when looking outward for a bracket. Defaults to I<1.6>. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
Note that the algorithm may change and this parameter may stop working or may |
263
|
|
|
|
|
|
|
take a different meaning in the future. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=back |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=cut |
268
|
|
|
|
|
|
|
|
269
|
4
|
|
|
4
|
1
|
104032
|
sub bracket ($func, $x1, $x2, %params) { |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
5
|
|
270
|
4
|
50
|
|
|
|
12
|
croak "\$x1 and \$x2 must be distinct in calls to Math::Numerical::bracket (${x1})" if $x1 == $x2; |
271
|
4
|
|
50
|
|
|
28
|
my $max_iter = $params{max_iteration} // 100; |
272
|
4
|
50
|
|
|
|
11
|
croak "max_iteration must be positive" unless $max_iter > 0; |
273
|
4
|
|
50
|
|
|
12
|
my $do_outward = $params{do_outward} // 1; |
274
|
4
|
|
50
|
|
|
12
|
my $do_inward = $params{do_inward} // 1; |
275
|
4
|
50
|
33
|
|
|
10
|
croak "One of do_outward and do_inward at least should be true" |
276
|
|
|
|
|
|
|
unless $do_outward || $do_inward; |
277
|
4
|
|
50
|
|
|
14
|
my $inward_split = $params{inward_split} // 3; |
278
|
4
|
50
|
|
|
|
11
|
croak "inward_split must be at least 2" unless $inward_split >= 2; |
279
|
4
|
|
50
|
|
|
13
|
my $inward_factor = $params{inward_factor} // 3; |
280
|
4
|
50
|
|
|
|
9
|
croak "inward_factor must be at least 2" unless $inward_factor >= 2; |
281
|
4
|
|
50
|
|
|
20
|
my $outward_factor = $params{outward_factor} // 1.6; |
282
|
4
|
50
|
|
|
|
14
|
croak "outward_factor must be larger than 1" unless $outward_factor > 1; |
283
|
4
|
|
|
|
|
7
|
my $f = _wrap_func($func); |
284
|
4
|
|
|
|
|
11
|
my ($xl1, $xl2) = ($x1, $x2); |
285
|
4
|
|
|
|
|
8
|
my $f1 = $f->($x1); |
286
|
4
|
|
|
|
|
10
|
my ($fl1, $fl2) = ($f1, $f->($xl2)); |
287
|
4
|
|
|
|
|
15
|
for my $i (1..$max_iter) { |
288
|
|
|
|
|
|
|
# We start with outward because the first iteration does nothing and just |
289
|
|
|
|
|
|
|
# checks the bounds that were given by the user. |
290
|
6
|
50
|
|
|
|
12
|
if ($do_outward) { |
291
|
6
|
100
|
|
|
|
39
|
return ($xl1, $xl2, $fl1, $fl2) if $fl1 * $fl2 < 0; |
292
|
2
|
50
|
|
|
|
18
|
if (abs($fl1) < abs($fl2)) { |
293
|
0
|
|
|
|
|
0
|
$xl1 += $outward_factor * ($xl1 -$xl2); |
294
|
0
|
|
|
|
|
0
|
$fl1 = $f->($xl1); |
295
|
|
|
|
|
|
|
} else { |
296
|
2
|
|
|
|
|
7
|
$xl2 += $outward_factor * ($xl2 -$xl1); |
297
|
2
|
|
|
|
|
5
|
$fl2 = $f->($xl2); |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
} |
300
|
2
|
50
|
|
|
|
6
|
if ($do_inward) { |
301
|
2
|
|
|
|
|
7
|
my $dx = ($x2 - $x1) / $inward_split; |
302
|
2
|
|
|
|
|
3
|
my $a = $x1; |
303
|
2
|
|
|
|
|
5
|
my ($fa, $fb) = ($f1); |
304
|
2
|
|
|
|
|
5
|
for my $j (1..$inward_split) { |
305
|
6
|
|
|
|
|
9
|
my $b = $a + $dx; |
306
|
6
|
|
|
|
|
10
|
$fb = $f->($b); |
307
|
6
|
50
|
|
|
|
16
|
return ($a, $b, $fa, $fb) if $fa * $fb < 0; |
308
|
6
|
|
|
|
|
9
|
($a, $fa) = ($b, $fb); |
309
|
|
|
|
|
|
|
} |
310
|
2
|
|
|
|
|
4
|
$inward_split *= $inward_factor; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
# We stop doing the inward algorithm when the number of splits exceeds |
313
|
|
|
|
|
|
|
# max_iteration, to bound the number of times the function is executed to a |
314
|
|
|
|
|
|
|
# reasonable value. |
315
|
2
|
50
|
|
|
|
19
|
$do_inward = 0 if $inward_split >= $max_iter; |
316
|
|
|
|
|
|
|
} |
317
|
0
|
|
|
|
|
|
return; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 AUTHOR |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Mathias Kende |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Copyright 2022 Mathias Kende |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=head1 SEE ALSO |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=over |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=item NR |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
L |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=back |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=cut |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
1; |