| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package ConstantCalculus::CircleConstant; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Set the VERSION. |
|
4
|
|
|
|
|
|
|
our $VERSION = "0.02"; |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# Load the Perl pragmas. |
|
7
|
1
|
|
|
1
|
|
75228
|
use 5.008009; |
|
|
1
|
|
|
|
|
16
|
|
|
8
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
20
|
|
|
9
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
53
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Load the Perl pragma Exporter. |
|
12
|
1
|
|
|
1
|
|
7
|
use vars qw(@ISA @EXPORT @EXPORT_OK); |
|
|
1
|
|
|
|
|
12
|
|
|
|
1
|
|
|
|
|
90
|
|
|
13
|
1
|
|
|
1
|
|
8
|
use Exporter 'import'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
107
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Base class of this (tron_addr) module. |
|
16
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Exporting the implemented subroutine. |
|
19
|
|
|
|
|
|
|
our @EXPORT = qw( |
|
20
|
|
|
|
|
|
|
chudnovsky_algorithm |
|
21
|
|
|
|
|
|
|
borwein25_algorithm |
|
22
|
|
|
|
|
|
|
pi_borwein25 |
|
23
|
|
|
|
|
|
|
tau_borwein25 |
|
24
|
|
|
|
|
|
|
pi_chudnovsky |
|
25
|
|
|
|
|
|
|
tau_chudnovsky |
|
26
|
|
|
|
|
|
|
bbp_algorithm |
|
27
|
|
|
|
|
|
|
bbp_digits |
|
28
|
|
|
|
|
|
|
bbp_digit |
|
29
|
|
|
|
|
|
|
S |
|
30
|
|
|
|
|
|
|
$PI_DEC |
|
31
|
|
|
|
|
|
|
$PI_HEX |
|
32
|
|
|
|
|
|
|
); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Exporting the multiply and divide routine on demand basis. |
|
35
|
|
|
|
|
|
|
@EXPORT_OK = qw( |
|
36
|
|
|
|
|
|
|
factorial |
|
37
|
|
|
|
|
|
|
sqrtroot |
|
38
|
|
|
|
|
|
|
modexp |
|
39
|
|
|
|
|
|
|
estimate_terms |
|
40
|
|
|
|
|
|
|
truncate_places |
|
41
|
|
|
|
|
|
|
); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Disable a warning. |
|
44
|
1
|
|
|
1
|
|
7
|
no warnings 'recursion'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Load the Perl module. |
|
47
|
1
|
|
|
1
|
|
760
|
use bignum; |
|
|
1
|
|
|
|
|
5868
|
|
|
|
1
|
|
|
|
|
6
|
|
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# Set the precision for bignum. |
|
50
|
|
|
|
|
|
|
bignum -> precision(-14); |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# Initialise pre-defined values of Pi. |
|
53
|
|
|
|
|
|
|
our $PI_DEC = undef; |
|
54
|
|
|
|
|
|
|
our $PI_HEX = undef; |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Initialise the array with the hexadecimal numbers. |
|
57
|
|
|
|
|
|
|
our @HX = ("0", "1", "2", "3", "4", "5", "6", "7", |
|
58
|
|
|
|
|
|
|
"8", "9", "A", "B", "C", "D", "E", "F"); |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
61
|
|
|
|
|
|
|
# Subroutine modexp() # |
|
62
|
|
|
|
|
|
|
# # |
|
63
|
|
|
|
|
|
|
# Description: # |
|
64
|
|
|
|
|
|
|
# The subroutine returns the result of a modular exponentiation. A modular # |
|
65
|
|
|
|
|
|
|
# exponentiation is an exponentiation applied over a modulus. The result of # |
|
66
|
|
|
|
|
|
|
# the modular exponentiation is the remainder when an integer b (the base) # |
|
67
|
|
|
|
|
|
|
# is exponentiated by e (the exponent) and divided by a positive integer m # |
|
68
|
|
|
|
|
|
|
# (modulus). # |
|
69
|
|
|
|
|
|
|
# # |
|
70
|
|
|
|
|
|
|
# @params $b Value of the base # |
|
71
|
|
|
|
|
|
|
# $e Value of the exponent # |
|
72
|
|
|
|
|
|
|
# $m Value of the modulus # |
|
73
|
|
|
|
|
|
|
# @returns $y Result of the modular exponentiation # |
|
74
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
75
|
|
|
|
|
|
|
sub modexp { |
|
76
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
77
|
0
|
|
|
0
|
1
|
0
|
my($b, $e, $m) = @_; |
|
78
|
|
|
|
|
|
|
# Initialise the return variable. |
|
79
|
0
|
|
|
|
|
0
|
my $y = 1; |
|
80
|
|
|
|
|
|
|
# Perfom the modular exponentiation. |
|
81
|
0
|
|
|
|
|
0
|
do { |
|
82
|
0
|
0
|
|
|
|
0
|
($y *= $b) %= $m if $e % 2; |
|
83
|
0
|
|
|
|
|
0
|
($b *= $b) %= $m; |
|
84
|
|
|
|
|
|
|
} while ($e = ($e/2) - (($e/2) % 1)); |
|
85
|
|
|
|
|
|
|
# Return the result of the modular exponentiation. |
|
86
|
0
|
|
|
|
|
0
|
return $y; |
|
87
|
|
|
|
|
|
|
}; |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
90
|
|
|
|
|
|
|
# Subroutine sqrtroot() # |
|
91
|
|
|
|
|
|
|
# # |
|
92
|
|
|
|
|
|
|
# Description: # |
|
93
|
|
|
|
|
|
|
# The subroutine calculates the square root of given number. # |
|
94
|
|
|
|
|
|
|
# # |
|
95
|
|
|
|
|
|
|
# @params $x Number for which the square root is sought # |
|
96
|
|
|
|
|
|
|
# @returns $y Square root of the given number $x # |
|
97
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
98
|
|
|
|
|
|
|
sub sqrtroot { |
|
99
|
|
|
|
|
|
|
# Assign the subroutine argument to the local variable. |
|
100
|
0
|
|
|
0
|
1
|
0
|
my $x = $_[0]; |
|
101
|
|
|
|
|
|
|
# Set the start values for the iteration. |
|
102
|
0
|
|
|
|
|
0
|
my $y = 1; |
|
103
|
0
|
|
|
|
|
0
|
my $y0 = 0; |
|
104
|
|
|
|
|
|
|
# Initialise the loop variables. |
|
105
|
0
|
|
|
|
|
0
|
my $i = 0; |
|
106
|
0
|
|
|
|
|
0
|
my $run = 1; |
|
107
|
|
|
|
|
|
|
# Run an infinite loop until the exit conditions is reached. |
|
108
|
0
|
|
|
|
|
0
|
while ($run == 1) { |
|
109
|
|
|
|
|
|
|
# Calculate the approximation. |
|
110
|
0
|
|
|
|
|
0
|
$y -= ($y * $y - $x) / (2 * $y); |
|
111
|
|
|
|
|
|
|
# Check termination criterion. |
|
112
|
0
|
0
|
|
|
|
0
|
$run = ($y0 == $y ? 0 : 1); |
|
113
|
|
|
|
|
|
|
# Store the approximation. |
|
114
|
0
|
|
|
|
|
0
|
$y0 = $y; |
|
115
|
|
|
|
|
|
|
# Increment the running variable. |
|
116
|
0
|
|
|
|
|
0
|
$i++; |
|
117
|
|
|
|
|
|
|
}; |
|
118
|
|
|
|
|
|
|
# Return the square root. |
|
119
|
0
|
|
|
|
|
0
|
return $y; |
|
120
|
|
|
|
|
|
|
}; |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
123
|
|
|
|
|
|
|
# Subroutine factorial() # |
|
124
|
|
|
|
|
|
|
# # |
|
125
|
|
|
|
|
|
|
# Description: # |
|
126
|
|
|
|
|
|
|
# The subroutine calculates the factorial of given number. # |
|
127
|
|
|
|
|
|
|
# # |
|
128
|
|
|
|
|
|
|
# @params $n Number for which the factorial is sought # |
|
129
|
|
|
|
|
|
|
# @returns $fact Factorial of the given number $n # |
|
130
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
131
|
|
|
|
|
|
|
sub factorial { |
|
132
|
|
|
|
|
|
|
# Assign the subroutine argument to the local variable. |
|
133
|
0
|
|
|
0
|
1
|
0
|
my $n = $_[0]; |
|
134
|
|
|
|
|
|
|
# Calculate the factorial of a number by recursion. |
|
135
|
0
|
0
|
|
|
|
0
|
my $fact = ($n == 0 ? 1 : factorial($n - 1) * $n); |
|
136
|
|
|
|
|
|
|
# Return the value of the factorial. |
|
137
|
0
|
|
|
|
|
0
|
return $fact; |
|
138
|
|
|
|
|
|
|
}; |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
141
|
|
|
|
|
|
|
# Subroutine truncate_places() # |
|
142
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
143
|
|
|
|
|
|
|
sub truncate_places { |
|
144
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
145
|
0
|
|
|
0
|
1
|
0
|
my $decimal = $_[0]; |
|
146
|
0
|
|
|
|
|
0
|
my $places = $_[1]; |
|
147
|
|
|
|
|
|
|
# Calculate the multiplication factor. |
|
148
|
0
|
|
|
|
|
0
|
my $factor = 10**$places; |
|
149
|
|
|
|
|
|
|
# Truncate the places using the multiplication factor. |
|
150
|
0
|
|
|
|
|
0
|
$decimal = int($decimal*$factor) / ($factor); |
|
151
|
|
|
|
|
|
|
# Truncate the decimal using the places plus two chars. |
|
152
|
0
|
|
|
|
|
0
|
$decimal = substr($decimal, 0, $places + 2); |
|
153
|
|
|
|
|
|
|
# Return the truncated decimal number. |
|
154
|
0
|
|
|
|
|
0
|
return $decimal; |
|
155
|
|
|
|
|
|
|
}; |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
158
|
|
|
|
|
|
|
# Subroutine estimate_terms() # |
|
159
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
160
|
|
|
|
|
|
|
sub estimate_terms { |
|
161
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
162
|
0
|
0
|
|
0
|
1
|
0
|
my $places = (defined $_[0] ? $_[0] : 0); |
|
163
|
0
|
0
|
|
|
|
0
|
my $new_places = (defined $_[1] ? $_[1] : 0); |
|
164
|
|
|
|
|
|
|
# Declare the return variable. |
|
165
|
0
|
|
|
|
|
0
|
my $number_terms = undef; |
|
166
|
|
|
|
|
|
|
# Determine the estimated number of terms. |
|
167
|
0
|
0
|
|
|
|
0
|
if ($places <= 1) { |
|
|
|
0
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
0
|
$number_terms = $places; |
|
169
|
|
|
|
|
|
|
} elsif ($places <= $new_places) { |
|
170
|
0
|
|
|
|
|
0
|
$number_terms = 1; |
|
171
|
|
|
|
|
|
|
} else { |
|
172
|
0
|
|
|
|
|
0
|
$number_terms = int($places / $new_places) + 1; |
|
173
|
|
|
|
|
|
|
}; |
|
174
|
|
|
|
|
|
|
# Return the estimated number of terms. |
|
175
|
0
|
|
|
|
|
0
|
return $number_terms; |
|
176
|
|
|
|
|
|
|
}; |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
179
|
|
|
|
|
|
|
# Subroutine is_unsigned_int() # |
|
180
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
181
|
|
|
|
|
|
|
sub is_unsigned_int { |
|
182
|
|
|
|
|
|
|
# Assign the subroutine argument to the local variable. |
|
183
|
0
|
0
|
|
0
|
0
|
0
|
my $arg = (defined $_[0] ? $_[0] : ''); |
|
184
|
|
|
|
|
|
|
# Set the Perl conform regex pattern. |
|
185
|
0
|
|
|
|
|
0
|
my $re = qr/^(([1-9][0-9]*)|0)$/; |
|
186
|
|
|
|
|
|
|
# Check the argument with the regex pattern. |
|
187
|
0
|
0
|
|
|
|
0
|
my $is_unsigned_int = (($arg =~ $re) ? 1 : 0); |
|
188
|
|
|
|
|
|
|
# Return 0 (false) or 1 (true). |
|
189
|
0
|
|
|
|
|
0
|
return $is_unsigned_int; |
|
190
|
|
|
|
|
|
|
}; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
193
|
|
|
|
|
|
|
# Subroutine check_places() # |
|
194
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
195
|
|
|
|
|
|
|
sub check_places { |
|
196
|
|
|
|
|
|
|
# Assign the subroutine argument to the local variable. |
|
197
|
0
|
0
|
|
0
|
0
|
0
|
my $places = (defined $_[0] ? $_[0] : 0); |
|
198
|
|
|
|
|
|
|
# Set the string for the farewell message. |
|
199
|
0
|
|
|
|
|
0
|
my $msg = "The number of places is not valid. Terminating processing. Bye!"; |
|
200
|
|
|
|
|
|
|
# Check if the given places are a valid number. |
|
201
|
0
|
0
|
|
|
|
0
|
if (is_unsigned_int($places) != 1) { |
|
202
|
|
|
|
|
|
|
# Print a message into the terminal window. |
|
203
|
0
|
|
|
|
|
0
|
print $msg . "\n"; |
|
204
|
|
|
|
|
|
|
# Exit the script. |
|
205
|
0
|
|
|
|
|
0
|
exit; |
|
206
|
|
|
|
|
|
|
}; |
|
207
|
|
|
|
|
|
|
# Return 1 (true). |
|
208
|
0
|
|
|
|
|
0
|
return 1; |
|
209
|
|
|
|
|
|
|
}; |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
212
|
|
|
|
|
|
|
# Subroutine S() # |
|
213
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
214
|
|
|
|
|
|
|
sub S { |
|
215
|
|
|
|
|
|
|
# Assign the subroutine arguments to local variables. |
|
216
|
0
|
|
|
0
|
1
|
0
|
my ($j, $n, $p) = @_; |
|
217
|
|
|
|
|
|
|
# Set the precision for bignum. |
|
218
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
219
|
|
|
|
|
|
|
# Initialise the variables for the left sum as well as the right sum. |
|
220
|
0
|
|
|
|
|
0
|
my ($l, $r) = (0, 0); |
|
221
|
|
|
|
|
|
|
# Initialise the variables for the total sum. |
|
222
|
0
|
|
|
|
|
0
|
my $sum = 0; |
|
223
|
|
|
|
|
|
|
# Initialise the variable for the denominator. |
|
224
|
0
|
|
|
|
|
0
|
my $d = 0; |
|
225
|
|
|
|
|
|
|
# Initialise the loop counter. |
|
226
|
0
|
|
|
|
|
0
|
my $k = 0; |
|
227
|
|
|
|
|
|
|
# Calculate the left sum. |
|
228
|
0
|
|
|
|
|
0
|
while ($k <= $n) { |
|
229
|
|
|
|
|
|
|
# Calculate the value of the denominator. |
|
230
|
0
|
|
|
|
|
0
|
$d = 8*$k+$j; |
|
231
|
|
|
|
|
|
|
# Calculate the left partial sum. |
|
232
|
0
|
|
|
|
|
0
|
$l = ($l + modexp(16, $n-$k, $d) / $d) % 1; |
|
233
|
|
|
|
|
|
|
# Increment the loop counter $k. |
|
234
|
0
|
|
|
|
|
0
|
$k += 1; |
|
235
|
|
|
|
|
|
|
}; |
|
236
|
|
|
|
|
|
|
# Initialise the variables for the right sum calculation. |
|
237
|
0
|
|
|
|
|
0
|
my $r0 = 0; |
|
238
|
|
|
|
|
|
|
# Reinitialise the loop counter. |
|
239
|
0
|
|
|
|
|
0
|
$k = $n + 1; |
|
240
|
|
|
|
|
|
|
# Initialise the run variable. |
|
241
|
0
|
|
|
|
|
0
|
my $run = 1; |
|
242
|
|
|
|
|
|
|
# Calculate the right sum. |
|
243
|
0
|
|
|
|
|
0
|
while ($run == 1) { |
|
244
|
|
|
|
|
|
|
# Calculate the value of the denominator. |
|
245
|
0
|
|
|
|
|
0
|
$d = 8*$k+$j; |
|
246
|
|
|
|
|
|
|
# Calculate the right partial sum. |
|
247
|
0
|
|
|
|
|
0
|
$r = $r0 + (16**($n-$k)) / $d; |
|
248
|
|
|
|
|
|
|
# Check the exit condition of the loop. |
|
249
|
0
|
0
|
|
|
|
0
|
$run = ($r0 == $r ? 0 : 1); |
|
250
|
|
|
|
|
|
|
# Save the old partial sum. |
|
251
|
0
|
|
|
|
|
0
|
$r0 = $r; |
|
252
|
|
|
|
|
|
|
# Increment the loop counter $k. |
|
253
|
0
|
|
|
|
|
0
|
$k += 1; |
|
254
|
|
|
|
|
|
|
}; |
|
255
|
|
|
|
|
|
|
# Calculate the total sum. |
|
256
|
0
|
|
|
|
|
0
|
$sum = $l + $r; |
|
257
|
|
|
|
|
|
|
# Return the total sum. |
|
258
|
0
|
|
|
|
|
0
|
return $sum; |
|
259
|
|
|
|
|
|
|
}; |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
262
|
|
|
|
|
|
|
# Subroutine bbp_digit() # |
|
263
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
264
|
|
|
|
|
|
|
sub bbp_digit { |
|
265
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
266
|
0
|
|
|
0
|
1
|
0
|
my ($n, $p) = @_; |
|
267
|
|
|
|
|
|
|
# Set the precision for bignum. |
|
268
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
269
|
|
|
|
|
|
|
# Decrement the value with the digit of interest by 1. |
|
270
|
0
|
|
|
|
|
0
|
$n -= 1; |
|
271
|
|
|
|
|
|
|
# Calculate the fraction with the hex numbers from the nth digit upwards. |
|
272
|
0
|
|
|
|
|
0
|
my $dec = (4*S(1, $n, $p) - 2*S(4, $n, $p) - |
|
273
|
|
|
|
|
|
|
S(5, $n, $p) - S(6, $n, $p)) % 1; |
|
274
|
|
|
|
|
|
|
# Get the decimal representation of the digit.. |
|
275
|
0
|
|
|
|
|
0
|
$dec = ($dec * 16) - ($dec * 16) % 1; |
|
276
|
|
|
|
|
|
|
# Get the hexadecimal representation of the digit. |
|
277
|
0
|
|
|
|
|
0
|
my $hex = $HX[$dec]; |
|
278
|
|
|
|
|
|
|
# Return the hex number. |
|
279
|
0
|
|
|
|
|
0
|
return $hex; |
|
280
|
|
|
|
|
|
|
}; |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
283
|
|
|
|
|
|
|
# Subroutine bbp_digits() # |
|
284
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
285
|
|
|
|
|
|
|
sub bbp_digits { |
|
286
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
287
|
0
|
|
|
0
|
1
|
0
|
my ($n, $digits, $p) = @_; |
|
288
|
|
|
|
|
|
|
# Set the precision for bignum. |
|
289
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
290
|
|
|
|
|
|
|
# Initialise the local variables. |
|
291
|
0
|
|
|
|
|
0
|
my $newdec = undef; |
|
292
|
0
|
|
|
|
|
0
|
my $hex_digit = ''; |
|
293
|
0
|
|
|
|
|
0
|
my $hex_digits = ''; |
|
294
|
|
|
|
|
|
|
# Decrement the value with the digit of interest by 1. |
|
295
|
0
|
|
|
|
|
0
|
$n -= 1; |
|
296
|
|
|
|
|
|
|
# Calculate the fraction with the hex numbers from the nth digit upwards. |
|
297
|
0
|
|
|
|
|
0
|
my $dec = (4*S(1, $n, $p) - 2*S(4, $n, $p) - |
|
298
|
|
|
|
|
|
|
S(5, $n, $p) - S(6, $n, $p)) % 1; |
|
299
|
|
|
|
|
|
|
# Calculate the hexadecimal number. |
|
300
|
0
|
|
|
|
|
0
|
for (my $j = 0; $j < length($dec); $j++) { |
|
301
|
0
|
|
|
|
|
0
|
$newdec = $dec * 16; |
|
302
|
0
|
|
|
|
|
0
|
$dec = $newdec - ($newdec % 1); |
|
303
|
0
|
|
|
|
|
0
|
$hex_digit = $HX[$dec]; |
|
304
|
0
|
|
|
|
|
0
|
$hex_digits = $hex_digits . $hex_digit; |
|
305
|
0
|
|
|
|
|
0
|
$dec = $newdec - $dec; |
|
306
|
|
|
|
|
|
|
}; |
|
307
|
|
|
|
|
|
|
# Return the hexadecimal number. |
|
308
|
0
|
|
|
|
|
0
|
return substr($hex_digits, 0, $digits); |
|
309
|
|
|
|
|
|
|
}; |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
312
|
|
|
|
|
|
|
# Subroutine bbp_algorith() # |
|
313
|
|
|
|
|
|
|
#------------------------------------------------------------------------------# |
|
314
|
|
|
|
|
|
|
sub bbp_algorithm { |
|
315
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
316
|
0
|
|
|
0
|
1
|
0
|
my ($places, $p) = @_; |
|
317
|
|
|
|
|
|
|
# Set the precision for bignum. |
|
318
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
319
|
|
|
|
|
|
|
# Initialise the local variable $pi_hex. |
|
320
|
0
|
|
|
|
|
0
|
my $pi_hex = "3."; |
|
321
|
|
|
|
|
|
|
# Declare the local variable $nth_digit. |
|
322
|
0
|
|
|
|
|
0
|
my $digits = undef; |
|
323
|
|
|
|
|
|
|
# Determine the hexadecimal places in a loop. |
|
324
|
0
|
|
|
|
|
0
|
for (my $i = 1; $i <= $places; $i++) { |
|
325
|
0
|
|
|
|
|
0
|
$digits = bbp_digit($i, $p); |
|
326
|
0
|
|
|
|
|
0
|
$pi_hex = $pi_hex . $digits; |
|
327
|
|
|
|
|
|
|
}; |
|
328
|
|
|
|
|
|
|
# Return Pi in hexadecimal representation. |
|
329
|
0
|
|
|
|
|
0
|
return $pi_hex; |
|
330
|
|
|
|
|
|
|
}; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
333
|
|
|
|
|
|
|
# Subroutine borwein25_algorithm() # |
|
334
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
335
|
|
|
|
|
|
|
sub borwein25_algorithm { |
|
336
|
|
|
|
|
|
|
# Assign the hash with the subroutine arguments to the local hash. |
|
337
|
0
|
|
|
0
|
1
|
0
|
my (%params) = @_; |
|
338
|
|
|
|
|
|
|
# Initialise the local variables. |
|
339
|
0
|
|
|
|
|
0
|
my $type0 = "pi"; |
|
340
|
0
|
|
|
|
|
0
|
my $type1 = "tau"; |
|
341
|
|
|
|
|
|
|
# Make a reference from the hash. |
|
342
|
0
|
|
|
|
|
0
|
my $args = \%params; |
|
343
|
|
|
|
|
|
|
# Initialise the locale variables. |
|
344
|
0
|
|
|
|
|
0
|
my $places = $args->{Places}; |
|
345
|
0
|
|
|
|
|
0
|
my $n = $args->{Terms}; |
|
346
|
0
|
|
|
|
|
0
|
my $p = $args->{Precision}; |
|
347
|
0
|
|
|
|
|
0
|
my $trim = $args->{Trim}; |
|
348
|
0
|
|
|
|
|
0
|
my $type = $args->{Type}; |
|
349
|
|
|
|
|
|
|
# Check if the the local variables are defined. |
|
350
|
0
|
0
|
|
|
|
0
|
$places = (defined $places ? $places : 0); |
|
351
|
0
|
0
|
|
|
|
0
|
$n = (defined $n ? $n : 0); |
|
352
|
0
|
0
|
|
|
|
0
|
$p = (defined $p ? $p : $places); |
|
353
|
0
|
0
|
|
|
|
0
|
$trim = (defined $trim ? $trim : $places); |
|
354
|
0
|
0
|
|
|
|
0
|
$type = (defined $type ? $type : $type0); |
|
355
|
|
|
|
|
|
|
# Set the precision. |
|
356
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
357
|
|
|
|
|
|
|
# Initialise the return variable. |
|
358
|
0
|
|
|
|
|
0
|
my $circle_constant = 0; |
|
359
|
|
|
|
|
|
|
# Set the local constants. |
|
360
|
0
|
|
|
|
|
0
|
my $sqrt61 = sqrtroot(61); |
|
361
|
0
|
|
|
|
|
0
|
my $A = (212175710912 * $sqrt61) + 1657145277365; |
|
362
|
0
|
|
|
|
|
0
|
my $B = (13773980892672 * $sqrt61) + 107578229802750; |
|
363
|
0
|
|
|
|
|
0
|
my $C = (5280 * (236674 + 30303 * $sqrt61))**3; |
|
364
|
0
|
|
|
|
|
0
|
my $factor = sqrtroot($C) / 12; |
|
365
|
|
|
|
|
|
|
# Set the initial values. |
|
366
|
0
|
|
|
|
|
0
|
my $a_k = 0; |
|
367
|
0
|
|
|
|
|
0
|
my $a_sum = 0; |
|
368
|
0
|
|
|
|
|
0
|
my $numerator = 0; |
|
369
|
0
|
|
|
|
|
0
|
my $denominator = 0; |
|
370
|
|
|
|
|
|
|
# Set the sign to 1. |
|
371
|
0
|
|
|
|
|
0
|
my $sign = 1; |
|
372
|
|
|
|
|
|
|
# Run index is of type int. |
|
373
|
0
|
|
|
|
|
0
|
for (my $k = 0; $k <= $n; $k++) { |
|
374
|
|
|
|
|
|
|
# Calculate numerator and denominator. |
|
375
|
0
|
|
|
|
|
0
|
$numerator = factorial(6*$k)*($A +$k*$B); |
|
376
|
0
|
|
|
|
|
0
|
$denominator = (factorial($k)**3)*factorial(3*$k)*($C**($k)); |
|
377
|
|
|
|
|
|
|
# Calculate the quotient. |
|
378
|
0
|
|
|
|
|
0
|
$a_k = $sign*($numerator / $denominator); |
|
379
|
|
|
|
|
|
|
# Add quotient to total sum. |
|
380
|
0
|
|
|
|
|
0
|
$a_sum += $a_k; |
|
381
|
|
|
|
|
|
|
# Change the sign. |
|
382
|
0
|
|
|
|
|
0
|
$sign *= -1; |
|
383
|
|
|
|
|
|
|
}; |
|
384
|
|
|
|
|
|
|
# Calculate the value of the circle_constant. |
|
385
|
0
|
|
|
|
|
0
|
$circle_constant = $factor / $a_sum; |
|
386
|
|
|
|
|
|
|
# Determine the value for Pi or for Tau. |
|
387
|
0
|
0
|
|
|
|
0
|
if ($type eq $type0) { |
|
|
|
0
|
|
|
|
|
|
|
388
|
0
|
|
|
|
|
0
|
$circle_constant = 1.0 * $circle_constant; |
|
389
|
|
|
|
|
|
|
} elsif ($type eq $type1) { |
|
390
|
0
|
|
|
|
|
0
|
$circle_constant = 2.0 * $circle_constant; |
|
391
|
|
|
|
|
|
|
}; |
|
392
|
|
|
|
|
|
|
# Cut the decimal number to the needed places. |
|
393
|
0
|
|
|
|
|
0
|
$circle_constant = truncate_places($circle_constant, $trim); |
|
394
|
|
|
|
|
|
|
# Return the value of the circle constant. |
|
395
|
0
|
|
|
|
|
0
|
return "$circle_constant"; |
|
396
|
|
|
|
|
|
|
}; |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
399
|
|
|
|
|
|
|
# Subroutine chudnovsky_algorithm() # |
|
400
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
401
|
|
|
|
|
|
|
sub chudnovsky_algorithm { |
|
402
|
|
|
|
|
|
|
# Assign the hash with the subroutine arguments to the local hash. |
|
403
|
0
|
|
|
0
|
1
|
0
|
my (%params) = @_; |
|
404
|
|
|
|
|
|
|
# Initialise the local variables. |
|
405
|
0
|
|
|
|
|
0
|
my $type0 = "pi"; |
|
406
|
0
|
|
|
|
|
0
|
my $type1 = "tau"; |
|
407
|
|
|
|
|
|
|
# Make a reference from the hash. |
|
408
|
0
|
|
|
|
|
0
|
my $args = \%params; |
|
409
|
|
|
|
|
|
|
# Initialise the locale variables. |
|
410
|
0
|
|
|
|
|
0
|
my $places = $args->{Places}; |
|
411
|
0
|
|
|
|
|
0
|
my $n = $args->{Terms}; |
|
412
|
0
|
|
|
|
|
0
|
my $p = $args->{Precision}; |
|
413
|
0
|
|
|
|
|
0
|
my $trim = $args->{Trim}; |
|
414
|
0
|
|
|
|
|
0
|
my $type = $args->{Type}; |
|
415
|
|
|
|
|
|
|
# Check if the the local variables are defined. |
|
416
|
0
|
0
|
|
|
|
0
|
$places = (defined $places ? $places : 0); |
|
417
|
0
|
0
|
|
|
|
0
|
$n = (defined $n ? $n : 0); |
|
418
|
0
|
0
|
|
|
|
0
|
$p = (defined $p ? $p : $places); |
|
419
|
0
|
0
|
|
|
|
0
|
$trim = (defined $trim ? $trim : $places); |
|
420
|
0
|
0
|
|
|
|
0
|
$type = (defined $type ? $type : $type0); |
|
421
|
|
|
|
|
|
|
# Set the precision. |
|
422
|
0
|
|
|
|
|
0
|
bignum -> precision(-$p); |
|
423
|
|
|
|
|
|
|
# Initialise the return variable. |
|
424
|
0
|
|
|
|
|
0
|
my $circle_constant = 0; |
|
425
|
|
|
|
|
|
|
# Set the local integer constants. |
|
426
|
0
|
|
|
|
|
0
|
my $c0 = 545140134; |
|
427
|
0
|
|
|
|
|
0
|
my $c1 = 13591409; |
|
428
|
0
|
|
|
|
|
0
|
my $c2 = 640320; |
|
429
|
0
|
|
|
|
|
0
|
my $c3 = 4270934400; |
|
430
|
0
|
|
|
|
|
0
|
my $c4 = 10005; |
|
431
|
|
|
|
|
|
|
# Set the initial values. |
|
432
|
0
|
|
|
|
|
0
|
my $a_k = 0; |
|
433
|
0
|
|
|
|
|
0
|
my $a_sum = 0; |
|
434
|
0
|
|
|
|
|
0
|
my $numerator = 0; |
|
435
|
0
|
|
|
|
|
0
|
my $denominator = 0; |
|
436
|
|
|
|
|
|
|
# Set the sign to 1. |
|
437
|
0
|
|
|
|
|
0
|
my $sign = 1; |
|
438
|
|
|
|
|
|
|
# Run index is of type int. |
|
439
|
0
|
|
|
|
|
0
|
for (my $k = 0; $k <= $n; $k++) { |
|
440
|
|
|
|
|
|
|
# Calculate numerator and denominator. |
|
441
|
0
|
|
|
|
|
0
|
$numerator = factorial(6*$k)*($c0*$k+$c1); |
|
442
|
0
|
|
|
|
|
0
|
$denominator = factorial(3*$k)*(factorial($k)**3)*($c2**(3*$k)); |
|
443
|
|
|
|
|
|
|
# Calculate the quotient. |
|
444
|
0
|
|
|
|
|
0
|
$a_k = $sign*($numerator / $denominator); |
|
445
|
|
|
|
|
|
|
# Add quotient to total sum. |
|
446
|
0
|
|
|
|
|
0
|
$a_sum += $a_k; |
|
447
|
|
|
|
|
|
|
# Change the sign. |
|
448
|
0
|
|
|
|
|
0
|
$sign *= -1; |
|
449
|
|
|
|
|
|
|
}; |
|
450
|
|
|
|
|
|
|
# Calculate the value of the circle_constant. |
|
451
|
0
|
|
|
|
|
0
|
$circle_constant = $c3 / (sqrt($c4)*$a_sum); |
|
452
|
|
|
|
|
|
|
# Determine Pi or Tau. |
|
453
|
0
|
0
|
|
|
|
0
|
if ($type eq $type0) { |
|
|
|
0
|
|
|
|
|
|
|
454
|
0
|
|
|
|
|
0
|
$circle_constant = 1.0 * $circle_constant; |
|
455
|
|
|
|
|
|
|
} elsif ($type eq $type1) { |
|
456
|
0
|
|
|
|
|
0
|
$circle_constant = 2.0 * $circle_constant; |
|
457
|
|
|
|
|
|
|
}; |
|
458
|
|
|
|
|
|
|
# Cut the decimal number to the needed places. |
|
459
|
0
|
|
|
|
|
0
|
$circle_constant = truncate_places($circle_constant, $trim); |
|
460
|
|
|
|
|
|
|
# Return the value of the circle constant. |
|
461
|
0
|
|
|
|
|
0
|
return "$circle_constant"; |
|
462
|
|
|
|
|
|
|
}; |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
465
|
|
|
|
|
|
|
# Subroutine chudnovsky_caller() # |
|
466
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
467
|
|
|
|
|
|
|
sub chudnovsky_caller { |
|
468
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
469
|
0
|
|
|
0
|
0
|
0
|
my $places = $_[0]; |
|
470
|
0
|
|
|
|
|
0
|
my $method = $_[1]; |
|
471
|
|
|
|
|
|
|
# Check if the places are valid. If not exit the script. |
|
472
|
0
|
|
|
|
|
0
|
check_places($places); |
|
473
|
|
|
|
|
|
|
# Calculate the required number of terms. |
|
474
|
0
|
|
|
|
|
0
|
my $terms = estimate_terms($places, 14); |
|
475
|
|
|
|
|
|
|
# Set the precision for the calculation. |
|
476
|
0
|
|
|
|
|
0
|
my $precision = $places + 15; |
|
477
|
|
|
|
|
|
|
# Get the value of the circle constant from the calculation. |
|
478
|
0
|
|
|
|
|
0
|
my $circle_constant = chudnovsky_algorithm( |
|
479
|
|
|
|
|
|
|
Places => $places, |
|
480
|
|
|
|
|
|
|
Terms => $terms, |
|
481
|
|
|
|
|
|
|
Precision => $precision, |
|
482
|
|
|
|
|
|
|
Trim => $places, |
|
483
|
|
|
|
|
|
|
Type => $method |
|
484
|
|
|
|
|
|
|
); |
|
485
|
|
|
|
|
|
|
# Return the value of the circle constant Pi or Tau. |
|
486
|
0
|
|
|
|
|
0
|
return "$circle_constant"; |
|
487
|
|
|
|
|
|
|
}; |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
490
|
|
|
|
|
|
|
# Subroutine borwein1989_caller() # |
|
491
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------- # |
|
492
|
|
|
|
|
|
|
sub borwein25_caller { |
|
493
|
|
|
|
|
|
|
# Assign the subroutine arguments to the local variables. |
|
494
|
0
|
|
|
0
|
0
|
0
|
my $places = $_[0]; |
|
495
|
0
|
|
|
|
|
0
|
my $method = $_[1]; |
|
496
|
|
|
|
|
|
|
# Check if the places are valid. If not exit the script. |
|
497
|
0
|
|
|
|
|
0
|
check_places($places); |
|
498
|
|
|
|
|
|
|
# Calculate the required number of terms. |
|
499
|
0
|
|
|
|
|
0
|
my $terms = estimate_terms($places, 25); |
|
500
|
|
|
|
|
|
|
# Set the precision for the calculation. |
|
501
|
0
|
|
|
|
|
0
|
my $precision = $places + 26; |
|
502
|
|
|
|
|
|
|
# Get the value of the circle constant from the calculation. |
|
503
|
0
|
|
|
|
|
0
|
my $circle_constant = borwein25_algorithm( |
|
504
|
|
|
|
|
|
|
Places => $places, |
|
505
|
|
|
|
|
|
|
Terms => $terms, |
|
506
|
|
|
|
|
|
|
Precision => $precision, |
|
507
|
|
|
|
|
|
|
Trim => $places, |
|
508
|
|
|
|
|
|
|
Type => $method |
|
509
|
|
|
|
|
|
|
); |
|
510
|
|
|
|
|
|
|
# Return the value of the circle constant Pi or Tau. |
|
511
|
0
|
|
|
|
|
0
|
return "$circle_constant"; |
|
512
|
|
|
|
|
|
|
}; |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # |
|
515
|
|
|
|
|
|
|
# Call the caller subroutines # |
|
516
|
|
|
|
|
|
|
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # |
|
517
|
0
|
|
|
0
|
1
|
0
|
sub pi_chudnovsky { return chudnovsky_caller($_[0], "pi") }; |
|
518
|
0
|
|
|
0
|
1
|
0
|
sub tau_chudnovsky { return chudnovsky_caller($_[0], "tau") }; |
|
519
|
0
|
|
|
0
|
1
|
0
|
sub pi_borwein25 { return borwein25_caller($_[0], "pi") }; |
|
520
|
0
|
|
|
0
|
1
|
0
|
sub tau_borwein25 { return borwein25_caller($_[0], "tau") }; |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# ============================================================================ # |
|
523
|
|
|
|
|
|
|
# Subroutine read_pi() # |
|
524
|
|
|
|
|
|
|
# ============================================================================ # |
|
525
|
|
|
|
|
|
|
sub read_pi { |
|
526
|
|
|
|
|
|
|
# Assign the subroutine argument to the local variable. |
|
527
|
2
|
|
|
2
|
0
|
5
|
my $type = $_[0]; |
|
528
|
|
|
|
|
|
|
# Initialise the local variables. |
|
529
|
2
|
|
|
|
|
4
|
my $line = ""; |
|
530
|
2
|
|
|
|
|
5
|
my $pi = ""; |
|
531
|
|
|
|
|
|
|
# Assemble the begin and end pattern. |
|
532
|
2
|
|
|
|
|
4
|
my $pattern0 = "# Begin Pi ${type}"; |
|
533
|
2
|
|
|
|
|
4
|
my $pattern1 = "# End Pi ${type}"; |
|
534
|
|
|
|
|
|
|
# Read the data from the DATA section. |
|
535
|
2
|
|
|
|
|
21
|
while () { |
|
536
|
|
|
|
|
|
|
# Read data only between the two given pattern. |
|
537
|
1058
|
100
|
|
|
|
2782
|
if (/$pattern0/../$pattern1/) { |
|
538
|
46
|
100
|
100
|
|
|
232
|
next if /$pattern0/ || /$pattern1/; |
|
539
|
42
|
|
|
|
|
71
|
$line = $_; |
|
540
|
42
|
|
|
|
|
331
|
$line =~ s/^\s+|\s+$//g; |
|
541
|
42
|
|
|
|
|
128
|
$pi = $pi . $line; |
|
542
|
|
|
|
|
|
|
}; |
|
543
|
|
|
|
|
|
|
}; |
|
544
|
|
|
|
|
|
|
# Return Pi. |
|
545
|
2
|
|
|
|
|
16
|
return $pi; |
|
546
|
|
|
|
|
|
|
}; |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# ============================================================================ # |
|
549
|
|
|
|
|
|
|
# Subroutine read_data() # |
|
550
|
|
|
|
|
|
|
# # |
|
551
|
|
|
|
|
|
|
# Description: # |
|
552
|
|
|
|
|
|
|
# The subroutine reads Pi in decimal and hexadecimal representation from the # |
|
553
|
|
|
|
|
|
|
# DATA section. # |
|
554
|
|
|
|
|
|
|
# ============================================================================ # |
|
555
|
|
|
|
|
|
|
sub read_data { |
|
556
|
|
|
|
|
|
|
# Save the position of DATA. |
|
557
|
1
|
|
|
1
|
0
|
3
|
my $data_start = tell DATA; |
|
558
|
|
|
|
|
|
|
# Read decimal Pi with 1000 places. |
|
559
|
1
|
|
|
|
|
2
|
my $pi_dec = uc(read_pi("dec")); |
|
560
|
|
|
|
|
|
|
# Reposition the filehandle right past to __DATA__ |
|
561
|
1
|
|
|
|
|
8
|
seek DATA, $data_start, 0; |
|
562
|
|
|
|
|
|
|
# Read hexadecimal Pi with 1000 places. |
|
563
|
1
|
|
|
|
|
51
|
my $pi_hex = uc(read_pi("hex")); |
|
564
|
|
|
|
|
|
|
# Return PI. |
|
565
|
1
|
|
|
|
|
5
|
return $pi_dec, $pi_hex; |
|
566
|
|
|
|
|
|
|
}; |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
# Read data from DATA. |
|
569
|
|
|
|
|
|
|
($PI_DEC, $PI_HEX) = read_data(); |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
1; |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
__DATA__ |