# Agent: Add New Programming Language to Pi Calculation Benchmark ## Overview This project benchmarks 34 programming languages calculating π (pi) using Machin's formula. Each language implements the same algorithm for fair performance comparison. This document provides complete instructions for adding new languages. ## Project Status **Current Languages (34 total):** bash, brainfuck, c, cpp, crystal, csharp, d, dart, elixir, erlang, fortran, go, haskell, java, javascript, julia, kotlin, objective-c, scala, typescript, lua, nim, odin, perl, php, python, r, ruby, rust, swift, zig, assembly, vimscript, wolfram **Test Environment:** - **Hardware:** MacBook Neo, Apple A18 Pro (6 cores: 2 performance + 4 efficiency), 8 GB RAM - **OS:** macOS (Darwin) - **Test Date:** 2026-04-23 **Performance Results (10000 decimals):** - **Fastest:** C (24 ms), Objective-C (25 ms), Assembly (27 ms) - **Slowest:** TypeScript (10334 ms), JavaScript (10065 ms), Swift (6735 ms) **Binary Sizes:** - **Smallest:** 103B (wrapper scripts for interpreted languages) - **Largest:** 13M (Haskell native binary) - **Typical compiled:** 34K-2.5M ## IMPORTANT: Bash Exception **Bash is an EXCEPTION** and serves only as reference code. Bash uses `bc -l` with formula `4*a(1)` to calculate pi, which is a different algorithm than Machin's formula. Bash is not included in performance comparisons and the requirements below do not apply to Bash. All other languages (Go, Rust, Python, C, C++, Haskell, Erlang, etc.) MUST follow the rules below exactly. ## Step 1: Create Directory Structure Create a new directory in the project root with the language name (lowercase) with the following structure: ``` /Users/einand/Code/test// ├── bin/ # Compiled binaries or wrapper scripts │ └── print_hej # The executable file ├── src/ # Source code │ └── print_hej. # Source file └── cmd/ # Commands and scripts ├── build.sh # Build script └── test.sh # Test script ``` Examples: - `python/src/print_hej.py` - `python/bin/print_hej` (wrapper script) - `python/cmd/build.sh` - `python/cmd/test.sh` - `rust/src/print_hej.rs` - `rust/bin/print_hej` (compiled binary) - `rust/cmd/build.sh` - `rust/cmd/test.sh` ## Step 2: Create Program File Create a file named `print_hej.` in the `src/` directory. ### Mandatory Program Requirements: 1. **Accept argument**: The program must accept one command-line argument specifying the number of decimal places to calculate. - If no argument provided, use default 100 decimals - If invalid argument, use default 100 decimals 2. **Calculate pi correctly**: Use Machin's formula with Taylor series for arctan. - Machin's formula: `pi/4 = 4*arctan(1/5) - arctan(1/239)` - Taylor-serien för arctan: `arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ...` ## Steg 2.5: OBLIGATORISK ALGORITM **VIKTIGT**: Alla implementationer MÅSTE använda exakt samma algoritm för att säkerställa rättvis jämförelse mellan språk. ### Den obligatoriska algoritmen för arctan(1/x): ``` function arctan(x, decimals): scale = 10^(decimals + 10) x_squared = x * x term = scale / x result = 0 sign = 1 n = 0 while term != 0 AND n < decimals * 3: // Add contribution with sign contrib = term / (2*n + 1) if sign > 0: result = result + contrib else: result = result - contrib // Next term: divide by x² term = term / x_squared // Flip sign sign = -sign n = n + 1 // Safety limit if n > decimals * 2: break return result ``` ### Nyckelpunkter för algoritmen: 1. **Skala med 10^(decimals+10)**: Använd heltalsaritmetik med skalfaktor för precision 2. **Dela med x² varje iteration**: Detta är den kritiska optimeringen! - ❌ **FEL**: Beräkna `x^(2n+1)` från grunden varje iteration (mycket långsamt) - ✅ **RÄTT**: `term = term / x²` varje iteration (snabbt) 3. **Använd teckenväxling**: `sign = -sign` för att alternera mellan addition och subtraktion 4. **Säkerhetsgräns**: `n < decimals * 3` för att undvika oändliga loopar ### Varför denna algoritm? Denna algoritm är **optimerad** för godtycklig precision: - **Effektivitet**: Att dela med `x²` varje iteration är O(n) operation - **Jämförbarhet**: Alla språk använder samma algoritm, vilket ger rättvis prestandajämförelse - **Korrekthet**: Algoritmen konvergerar snabbt och ger exakta resultat ### Exempel på implementationer: **Python:** ```python def arctan(x, precision): result = Decimal(0) x = Decimal(x) x_squared = x * x term = Decimal(1) / x sign = 1 for n in range(1000000): divisor = Decimal(2 * n + 1) contrib = term / divisor if sign > 0: result += contrib else: result -= contrib term = term / x_squared sign = -sign if term < Decimal(10) ** (-precision - 10): break return result ``` **Rust:** ```rust fn arctan_big(x: u32, scale: &BigUint) -> BigUint { let mut result = BigUint::zero(); let x_big = BigUint::from(x); let x_squared = &x_big * &x_big; let mut term = scale / &x_big; let mut sign: i32 = 1; let mut n: u64 = 0; loop { let divisor = BigUint::from(2u64 * n + 1); let contrib = &term / &divisor; if sign > 0 { result = &result + &contrib; } else { result = &result - &contrib; } term = &term / &x_squared; sign = -sign; if term.is_zero() || n > 5000000 { break; } n += 1; } result } ``` **C:** ```c void arctan(mpz_t result, unsigned long x, unsigned long decimals) { mpz_t term, x_squared, contrib; mpz_init(term); mpz_init(x_squared); mpz_init(contrib); mpz_t scale; mpz_init(scale); mpz_ui_pow_ui(scale, 10, decimals + 10); mpz_set_ui(x_squared, x); mpz_mul_ui(x_squared, x_squared, x); mpz_fdiv_q_ui(term, scale, x); mpz_set_ui(result, 0); unsigned long n = 0; int sign = 1; while (mpz_cmp_ui(term, 0) != 0 && n < decimals * 3) { mpz_fdiv_q_ui(contrib, term, 2 * n + 1); if (sign > 0) { mpz_add(result, result, contrib); } else { mpz_sub(result, result, contrib); } mpz_fdiv_q(term, term, x_squared); sign = -sign; n++; if (n > decimals * 2) break; } mpz_clear(term); mpz_clear(x_squared); mpz_clear(contrib); mpz_clear(scale); } ``` ### Steg 4: Utdataformat Programmet ska skriva ut pi med exakt antal decimaler, följt av newline. - Format: `3.1415926535...` (inga extra tecken, ingen avrundning) - Exakt `` decimaler efter punkten 5. **Inga extra utskrifter**: Endast pi-värdet ska skrivas ut, inga debug-meddelanden eller statusinformation. ### Exempel på korrekt utdata: ``` $ bin/print_hej 10 3.1415926535 $ bin/print_hej 5 3.14159 $ bin/print_hej 100 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 ``` ## Steg 5: Använd godtycklig precision (Arbitrary Precision) Programmet MÅSTE använda godtycklig precision (arbitrary precision) aritmetik för att beräkna pi korrekt med många decimaler. ### Språkspecifika bibliotek: | Språk | Bibliotek | Användning | |-------|-----------|------------| | Python | `decimal.Decimal` | `from decimal import Decimal, getcontext` | | Rust | `num-bigint` | `use num_bigint::BigUint;` | | Go | `math/big` | `import "math/big"` | | Bash | `bc -l` | `echo "scale=$decimals; 4*a(1)" \| bc -l` | | C | `GMP` eller egen implementation | `#include ` | | C++ | `boost::multiprecision` | `#include ` | | Java | `BigInteger` / `BigDecimal` | `import java.math.BigInteger;` | | JavaScript | `big-integer` eller `decimal.js` | `npm install big-integer` | | Ruby | `BigDecimal` | `require 'bigdecimal'` | ### Viktigt om precision: - Sätt precision till minst `decimals + 10` för att undvika avrundningsfel - Använd heltalsaritmetik där det är möjligt (skala med 10^n) - Kontrollera att resultatet matchar facit.txt ## Steg 6: Kompilera (om nödvändigt) Om språket kräver kompilering: ### Kompilerade språk: 1. **Rust**: Skapa `Cargo.toml` med beroenden ```toml [dependencies] num-bigint = "0.4" num-traits = "0.2" ``` Kompilera: `cargo build --release` Binär: `bin/print_hej` 2. **Go**: Ingen extra konfiguration behövs Kompilera: `go build -o bin/print_hej src/print_hej.go` 3. **C/C++**: Skapa `Makefile` eller kompilera manuellt Kompilera: `gcc -o bin/print_hej src/print_hej.c -lgmp` ### Tolkade språk: Ingen kompilering behövs. Skapa ett wrapper-script i `bin/`: ```bash #!/bin/bash # Wrapper script for interpreted languages SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" src/print_hej. "$@" ``` ## Steg 7: Skapa build.sh (OBLIGATORISKT) **VIKTIGT**: Varje språk MÅSTE ha en `build.sh` i `cmd/`-katalogen som bygger programmet. Skapa filen `/cmd/build.sh` med följande innehåll: ### För kompilerade språk: ```bash #!/bin/bash # Build Script SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Build ===" echo "" # Skapa bin-katalog mkdir -p bin # Kompilera programmet -o bin/print_hej src/print_hej. if [ $? -eq 0 ]; then echo "✓ Kompilering lyckades!" echo "Binär: bin/print_hej" echo "" echo "För att köra:" echo " bin/print_hej [decimaler]" else echo "✗ Kompilering misslyckades!" exit 1 fi ``` ### För interpreterade språk: ```bash #!/bin/bash # Build Script - är interpreterat, ingen kompilering behövs SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Build ===" echo " är ett interpreterat språk, ingen kompilering behövs." echo "Script: src/print_hej." echo "" echo "Skapar wrapper script i bin/" mkdir -p bin cat > bin/print_hej << 'EOF' #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" src/print_hej. "$@" EOF chmod +x bin/print_hej echo "✓ Klart!" ``` ### Exempel: **C:** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== C Build ===" mkdir -p bin gcc -o bin/print_hej src/print_hej.c -lgmp if [ $? -eq 0 ]; then echo "✓ Kompilering lyckades!" else echo "✗ Kompilering misslyckades!" exit 1 fi ``` **Python:** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Python Build ===" mkdir -p bin cat > bin/print_hej << 'EOF' #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" python3 src/print_hej.py "$@" EOF chmod +x bin/print_hej echo "✓ Klart!" ``` ## Steg 8: Skapa test.sh (OBLIGATORISKT) **VIKTIGT**: Tester är OBLIGATORISKT, inte valfria. Varje nytt språk MÅSTE ha tester. Skapa filen `/cmd/test.sh` som kör språkets testramverk: ### För språk med testramverk: ```bash #!/bin/bash # Unit Tests - använder SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Pi-beräkning Unit Tester () ===" echo "" # Kör testramverket exit $? ``` ### Exempel per språk: **Python (pytest):** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Python Pi-beräkning Unit Tester (pytest) ===" /Users/einand/Code/test/.venv/bin/python -m pytest src/test_pi.py -v exit $? ``` **JavaScript (Jest):** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== JavaScript Pi-beräkning Unit Tester (Jest) ===" npm test exit $? ``` **Go (go test):** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Go Pi-beräkning Unit Tester (go test) ===" go test -v exit $? ``` **Rust (cargo test):** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== Rust Pi-beräkning Unit Tester (cargo test) ===" cargo test exit $? ``` **C (assert):** ```bash #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" cd "$SCRIPT_DIR" echo "=== C Pi-beräkning Unit Tester (assert) ===" gcc -o bin/pi_test src/pi_test.c bin/pi_test exit $? ``` ### Obligatoriska tester: Varje testfil ska innehålla följande testfall: 1. **Testa 10 decimaler**: Resultatet ska vara `3.1415926535` 2. **Testa 5 decimaler**: Resultatet ska vara `3.14159` 3. **Testa 1 decimal**: Resultatet ska vara `3.1` 4. **Testa 100 decimaler**: Resultatet ska matcha facit.txt 5. **Testa default (100 decimaler)**: Resultatet ska matcha facit.txt 6. **Testa ogiltig input**: Ska använda default (100 decimaler) 7. **Testa 10000 decimaler**: Resultatet ska matcha facit.txt ## Steg 9: Verifiera Kör `build.sh` och `test.sh` för att verifiera: ```bash # Bygg programmet cd cmd/build.sh # Kör tester cmd/test.sh # Eller kör alla builds och tester från roten cd /Users/einand/Code/test ./build.sh # Bygger alla språk ./run_all_tests.sh # Kör alla tester ``` Alla tester ska passera för det nya språket. ## Steg 10: Dokumentation Lägg till en README.md i språkkatalogen med: 1. **Beskrivning**: Kort beskrivning av implementationen 2. **Krav**: Nödvändiga beroenden och versioner 3. **Kompilering**: Instruktioner för att kompilera (om nödvändigt) 4. **Körning**: Instruktioner för att köra programmet 5. **Prestanda**: Notering om prestanda jämfört med andra språk ### Exempel på README.md: ```markdown # Python Pi-beräkning ## Beskrivning Beräknar pi med godtycklig precision med hjälp av Machins formel. ## Struktur ``` python/ ├── bin/ │ └── print_hej # Wrapper script ├── src/ │ └── print_hej.py # Källkod └── cmd/ ├── build.sh # Byggscript └── test.sh # Testscript ``` ## Krav - Python 3.6+ - Inga externa beroenden (använder `decimal` från standardbiblioteket) ## Körning ```bash # Bygg (skapar wrapper script) cmd/build.sh # Kör bin/print_hej ``` ## Prestanda - 10 decimaler: ~100 ms - 100 decimaler: ~40 ms - 10000 decimaler: ~500 ms ``` ## Vanliga problem och lösningar ### Problem: "Avrundningsfel vid många decimaler" **Lösning**: Öka precisionen i beräkningen. Sätt precision till minst `decimals + 20` för att undvika avrundningsfel i sista siffrorna. ### Problem: "Programmet är för långsamt" **Lösning**: - Använd Machins formel istället för Leibniz formel (konvergerar snabbare) - Optimera arctan-funktionen med bättre algoritmer - Använd språkets optimerade bibliotek för stor heltalsaritmetik ### Problem: "Resultatet matchar inte facit.txt" **Lösning**: - Kontrollera att du inte avrundar resultatet - Se till att du klipper till exakt rätt antal decimaler - Verifiera att algoritmen är korrekt implementerad ### Problem: "Kompileringsfel med beroenden" **Lösning**: - Se till att alla beroenden är installerade - Kontrollera versioner av bibliotek - Använd container för att isolera miljön ## Facit Facit finns i `/Users/einand/Code/test/facit.txt` och innehåller pi med 10000+ decimaler. ## Struktur ``` /Users/einand/Code/test/ ├── bash/ │ ├── bin/ │ │ └── print_hej │ ├── src/ │ │ └── print_hej.sh │ └── cmd/ │ ├── build.sh │ └── test.sh ├── go/ │ ├── bin/ │ │ └── print_hej │ ├── src/ │ │ ├── print_hej.go │ │ └── print_hej_test.go │ └── cmd/ │ ├── build.sh │ └── test.sh ├── rust/ │ ├── bin/ │ │ └── print_hej │ ├── src/ │ │ └── print_hej.rs │ └── cmd/ │ ├── build.sh │ └── test.sh ├── python/ │ ├── bin/ │ │ └── print_hej │ ├── src/ │ │ ├── print_hej.py │ │ └── test_pi.py │ └── cmd/ │ ├── build.sh │ └── test.sh ├── / │ ├── bin/ │ │ └── print_hej │ ├── src/ │ │ └── print_hej. │ └── cmd/ │ ├── build.sh │ └── test.sh └── facit.txt # Facit för verifiering ``` ## Sammanfattning För att lägga till ett nytt språk: 1. Skapa katalogstruktur `/{bin,src,cmd}/` 2. Skapa `src/print_hej.` med korrekt implementation 3. **Använd den obligatoriska algoritmen** (se Steg 2.5) 4. Använd godtycklig precision (arbitrary precision) 5. Skapa `cmd/build.sh` (OBLIGATORISKT) - bygger programmet 6. Skapa `cmd/test.sh` (OBLIGATORISKT) - kör testramverket 7. Skapa testfiler för språkets testramverk (t.ex. `src/test_pi.py`, `src/pi_test.go`) 8. Verifiera med `cmd/build.sh` och `cmd/test.sh` 9. Dokumentera i README.md **VIKTIGT**: - Alla implementationer MÅSTE använda exakt samma algoritm (se Steg 2.5) för att säkerställa rättvis prestandajämförelse - `cmd/build.sh` och `cmd/test.sh` är OBLIGATORISKA, inte valfria - Tester ska använda språkets standardiserade testramverk (pytest, Jest, go test, etc.) - Binären/wrappern ska placeras i `bin/`-katalogen - Källkoden ska placeras i `src/`-katalogen - Scripts ska placeras i `cmd/`-katalogen Följ dessa steg exakt för att säkerställa att det nya språket fungerar korrekt med resten av projektet.