foxpi 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cli.py +115 -0
- core/__init__.py +0 -0
- core/algorithms.py +235 -0
- core/visualize.py +25 -0
- foxpi-0.1.0.dist-info/METADATA +336 -0
- foxpi-0.1.0.dist-info/RECORD +10 -0
- foxpi-0.1.0.dist-info/WHEEL +5 -0
- foxpi-0.1.0.dist-info/entry_points.txt +2 -0
- foxpi-0.1.0.dist-info/licenses/LICENSE +21 -0
- foxpi-0.1.0.dist-info/top_level.txt +2 -0
cli.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# cli.py
|
|
2
|
+
#!/usr/bin/env python3
|
|
3
|
+
"""
|
|
4
|
+
FoxPi â High-precision Ī & mathematical explorer
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
import argparse
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import List
|
|
12
|
+
|
|
13
|
+
from core.algorithms import (
|
|
14
|
+
get_ramanujan_pi_terms,
|
|
15
|
+
get_chudnovsky_pi_terms,
|
|
16
|
+
compute_chudnovsky_pi,
|
|
17
|
+
compute_machin_pi,
|
|
18
|
+
generate_bbp_spigot,
|
|
19
|
+
isqrt,
|
|
20
|
+
)
|
|
21
|
+
from core.visualize import render_convergence_table, render_comparison
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
parser = argparse.ArgumentParser(prog="foxpi", description="High-precision Ī explorer đĻ")
|
|
25
|
+
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
26
|
+
|
|
27
|
+
# digits command
|
|
28
|
+
d = sub.add_parser("digits", help="Compute N digits of Ī")
|
|
29
|
+
d.add_argument("count", type=int, help="Number of decimal digits")
|
|
30
|
+
d.add_argument("--method", choices=["ramanujan", "chudnovsky", "machin"], default="chudnovsky")
|
|
31
|
+
|
|
32
|
+
# explore command
|
|
33
|
+
e = sub.add_parser("explore", help="Live convergence visualisation")
|
|
34
|
+
e.add_argument("--method", choices=["ramanujan", "chudnovsky"], default="ramanujan")
|
|
35
|
+
e.add_argument("--terms", type=int, default=30)
|
|
36
|
+
|
|
37
|
+
# compare command
|
|
38
|
+
sub.add_parser("compare", help="Benchmark multiple algorithms")
|
|
39
|
+
|
|
40
|
+
# bbp spigot
|
|
41
|
+
b = sub.add_parser("bbp", help="Extract hexadecimal digits using BBP formula")
|
|
42
|
+
b.add_argument("position", type=int, default=1, help="Starting digit position (1 = first after decimal)")
|
|
43
|
+
|
|
44
|
+
args = parser.parse_args()
|
|
45
|
+
|
|
46
|
+
if args.cmd == "digits" and args.count < 0:
|
|
47
|
+
print(f"Error: digit count must be >= 0 (got {args.count}).", file=sys.stderr)
|
|
48
|
+
sys.exit(1)
|
|
49
|
+
if args.cmd == "bbp" and args.position < 1:
|
|
50
|
+
print(f"Error: position must be >= 1 (got {args.position}); 1 is the first hex digit after the point.", file=sys.stderr)
|
|
51
|
+
sys.exit(1)
|
|
52
|
+
if args.cmd == "explore" and args.terms < 1:
|
|
53
|
+
print(f"Error: --terms must be >= 1 (got {args.terms}).", file=sys.stderr)
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
|
|
56
|
+
if args.cmd == "digits":
|
|
57
|
+
# Python 3.11+ caps int->str conversion at 4300 digits by default;
|
|
58
|
+
# raise it to fit the requested precision (plus a small margin).
|
|
59
|
+
sys.set_int_max_str_digits(max(4300, args.count + 20))
|
|
60
|
+
|
|
61
|
+
start = time.perf_counter()
|
|
62
|
+
if args.method == "chudnovsky":
|
|
63
|
+
pi_int = compute_chudnovsky_pi(args.count)
|
|
64
|
+
elif args.method == "ramanujan":
|
|
65
|
+
# Take last term
|
|
66
|
+
last = None
|
|
67
|
+
for term in get_ramanujan_pi_terms(args.count):
|
|
68
|
+
last = term
|
|
69
|
+
pi_int = last[1]
|
|
70
|
+
else: # machin
|
|
71
|
+
pi_int = compute_machin_pi(args.count)
|
|
72
|
+
|
|
73
|
+
elapsed = time.perf_counter() - start
|
|
74
|
+
pi_str = str(pi_int)
|
|
75
|
+
print(f"\nĪ ({args.count} digits) using {args.method.capitalize()}:")
|
|
76
|
+
print(f"{pi_str[0]}.{pi_str[1:]}")
|
|
77
|
+
print(f"Time: {elapsed:.4f}s")
|
|
78
|
+
|
|
79
|
+
elif args.cmd == "explore":
|
|
80
|
+
print(f"Exploring convergence with {args.method}...\n")
|
|
81
|
+
history = []
|
|
82
|
+
gen = get_ramanujan_pi_terms(100) if args.method == "ramanujan" else get_chudnovsky_pi_terms(100)
|
|
83
|
+
|
|
84
|
+
for i in range(args.terms):
|
|
85
|
+
try:
|
|
86
|
+
k, pi_est, delta = next(gen)
|
|
87
|
+
history.append({'step': k, 'pi': pi_est, 'delta': delta})
|
|
88
|
+
pi_s = str(pi_est)
|
|
89
|
+
print(f"Term {k:3d} â Ī â {pi_s[0]}.{pi_s[1:15]}...", end="\r")
|
|
90
|
+
except StopIteration:
|
|
91
|
+
print(f"\n(series exhausted at {len(history)} term(s) for this precision â "
|
|
92
|
+
f"further terms would add no more distinguishable digits)")
|
|
93
|
+
break
|
|
94
|
+
print("\n")
|
|
95
|
+
render_convergence_table(history)
|
|
96
|
+
|
|
97
|
+
elif args.cmd == "compare":
|
|
98
|
+
print("Benchmarking algorithms...\n")
|
|
99
|
+
results = []
|
|
100
|
+
for method, func in [("Chudnovsky", lambda: compute_chudnovsky_pi(1000)),
|
|
101
|
+
("Machin", lambda: compute_machin_pi(1000))]:
|
|
102
|
+
t0 = time.perf_counter()
|
|
103
|
+
func()
|
|
104
|
+
t1 = time.perf_counter()
|
|
105
|
+
results.append({'algo': method, 'precision': 1000, 'time': t1-t0})
|
|
106
|
+
render_comparison(results)
|
|
107
|
+
|
|
108
|
+
elif args.cmd == "bbp":
|
|
109
|
+
print(f"Extracting 16 hex digits of Ī starting at position {args.position}:")
|
|
110
|
+
digits = list(generate_bbp_spigot(args.position))
|
|
111
|
+
print("".join(digits))
|
|
112
|
+
print("(BBP Spigot â hexadecimal)")
|
|
113
|
+
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
main()
|
core/__init__.py
ADDED
|
File without changes
|
core/algorithms.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FoxPi Core Algorithms â High-precision Ī computation.
|
|
3
|
+
Implements exact integer-scaled implementations of historical and elite formulas.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Generator, Tuple
|
|
7
|
+
|
|
8
|
+
def get_ramanujan_pi_terms(precision: int) -> Generator[Tuple[int, int, int], None, None]:
|
|
9
|
+
"""
|
|
10
|
+
Ramanujan's legendary 1914 hypergeometric series for 1/Ī.
|
|
11
|
+
Formula:
|
|
12
|
+
1/Ī = (2â2 / 9801) * ÎŖ [ (4k)! * (1103 + 26390k) / ((k!)^4 * 396^(4k)) ]
|
|
13
|
+
|
|
14
|
+
Yields:
|
|
15
|
+
Tuple[int, int, int]: (term_index, current_pi_estimate, current_term_value)
|
|
16
|
+
"""
|
|
17
|
+
# Guard digits to mitigate rounding accumulation
|
|
18
|
+
guard = 20
|
|
19
|
+
scale = 10 ** (precision + guard)
|
|
20
|
+
|
|
21
|
+
# Pre-calculate integer-scaled square root of 2: isqrt(2 * scale^2)
|
|
22
|
+
# 2â2 * scale = isqrt(8 * scale^2)
|
|
23
|
+
two_sqrt_two = isqrt(8 * (scale ** 2))
|
|
24
|
+
|
|
25
|
+
total_sum = 0
|
|
26
|
+
|
|
27
|
+
# Iterative hypergeometric factors
|
|
28
|
+
# Holds: (4k)! / ((k!)^4 * 396^(4k))
|
|
29
|
+
num_ratio = 1
|
|
30
|
+
den_ratio = 1
|
|
31
|
+
|
|
32
|
+
k = 0
|
|
33
|
+
while True:
|
|
34
|
+
# Linear term: (1103 + 26390k)
|
|
35
|
+
linear = 1103 + 26390 * k
|
|
36
|
+
|
|
37
|
+
# Current hypergeometric term
|
|
38
|
+
term = (scale * num_ratio * linear) // den_ratio
|
|
39
|
+
|
|
40
|
+
if term == 0:
|
|
41
|
+
break
|
|
42
|
+
|
|
43
|
+
total_sum += term
|
|
44
|
+
|
|
45
|
+
# 1/pi = (2sqrt2/9801) * Sigma => pi = 9801*scale^3 / (two_sqrt_two * total_sum)
|
|
46
|
+
# (two_sqrt_two and total_sum each already carry one factor of scale)
|
|
47
|
+
current_pi = (9801 * scale * scale * scale) // (two_sqrt_two * total_sum)
|
|
48
|
+
final_pi = current_pi // (10 ** guard)
|
|
49
|
+
|
|
50
|
+
yield k, final_pi, term
|
|
51
|
+
|
|
52
|
+
# Hypergeometric updates for k -> k + 1 step
|
|
53
|
+
# Multiplier derivation: (4k+1)(4k+2)(4k+3)(4k+4) / ((k+1)^4 * 396^4)
|
|
54
|
+
num_ratio *= (4 * k + 1) * (4 * k + 2) * (4 * k + 3) * (4 * k + 4)
|
|
55
|
+
den_ratio *= ((k + 1) ** 4) * 24591257856 # 396^4 = 24591257856
|
|
56
|
+
k += 1
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_chudnovsky_pi_terms(precision: int = 100) -> Generator[Tuple[int, int, int], None, None]:
|
|
60
|
+
"""
|
|
61
|
+
Chudnovsky series computed one term at a time for convergence
|
|
62
|
+
visualization (the `explore` command). Recomputes binary splitting
|
|
63
|
+
from scratch each step â O(k^2) overall, which is fine for the
|
|
64
|
+
handful of terms `explore` requests. Use compute_chudnovsky_pi for
|
|
65
|
+
actual high-precision computation.
|
|
66
|
+
|
|
67
|
+
Yields:
|
|
68
|
+
Tuple[int, int, int]: (term_index, current_pi_estimate, term_magnitude)
|
|
69
|
+
"""
|
|
70
|
+
guard = 20
|
|
71
|
+
scale = 10 ** (precision + guard)
|
|
72
|
+
C = 640320
|
|
73
|
+
C3_OVER_24 = (C ** 3) // 24
|
|
74
|
+
|
|
75
|
+
def bs(a: int, b: int) -> Tuple[int, int, int]:
|
|
76
|
+
if b - a == 1:
|
|
77
|
+
if a == 0:
|
|
78
|
+
P = 1
|
|
79
|
+
Q = 1
|
|
80
|
+
else:
|
|
81
|
+
P = (6 * a - 5) * (2 * a - 1) * (6 * a - 1)
|
|
82
|
+
Q = (a ** 3) * C3_OVER_24
|
|
83
|
+
T = P * (13591409 + 545140134 * a)
|
|
84
|
+
if a % 2 == 1:
|
|
85
|
+
T = -T
|
|
86
|
+
return P, Q, T
|
|
87
|
+
else:
|
|
88
|
+
m = (a + b) // 2
|
|
89
|
+
P1, Q1, T1 = bs(a, m)
|
|
90
|
+
P2, Q2, T2 = bs(m, b)
|
|
91
|
+
return P1 * P2, Q1 * Q2, Q2 * T1 + P1 * T2
|
|
92
|
+
|
|
93
|
+
sqrt_10005 = isqrt(10005 * (scale ** 2))
|
|
94
|
+
max_terms = (precision // 14) + 2 # Chudnovsky gives ~14 digits/term
|
|
95
|
+
|
|
96
|
+
k = 1
|
|
97
|
+
while k <= max_terms:
|
|
98
|
+
_, _, single_T = bs(k - 1, k)
|
|
99
|
+
term_magnitude = abs(single_T) if single_T != 0 else 1
|
|
100
|
+
|
|
101
|
+
_, Q, T = bs(0, k)
|
|
102
|
+
numerator = 426880 * sqrt_10005 * Q
|
|
103
|
+
pi_val = numerator // T
|
|
104
|
+
final_pi = pi_val // (10 ** guard)
|
|
105
|
+
|
|
106
|
+
yield k - 1, final_pi, term_magnitude
|
|
107
|
+
k += 1
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def compute_chudnovsky_pi(precision: int) -> int:
|
|
111
|
+
"""
|
|
112
|
+
The Chudnovsky algorithm utilizing Binary Splitting execution logic.
|
|
113
|
+
Provides ~14 digits per iteration. Used by world-record engines.
|
|
114
|
+
"""
|
|
115
|
+
guard = 20
|
|
116
|
+
scale = 10 ** (precision + guard)
|
|
117
|
+
|
|
118
|
+
# Constants
|
|
119
|
+
C = 640320
|
|
120
|
+
C3_OVER_24 = (C ** 3) // 24
|
|
121
|
+
|
|
122
|
+
# Binary splitting helper to divide-and-conquer huge integer expansions
|
|
123
|
+
def bs(a: int, b: int) -> Tuple[int, int, int]:
|
|
124
|
+
if b - a == 1:
|
|
125
|
+
if a == 0:
|
|
126
|
+
P = 1
|
|
127
|
+
Q = 1
|
|
128
|
+
else:
|
|
129
|
+
P = (6 * a - 5) * (2 * a - 1) * (6 * a - 1)
|
|
130
|
+
Q = (a ** 3) * C3_OVER_24
|
|
131
|
+
T = P * (13591409 + 545140134 * a)
|
|
132
|
+
if a % 2 == 1:
|
|
133
|
+
T = -T
|
|
134
|
+
return P, Q, T
|
|
135
|
+
else:
|
|
136
|
+
m = (a + b) // 2
|
|
137
|
+
P1, Q1, T1 = bs(a, m)
|
|
138
|
+
P2, Q2, T2 = bs(m, b)
|
|
139
|
+
P = P1 * P2
|
|
140
|
+
Q = Q1 * Q2
|
|
141
|
+
T = Q2 * T1 + P1 * T2
|
|
142
|
+
return P, Q, T
|
|
143
|
+
|
|
144
|
+
# Estimate required terms: ~14 digits per term
|
|
145
|
+
terms = (precision // 14) + 1
|
|
146
|
+
P, Q, T = bs(0, terms)
|
|
147
|
+
|
|
148
|
+
# 426880 * â10005
|
|
149
|
+
sqrt_10005 = isqrt(10005 * (scale ** 2))
|
|
150
|
+
numerator = 426880 * sqrt_10005 * Q
|
|
151
|
+
|
|
152
|
+
pi = numerator // T
|
|
153
|
+
return pi // (10 ** guard)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def compute_machin_pi(precision: int) -> int:
|
|
157
|
+
"""Classical Machin formula with scaled integer arithmetic."""
|
|
158
|
+
guard = 20
|
|
159
|
+
scale = 10 ** (precision + guard)
|
|
160
|
+
|
|
161
|
+
def arccot(x: int, base_scale: int) -> int:
|
|
162
|
+
total = base_scale // x
|
|
163
|
+
term = total
|
|
164
|
+
n = 3
|
|
165
|
+
x2 = x * x
|
|
166
|
+
sign = -1
|
|
167
|
+
while True:
|
|
168
|
+
term = term // x2
|
|
169
|
+
if term == 0:
|
|
170
|
+
break
|
|
171
|
+
total += sign * (term // n)
|
|
172
|
+
sign = -sign
|
|
173
|
+
n += 2
|
|
174
|
+
return total
|
|
175
|
+
|
|
176
|
+
pi_approx = 4 * (4 * arccot(5, scale) - arccot(239, scale))
|
|
177
|
+
return pi_approx // (10 ** guard)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def generate_bbp_spigot(digit_position: int) -> Generator[str, None, None]:
|
|
181
|
+
"""
|
|
182
|
+
Bailey-Borwein-Plouffe (BBP) Spigot implementation.
|
|
183
|
+
Extracts hexadecimal digits of Ī starting directly at 'digit_position'.
|
|
184
|
+
Does not require calculating any preceding digits.
|
|
185
|
+
"""
|
|
186
|
+
from decimal import Decimal, getcontext
|
|
187
|
+
|
|
188
|
+
# Native float (53-bit mantissa) loses precision after ~13-14 hex digits
|
|
189
|
+
# of summation at deeper positions, corrupting trailing output digits.
|
|
190
|
+
# Use Decimal with enough guard digits to keep all 16 requested digits exact.
|
|
191
|
+
getcontext().prec = max(30, len(str(digit_position)) + 30)
|
|
192
|
+
|
|
193
|
+
def series_sum(n: int, j: int) -> Decimal:
|
|
194
|
+
s = Decimal(0)
|
|
195
|
+
for k in range(n + 1):
|
|
196
|
+
r = 8 * k + j
|
|
197
|
+
s = (s + Decimal(pow(16, n - k, r)) / r) % 1
|
|
198
|
+
k = n + 1
|
|
199
|
+
while True:
|
|
200
|
+
term = Decimal(16) ** (n - k) / (8 * k + j)
|
|
201
|
+
if term < Decimal("1e-30"):
|
|
202
|
+
break
|
|
203
|
+
s += term
|
|
204
|
+
k += 1
|
|
205
|
+
return s
|
|
206
|
+
|
|
207
|
+
n = digit_position - 1
|
|
208
|
+
s1 = series_sum(n, 1)
|
|
209
|
+
s2 = series_sum(n, 4)
|
|
210
|
+
s3 = series_sum(n, 5)
|
|
211
|
+
s4 = series_sum(n, 6)
|
|
212
|
+
|
|
213
|
+
pid = (4 * s1 - 2 * s2 - s3 - s4) % 1
|
|
214
|
+
if pid < 0:
|
|
215
|
+
pid += 1
|
|
216
|
+
|
|
217
|
+
for _ in range(16):
|
|
218
|
+
pid *= 16
|
|
219
|
+
digit = int(pid)
|
|
220
|
+
yield hex(digit)[2:].upper()
|
|
221
|
+
pid -= digit
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def isqrt(n: int) -> int:
|
|
225
|
+
"""High-performance standard Newton-Raphson integer square root engine."""
|
|
226
|
+
if n < 0:
|
|
227
|
+
raise ValueError("Square root of a negative integer is undefined.")
|
|
228
|
+
if n == 0:
|
|
229
|
+
return 0
|
|
230
|
+
x = 2 ** ((n.bit_length() + 1) // 2)
|
|
231
|
+
while True:
|
|
232
|
+
y = (x + n // x) // 2
|
|
233
|
+
if y >= x:
|
|
234
|
+
return x
|
|
235
|
+
x = y
|
core/visualize.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FoxPi Visualization Module
|
|
3
|
+
Handles high-fidelity CLI output formats.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import time
|
|
7
|
+
from typing import List, Dict, Any
|
|
8
|
+
|
|
9
|
+
def render_convergence_table(history: List[Dict[str, Any]]) -> None:
|
|
10
|
+
"""Prints a beautiful live convergence log to stdout."""
|
|
11
|
+
print(f"\n{'Iteration':<12} | {'Term Delta (Log10)':<20} | {'Pi Preview (First 15 Digits)':<20}")
|
|
12
|
+
print("-" * 60)
|
|
13
|
+
for entry in history:
|
|
14
|
+
idx = entry['step']
|
|
15
|
+
delta_len = len(str(entry['delta']))
|
|
16
|
+
pi_str = str(entry['pi'])
|
|
17
|
+
pi_preview = f"{pi_str[0]}.{pi_str[1:15]}..." if len(pi_str) > 15 else pi_str
|
|
18
|
+
print(f"{idx:<12} | -10^{delta_len:<16} | {pi_preview:<20}")
|
|
19
|
+
|
|
20
|
+
def render_comparison(results: List[Dict[str, Any]]) -> None:
|
|
21
|
+
"""Displays benchmark metrics comparing different numerical formulas."""
|
|
22
|
+
print(f"\n{'Algorithm':<15} | {'Precision (Digits)':<20} | {'Time Elapsed (s)':<18}")
|
|
23
|
+
print("-" * 60)
|
|
24
|
+
for res in results:
|
|
25
|
+
print(f"{res['algo']:<15} | {res['precision']:<20} | {res['time']:.6f}s")
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: foxpi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-precision terminal Ī explorer â Chudnovsky, Ramanujan, Machin, and BBP spigot algorithms.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Source, https://github.com/foxhackerzdevs/foxpi
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# đĻ FoxPi
|
|
13
|
+
|
|
14
|
+
**High-precision Ī explorer and mathematical visualization toolkit for the command line.**
|
|
15
|
+
|
|
16
|
+
FoxPi is a Python-based CLI application for computing and exploring the digits of Ī using several famous algorithms. It provides fast high-precision computation, convergence visualization, benchmarking tools, and hexadecimal digit extraction via the BaileyâBorweinâPlouffe (BBP) formula.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Table of Contents
|
|
21
|
+
|
|
22
|
+
* [Features](#features)
|
|
23
|
+
* [Project Structure](#project-structure)
|
|
24
|
+
* [Installation](#installation)
|
|
25
|
+
* [Usage](#usage)
|
|
26
|
+
|
|
27
|
+
* Compute Digits
|
|
28
|
+
* Explore Convergence
|
|
29
|
+
* Compare Algorithms
|
|
30
|
+
* BBP Hexadecimal Digits
|
|
31
|
+
* [Algorithms Implemented](#algorithms-implemented)
|
|
32
|
+
* [Examples](#examples)
|
|
33
|
+
* [Dependencies](#dependencies)
|
|
34
|
+
* [Configuration](#configuration)
|
|
35
|
+
* [Troubleshooting](#troubleshooting)
|
|
36
|
+
* [Contributing](#contributing)
|
|
37
|
+
* [License](#license)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Features
|
|
42
|
+
|
|
43
|
+
* Compute Ī to an arbitrary number of decimal digits.
|
|
44
|
+
* Multiple computation algorithms:
|
|
45
|
+
|
|
46
|
+
* Chudnovsky Algorithm
|
|
47
|
+
* Ramanujan Series
|
|
48
|
+
* Machin Formula
|
|
49
|
+
* Interactive convergence exploration.
|
|
50
|
+
* Benchmark algorithm performance.
|
|
51
|
+
* Extract hexadecimal digits directly using the BBP formula.
|
|
52
|
+
* Pure Python implementation using integer arithmetic for high precision.
|
|
53
|
+
* No third-party dependencies.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
# Project Structure
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
foxpi/
|
|
61
|
+
â
|
|
62
|
+
âââ cli.py # Command-line interface
|
|
63
|
+
âââ core/
|
|
64
|
+
âââ algorithms.py # Mathematical algorithms
|
|
65
|
+
âââ visualize.py # CLI visualization utilities
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# Installation
|
|
71
|
+
|
|
72
|
+
Clone the repository:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone <repository-url>
|
|
76
|
+
cd foxpi
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Python 3.9+ is recommended.
|
|
80
|
+
|
|
81
|
+
No external packages are required.
|
|
82
|
+
|
|
83
|
+
Run with a subcommand:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
python cli.py digits 100
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`python cli.py` alone (with no subcommand) prints usage and exits with an error â a subcommand (`digits`, `explore`, `compare`, or `bbp`) is required.
|
|
90
|
+
|
|
91
|
+
or
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python -m cli
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
# Usage
|
|
100
|
+
|
|
101
|
+
## Compute Decimal Digits
|
|
102
|
+
|
|
103
|
+
Compute Ī using one of the supported algorithms.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
python cli.py digits 1000
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Specify the algorithm:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python cli.py digits 5000 --method chudnovsky
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
python cli.py digits 1000 --method ramanujan
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python cli.py digits 1000 --method machin
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Explore Convergence
|
|
126
|
+
|
|
127
|
+
Watch the approximation converge term by term.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python cli.py explore
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Choose an algorithm:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
python cli.py explore --method ramanujan
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
python cli.py explore --method chudnovsky
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Limit the number of displayed terms:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python cli.py explore --terms 20
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Compare Algorithms
|
|
152
|
+
|
|
153
|
+
Benchmark the available implementations.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python cli.py compare
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Current benchmark compares:
|
|
160
|
+
|
|
161
|
+
* Chudnovsky
|
|
162
|
+
* Machin
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Extract Hexadecimal Digits (BBP)
|
|
167
|
+
|
|
168
|
+
Retrieve hexadecimal digits beginning at a specified position without computing previous digits.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
python cli.py bbp 1
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Example:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
python cli.py bbp 1000
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Outputs the next 16 hexadecimal digits beginning at that position.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
# Algorithms Implemented
|
|
185
|
+
|
|
186
|
+
## Chudnovsky Algorithm
|
|
187
|
+
|
|
188
|
+
* Modern state-of-the-art series for computing Ī.
|
|
189
|
+
* Approximately **14 decimal digits per term**.
|
|
190
|
+
* Uses **binary splitting** for efficient large integer arithmetic.
|
|
191
|
+
* Suitable for very high precision.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Ramanujan Series
|
|
196
|
+
|
|
197
|
+
* Classic 1914 hypergeometric series.
|
|
198
|
+
* Extremely rapid convergence.
|
|
199
|
+
* Integer-scaled implementation for numerical stability.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Machin Formula
|
|
204
|
+
|
|
205
|
+
Uses
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
Ī = 4 Ã (4 arccot(5) â arccot(239))
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Advantages:
|
|
212
|
+
|
|
213
|
+
* Simple
|
|
214
|
+
* Educational
|
|
215
|
+
* Useful for comparison against faster modern methods
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## BaileyâBorweinâPlouffe (BBP)
|
|
220
|
+
|
|
221
|
+
Supports direct extraction of hexadecimal digits of Ī.
|
|
222
|
+
|
|
223
|
+
Unlike traditional algorithms, BBP allows accessing hexadecimal digits beginning at an arbitrary position without computing all preceding digits.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
# Examples
|
|
228
|
+
|
|
229
|
+
Compute 100 digits:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
python cli.py digits 100
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Compute 5000 digits using Chudnovsky:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
python cli.py digits 5000 --method chudnovsky
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Visualize convergence:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
python cli.py explore --method chudnovsky --terms 15
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Benchmark:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
python cli.py compare
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Extract hexadecimal digits:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
python cli.py bbp 250
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
# Dependencies
|
|
262
|
+
|
|
263
|
+
Only Python standard library modules are used:
|
|
264
|
+
|
|
265
|
+
* argparse
|
|
266
|
+
* decimal
|
|
267
|
+
* pathlib
|
|
268
|
+
* sys
|
|
269
|
+
* time
|
|
270
|
+
* typing
|
|
271
|
+
|
|
272
|
+
No external dependencies are required.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
# Configuration
|
|
277
|
+
|
|
278
|
+
There are currently no configuration files.
|
|
279
|
+
|
|
280
|
+
Precision and algorithm selection are controlled through command-line arguments.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
# Troubleshooting
|
|
285
|
+
|
|
286
|
+
### Import errors
|
|
287
|
+
|
|
288
|
+
Ensure the project directory structure matches the expected layout:
|
|
289
|
+
|
|
290
|
+
```text
|
|
291
|
+
core/
|
|
292
|
+
algorithms.py
|
|
293
|
+
visualize.py
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
### Slow execution
|
|
299
|
+
|
|
300
|
+
Very large digit counts require significant CPU time.
|
|
301
|
+
|
|
302
|
+
For best performance:
|
|
303
|
+
|
|
304
|
+
* Prefer the Chudnovsky algorithm.
|
|
305
|
+
* Use Ramanujan for convergence exploration.
|
|
306
|
+
* Use Machin primarily for educational purposes and comparisons.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### Unexpected precision
|
|
311
|
+
|
|
312
|
+
Higher requested precision naturally requires more computation time and memory due to large integer arithmetic.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
# Contributing
|
|
317
|
+
|
|
318
|
+
Contributions are welcome.
|
|
319
|
+
|
|
320
|
+
Possible improvements include:
|
|
321
|
+
|
|
322
|
+
* Additional Ī algorithms
|
|
323
|
+
* Parallel binary splitting
|
|
324
|
+
* Progress bars
|
|
325
|
+
* Graphical convergence plots
|
|
326
|
+
* Export benchmark results
|
|
327
|
+
* Automated testing
|
|
328
|
+
* Packaging for PyPI
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
# License
|
|
333
|
+
|
|
334
|
+
No license information was provided in the source files.
|
|
335
|
+
|
|
336
|
+
Consider adding a `LICENSE` file (for example MIT, Apache-2.0, or GPL-3.0) before publishing the project.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cli.py,sha256=bC1_Dfc8M2yW3EHPsKVhp9V4ij0UST73-kzkAKjb1JM,4393
|
|
2
|
+
core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
core/algorithms.py,sha256=bjZVvQhkk9s4lIdU-FTyzqdQfGBSWhNFsSgWIRPIFFI,7228
|
|
4
|
+
core/visualize.py,sha256=bFV-BZyqMrQkzxf9fhtOQqjVfY_b7G24VQH0NZ7OJYA,1022
|
|
5
|
+
foxpi-0.1.0.dist-info/licenses/LICENSE,sha256=p1OSXnJheNJK39gGLrV1Q4tD6bRP_UYYl_mQvp1_YNY,1068
|
|
6
|
+
foxpi-0.1.0.dist-info/METADATA,sha256=8PVgVFyexMKw-Tfh3LEZFPO3JfCXB-rvNVk_MYARVDA,5887
|
|
7
|
+
foxpi-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
8
|
+
foxpi-0.1.0.dist-info/entry_points.txt,sha256=DJ8tj_Bw-PI0HaaRWTFrmVWQ7ihel-G1fl-wBZmUZQs,35
|
|
9
|
+
foxpi-0.1.0.dist-info/top_level.txt,sha256=3d1SrIv4s8kkUKftU2GUWApholP9j4ktB3LaSaSWSNM,9
|
|
10
|
+
foxpi-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fox Hackerz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|