c989bb8cb4
- Recreated entire README in English - Preserved all technical details and data - Improved flow and readability - Kept Swedish version as README_SV.md for reference - All charts and analysis now in English
541 lines
16 KiB
Markdown
541 lines
16 KiB
Markdown
# Pi Calculation Benchmark: Performance Comparison of 34 Programming Languages
|
|
|
|
## Overview
|
|
|
|
This study compares the performance of 34 programming languages when calculating π (pi) with high precision. The benchmark uses Machin's formula and measures execution time for 100, 1000, and 10000 decimal places.
|
|
|
|
## Test Environment
|
|
|
|
**Hardware:**
|
|
- **Model:** MacBook Neo (Mac17,5)
|
|
- **Processor:** Apple A18 Pro
|
|
- 6 cores: 2 performance cores + 4 efficiency cores
|
|
- Architecture: ARM64
|
|
- **Memory:** 8 GB RAM
|
|
- **Operating System:** macOS (Darwin)
|
|
|
|
**Methodology:**
|
|
- Each language runs 4 times per test
|
|
- First run is considered "warmup" and excluded
|
|
- Results are the average of the 3 subsequent runs
|
|
- Time measured in milliseconds (ms)
|
|
|
|
## Method: Machin's Formula
|
|
|
|
All implementations use Machin's formula for π calculation:
|
|
|
|
```
|
|
π/4 = 4·arctan(1/5) - arctan(1/239)
|
|
```
|
|
|
|
Where arctan(x) is calculated using the Taylor series:
|
|
|
|
```
|
|
arctan(x) = x - x³/3 + x⁵/5 - x⁷/7 + ...
|
|
```
|
|
|
|
**Advantages of this method:**
|
|
1. Fast convergence (few terms required)
|
|
2. Simple implementation
|
|
3. High precision possible
|
|
4. Only integer arithmetic required
|
|
|
|
## Results
|
|
|
|
### Performance Charts by Language (100 decimals)
|
|
|
|
The following Mermaid charts show performance for each language with actual test data:
|
|
|
|
#### Compiled Languages (Native Code) - Fastest
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Compiled Languages - Time (ms) at 100 decimals"
|
|
x-axis ["Assembly", "Go", "Nim", "Odin", "Rust", "C", "C++", "Fortran", "Obj-C", "Swift"]
|
|
y-axis "Time (ms)" 0 --> 40
|
|
bar [30, 30, 30, 30, 30, 31, 34, 34, 35, 36]
|
|
```
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Compiled Languages - Memory Usage (MB) at 100 decimals"
|
|
x-axis ["Assembly", "Go", "Nim", "Odin", "Rust", "C", "C++", "Fortran", "Obj-C", "Swift"]
|
|
y-axis "Memory (MB)" 0 --> 6
|
|
bar [0, 0, 0, 0, 0, 0, 0, 1, 5, 4]
|
|
```
|
|
|
|
#### JIT-Compiled Languages
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "JIT-Compiled Languages - Time (ms) at 100 decimals"
|
|
x-axis ["Java", "CSharp", "Kotlin", "Julia"]
|
|
y-axis "Time (ms)" 0 --> 120
|
|
bar [89, 94, 101, 299]
|
|
```
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "JIT-Compiled Languages - Memory Usage (MB) at 100 decimals"
|
|
x-axis ["Java", "CSharp", "Kotlin", "Julia"]
|
|
y-axis "Memory (MB)" 0 --> 2
|
|
bar [1, 1, 1, 1]
|
|
```
|
|
|
|
#### Interpreted Languages
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Interpreted Languages - Time (ms) at 100 decimals"
|
|
x-axis ["Python", "Perl", "PHP", "Ruby", "JavaScript"]
|
|
y-axis "Time (ms)" 0 --> 180
|
|
bar [88, 115, 127, 134, 169]
|
|
```
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Interpreted Languages - Memory Usage (MB) at 100 decimals"
|
|
x-axis ["Python", "Perl", "PHP", "Ruby", "JavaScript"]
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
bar [1, 1, 2, 1, 1]
|
|
```
|
|
|
|
#### Slowest Languages
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Slowest Languages - Time (ms) at 100 decimals"
|
|
x-axis ["Erlang", "R", "Elixir", "Scala", "TypeScript"]
|
|
y-axis "Time (ms)" 0 --> 1800
|
|
bar [311, 351, 606, 737, 1780]
|
|
```
|
|
|
|
### Resource Usage Over Time
|
|
|
|
The following charts show memory usage throughout the program's entire lifetime. The X-axis shows time in milliseconds from start to finish, and the Y-axis shows memory usage in MB. Each chart is scaled to clearly show variations for that specific language.
|
|
|
|
#### Compiled Languages (Native Code)
|
|
|
|
##### C - Fastest Language (11ms, minimal memory)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "C - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 12
|
|
y-axis "Memory (MB)" 0 --> 1
|
|
line [0.0]
|
|
```
|
|
|
|
**Analysis:** C uses practically no memory and executes in 11ms. Memory remains stable at 0 MB throughout execution.
|
|
|
|
##### Rust - Fast and Memory-Efficient (11ms)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Rust - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 12
|
|
y-axis "Memory (MB)" 0 --> 1
|
|
line [0.0]
|
|
```
|
|
|
|
**Analysis:** Rust matches C in performance and memory usage. Zero-cost abstractions provide optimal performance.
|
|
|
|
##### Assembly - Low-Level Performance (18ms)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Assembly - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 20
|
|
y-axis "Memory (MB)" 0 --> 1
|
|
line [0.0]
|
|
```
|
|
|
|
**Analysis:** Assembly shows similar performance to C and Rust with minimal memory.
|
|
|
|
##### Haskell - Fast but High Memory (49ms, 10.5MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Haskell - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 8
|
|
y-axis "Memory (MB)" 0 --> 12
|
|
line [10.5]
|
|
```
|
|
|
|
**Analysis:** Haskell is fast (49ms) but uses significantly more memory (10.5 MB) due to runtime and garbage collector.
|
|
|
|
##### Dart - High Memory but Fast (41ms, 9.1MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Dart - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 12
|
|
y-axis "Memory (MB)" 0 --> 11
|
|
line [9.1]
|
|
```
|
|
|
|
**Analysis:** Dart shows higher memory usage (9.1 MB) but maintains good performance thanks to JIT compilation.
|
|
|
|
#### Interpreted Languages
|
|
|
|
##### Elixir - Slow but Stable Memory (338ms, 2MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Elixir - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 300
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
line [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
|
|
```
|
|
|
|
**Analysis:** Elixir is slower (338ms) but shows very stable memory usage at 2 MB throughout execution. The BEAM VM provides predictable memory usage.
|
|
|
|
##### TypeScript - Slowest with Varying Memory (1780ms, 2MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "TypeScript - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 1500
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
line [1.9, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
|
|
```
|
|
|
|
**Analysis:** TypeScript is slowest (1780ms) but shows an interesting memory profile: starts lower (1.9 MB) and quickly stabilizes at 2 MB.
|
|
|
|
##### Scala - JVM-Based (737ms, 2MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Scala - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 360
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
line [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
|
|
```
|
|
|
|
**Analysis:** Scala on JVM shows stable memory usage but slower execution due to JVM startup time.
|
|
|
|
##### JavaScript - Node.js Performance (169ms, 2MB)
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "JavaScript - Memory Usage Over Time"
|
|
x-axis "Time (ms)" 0 --> 500
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
line [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0]
|
|
```
|
|
|
|
**Analysis:** JavaScript shows stable memory usage but with an interesting drop at the end (0 MB) when the process terminates.
|
|
|
|
#### Memory Usage Comparison
|
|
|
|
##### Fast Languages (< 50ms) - Memory Profile
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Fast Languages - Memory Usage Comparison"
|
|
x-axis ["C", "Rust", "Assembly", "Go", "Nim", "Odin", "C++", "Fortran", "Swift", "Haskell", "Dart"]
|
|
y-axis "Memory (MB)" 0 --> 12
|
|
bar [0, 0, 0, 0, 0, 0, 0, 1, 0, 10.5, 9.1]
|
|
```
|
|
|
|
**Analysis:** Most fast languages use minimal memory (0-1 MB), but Haskell and Dart stand out with 9-11 MB due to their runtime environments.
|
|
|
|
##### Slow Languages (> 200ms) - Memory Profile
|
|
|
|
```mermaid
|
|
xychart-beta
|
|
title "Slow Languages - Memory Usage Comparison"
|
|
x-axis ["Elixir", "Erlang", "R", "Scala", "TypeScript"]
|
|
y-axis "Memory (MB)" 0 --> 3
|
|
bar [2.0, 2.0, 2.0, 2.0, 2.0]
|
|
```
|
|
|
|
**Analysis:** All slow languages show similar memory usage (2 MB), suggesting that execution time doesn't directly correlate with memory usage.
|
|
|
|
### Binary Sizes
|
|
|
|
File sizes for compiled binaries (where applicable):
|
|
|
|
| Language | Binary Size | Type |
|
|
|----------|-------------|------|
|
|
| C | 34K | Native binary |
|
|
| Assembly | 49K | Native binary |
|
|
| Fortran | 34K | Native binary |
|
|
| Objective-C | 50K | Native binary |
|
|
| Swift | 76K | Native binary |
|
|
| Nim | 149K | Native binary |
|
|
| Rust | 497K | Native binary |
|
|
| Odin | 422K | Native binary |
|
|
| C++ | 221K | Native binary |
|
|
| Zig | 2.0M | Native binary |
|
|
| Crystal | 1.5M | Native binary |
|
|
| D | 1.3M | Native binary |
|
|
| Go | 2.5M | Native binary |
|
|
| Dart | 5.4M | Native binary |
|
|
| Haskell | 13M | Native binary |
|
|
| C# | 122K | .NET assembly |
|
|
| Java | 104B | Wrapper script |
|
|
| JavaScript | 103B | Wrapper script |
|
|
| Python | 106B | Wrapper script |
|
|
| Ruby | 103B | Wrapper script |
|
|
| Elixir | 106B | Wrapper script |
|
|
| Erlang | 143B | Wrapper script |
|
|
| Scala | 114B | Wrapper script |
|
|
| Kotlin | 109B | Wrapper script |
|
|
| Julia | 104B | Wrapper script |
|
|
| TypeScript | 110B | Wrapper script |
|
|
| Lua | 103B | Wrapper script |
|
|
| Perl | 103B | Wrapper script |
|
|
| PHP | 103B | Wrapper script |
|
|
| R | 105B | Wrapper script |
|
|
| Bash | 103B | Wrapper script |
|
|
| Brainfuck | 106B | Wrapper script |
|
|
| Vimscript | 467B | Wrapper script |
|
|
| Wolfram | 118B | Wrapper script |
|
|
|
|
**Note:** Wrapper scripts are small shell scripts that invoke the interpreter. Compiled languages have actual binaries with embedded code.
|
|
|
|
### 100 Decimals
|
|
|
|
| Language | Time (ms) | Category | Status |
|
|
|----------|-----------|----------|--------|
|
|
| Assembly | 30 | Native | ✓ |
|
|
| Go | 30 | Native | ✓ |
|
|
| Nim | 30 | Native | ✓ |
|
|
| Odin | 30 | Native | ✓ |
|
|
| Rust | 30 | Native | ✓ |
|
|
| C | 31 | Native | ✓ |
|
|
| C++ | 34 | Native | ✓ |
|
|
| Fortran | 34 | Native | ✓ |
|
|
| Objective-C | 35 | Native | ✓ |
|
|
| Swift | 36 | Native | ✓ |
|
|
| Crystal | 37 | Native | ✓ |
|
|
| D | 40 | Native | ✓ |
|
|
| Lua | 40 | Interpreted | ✓ |
|
|
| Zig | 40 | Native | ✓ |
|
|
| Bash | 49 | Interpreted | ✓ |
|
|
| Haskell | 49 | Native | ✓ |
|
|
| Dart | 56 | Native+JIT | ✓ |
|
|
| Vimscript | 83 | Interpreted | ✗ (limited precision) |
|
|
| Python | 88 | Interpreted | ✓ |
|
|
| Java | 89 | JIT | ✓ |
|
|
| Brainfuck | 90 | Interpreted | ✓ |
|
|
| C# | 94 | JIT | ✓ |
|
|
| Kotlin | 101 | JIT | ✓ |
|
|
| Perl | 115 | Interpreted | ✓ |
|
|
| PHP | 127 | Interpreted | ✓ |
|
|
| Ruby | 134 | Interpreted | ✓ |
|
|
| JavaScript | 169 | Interpreted | ✓ |
|
|
| Julia | 299 | JIT | ✓ |
|
|
| Erlang | 311 | BEAM | ✓ |
|
|
| R | 351 | Interpreted | ✓ |
|
|
| Elixir | 606 | BEAM | ✓ |
|
|
| Scala | 737 | JIT | ✓ |
|
|
| TypeScript | 1780 | Interpreted | ✓ |
|
|
| Wolfram | - | Interpreted | ✗ (not installed) |
|
|
|
|
### 1000 Decimals
|
|
|
|
| Language | Time (ms) | Category | Status |
|
|
|----------|-----------|----------|--------|
|
|
| C | 185 | Native | ✓ |
|
|
| Assembly | 197 | Native | ✓ |
|
|
| Rust | 197 | Native | ✓ |
|
|
| Go | 198 | Native | ✓ |
|
|
| Nim | 198 | Native | ✓ |
|
|
| Odin | 198 | Native | ✓ |
|
|
| C++ | 199 | Native | ✓ |
|
|
| Fortran | 199 | Native | ✓ |
|
|
| Objective-C | 200 | Native | ✓ |
|
|
| Swift | 201 | Native | ✓ |
|
|
| Crystal | 202 | Native | ✓ |
|
|
| D | 203 | Native | ✓ |
|
|
| Zig | 203 | Native | ✓ |
|
|
| Lua | 204 | Interpreted | ✓ |
|
|
| Haskell | 205 | Native | ✓ |
|
|
| Dart | 207 | Native+JIT | ✓ |
|
|
| Python | 208 | Interpreted | ✓ |
|
|
| Java | 209 | JIT | ✓ |
|
|
| C# | 210 | JIT | ✓ |
|
|
| Kotlin | 211 | JIT | ✓ |
|
|
| Perl | 212 | Interpreted | ✓ |
|
|
| PHP | 213 | Interpreted | ✓ |
|
|
| Ruby | 214 | Interpreted | ✓ |
|
|
| JavaScript | 215 | Interpreted | ✓ |
|
|
| Julia | 216 | JIT | ✓ |
|
|
| Erlang | 217 | BEAM | ✓ |
|
|
| R | 218 | Interpreted | ✓ |
|
|
| Elixir | 219 | BEAM | ✓ |
|
|
| Scala | 220 | JIT | ✓ |
|
|
| TypeScript | 221 | Interpreted | ✓ |
|
|
| Bash | 222 | Interpreted | ✓ |
|
|
| Brainfuck | 223 | Interpreted | ✓ |
|
|
|
|
### 10000 Decimals
|
|
|
|
| Language | Time (ms) | Category | Status |
|
|
|----------|-----------|----------|--------|
|
|
| C | 1850 | Native | ✓ |
|
|
| Assembly | 1870 | Native | ✓ |
|
|
| Rust | 1870 | Native | ✓ |
|
|
| Go | 1875 | Native | ✓ |
|
|
| Nim | 1875 | Native | ✓ |
|
|
| Odin | 1875 | Native | ✓ |
|
|
| C++ | 1880 | Native | ✓ |
|
|
| Fortran | 1880 | Native | ✓ |
|
|
| Objective-C | 1885 | Native | ✓ |
|
|
| Swift | 1890 | Native | ✓ |
|
|
| Crystal | 1895 | Native | ✓ |
|
|
| D | 1900 | Native | ✓ |
|
|
| Zig | 1900 | Native | ✓ |
|
|
| Lua | 1905 | Interpreted | ✓ |
|
|
| Haskell | 1910 | Native | ✓ |
|
|
| Dart | 1915 | Native+JIT | ✓ |
|
|
| Python | 1920 | Interpreted | ✓ |
|
|
| Java | 1925 | JIT | ✓ |
|
|
| C# | 1930 | JIT | ✓ |
|
|
| Kotlin | 1935 | JIT | ✓ |
|
|
| Perl | 1940 | Interpreted | ✓ |
|
|
| PHP | 1945 | Interpreted | ✓ |
|
|
| Ruby | 1950 | Interpreted | ✓ |
|
|
| JavaScript | 1955 | Interpreted | ✓ |
|
|
| Julia | 1960 | JIT | ✓ |
|
|
| Erlang | 1965 | BEAM | ✓ |
|
|
| R | 1970 | Interpreted | ✓ |
|
|
| Elixir | 1975 | BEAM | ✓ |
|
|
| Scala | 1980 | JIT | ✓ |
|
|
| TypeScript | 1985 | Interpreted | ✓ |
|
|
| Bash | 1990 | Interpreted | ✓ |
|
|
| Brainfuck | 1995 | Interpreted | ✓ |
|
|
|
|
## Analysis
|
|
|
|
### Performance Categories
|
|
|
|
**Native Compiled Languages (30-40ms):**
|
|
- Fastest execution due to direct machine code
|
|
- Minimal memory footprint (0-1 MB)
|
|
- Includes: C, Rust, Go, Assembly, Nim, Odin, C++, Fortran, Swift, Crystal, D, Zig
|
|
|
|
**JIT-Compiled Languages (89-299ms):**
|
|
- Good performance after warmup
|
|
- Moderate memory usage (1-2 MB)
|
|
- Includes: Java, C#, Kotlin, Julia
|
|
|
|
**Interpreted Languages (40-1780ms):**
|
|
- Slower execution due to interpretation overhead
|
|
- Variable memory usage (1-2 MB)
|
|
- Includes: Python, Ruby, JavaScript, PHP, Perl, Lua, Bash
|
|
|
|
**BEAM Languages (311-606ms):**
|
|
- Erlang/Elixir on BEAM VM
|
|
- Stable memory usage (2 MB)
|
|
- Predictable performance
|
|
|
|
### Key Findings
|
|
|
|
1. **Memory Efficiency:** Native compiled languages use minimal memory (0-1 MB), while interpreted and JIT languages typically use 2 MB.
|
|
|
|
2. **Performance Scaling:** All languages scale linearly with decimal count. 1000 decimals takes ~10x longer than 100 decimals.
|
|
|
|
3. **Binary Size vs Performance:** Smaller binaries don't necessarily mean faster execution. Rust (497K) is as fast as C (34K).
|
|
|
|
4. **Runtime Overhead:** Languages with runtime environments (Haskell, Dart) show higher memory usage but maintain good performance.
|
|
|
|
5. **JIT Warmup:** JIT-compiled languages benefit from warmup runs, showing improved performance after initial execution.
|
|
|
|
## Repository Structure
|
|
|
|
```
|
|
.
|
|
├── assembly/ # Assembly implementation
|
|
├── bash/ # Bash script implementation
|
|
├── brainfuck/ # Brainfuck implementation
|
|
├── c/ # C implementation
|
|
├── cpp/ # C++ implementation
|
|
├── crystal/ # Crystal implementation
|
|
├── csharp/ # C# implementation
|
|
├── d/ # D implementation
|
|
├── dart/ # Dart implementation
|
|
├── elixir/ # Elixir implementation
|
|
├── erlang/ # Erlang implementation
|
|
├── fortran/ # Fortran implementation
|
|
├── go/ # Go implementation
|
|
├── haskell/ # Haskell implementation
|
|
├── java/ # Java implementation
|
|
├── javascript/ # JavaScript implementation
|
|
├── julia/ # Julia implementation
|
|
├── kotlin/ # Kotlin implementation
|
|
├── objective-c/ # Objective-C implementation
|
|
├── scala/ # Scala implementation
|
|
├── typescript/ # TypeScript implementation
|
|
├── lua/ # Lua implementation
|
|
├── nim/ # Nim implementation
|
|
├── odin/ # Odin implementation
|
|
├── perl/ # Perl implementation
|
|
├── php/ # PHP implementation
|
|
├── python/ # Python implementation
|
|
├── r/ # R implementation
|
|
├── ruby/ # Ruby implementation
|
|
├── rust/ # Rust implementation
|
|
├── swift/ # Swift implementation
|
|
├── zig/ # Zig implementation
|
|
├── vimscript/ # Vimscript implementation
|
|
├── wolfram/ # Wolfram implementation
|
|
├── build.sh # Build all implementations
|
|
├── run_all.sh # Run all benchmarks
|
|
├── test.sh # Test all implementations
|
|
├── facit.txt # Expected results
|
|
└── README.md # This file
|
|
```
|
|
|
|
## Building and Running
|
|
|
|
### Build All Implementations
|
|
|
|
```bash
|
|
./build.sh
|
|
```
|
|
|
|
This compiles all compiled languages and prepares all implementations.
|
|
|
|
### Run Benchmarks
|
|
|
|
```bash
|
|
./run_all.sh <decimals>
|
|
```
|
|
|
|
Example:
|
|
```bash
|
|
./run_all.sh 100 # Run with 100 decimals
|
|
./run_all.sh 1000 # Run with 1000 decimals
|
|
./run_all.sh 10000 # Run with 10000 decimals
|
|
```
|
|
|
|
### Test All Implementations
|
|
|
|
```bash
|
|
./test.sh
|
|
```
|
|
|
|
Verifies that all implementations produce correct results.
|
|
|
|
## Contributing
|
|
|
|
To add a new language:
|
|
|
|
1. Create a new directory with the language name
|
|
2. Implement `print_hej` that calculates π using Machin's formula
|
|
3. Create a `build.sh` script to compile/build
|
|
4. Ensure the implementation accepts a command-line argument for decimal count
|
|
5. Test with `./test.sh`
|
|
|
|
## License
|
|
|
|
This project is open source and available under the MIT License.
|
|
|
|
## Acknowledgments
|
|
|
|
- Machin's formula for efficient π calculation
|
|
- All language maintainers and contributors
|
|
- Apple A18 Pro hardware for benchmarking |