Files
Ein Anderssono cb9363dc26 Update AGENT.md with English translation and project status
- Translated beginning of AGENT.md to English
- Added project status section with current languages (34 total)
- Added test environment specifications (Apple A18 Pro, 8GB RAM)
- Added performance results summary
- Added binary size information
- Partial translation in progress
2026-04-23 00:50:13 +02:00

18 KiB

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/<language>/
├── bin/           # Compiled binaries or wrapper scripts
│   └── print_hej  # The executable file
├── src/           # Source code
│   └── print_hej.<extension>  # 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.<extension> 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 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:

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:

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:

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 <antal_decimaler> decimaler efter punkten
  1. 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 <gmp.h>
C++ boost::multiprecision #include <boost/multiprecision/cpp_int.hpp>
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

    [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/:

#!/bin/bash
# Wrapper script for interpreted languages
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"
<interpreter> src/print_hej.<extension> "$@"

Steg 7: Skapa build.sh (OBLIGATORISKT)

VIKTIGT: Varje språk MÅSTE ha en build.sh i cmd/-katalogen som bygger programmet.

Skapa filen <språk>/cmd/build.sh med följande innehåll:

För kompilerade språk:

#!/bin/bash

# <Språk> Build Script

SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"

echo "=== <Språk> Build ==="
echo ""

# Skapa bin-katalog
mkdir -p bin

# Kompilera programmet
<kompilationskommando> -o bin/print_hej src/print_hej.<extension>

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:

#!/bin/bash

# <Språk> Build Script - <Språk> är interpreterat, ingen kompilering behövs

SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"

echo "=== <Språk> Build ==="
echo "<Språk> är ett interpreterat språk, ingen kompilering behövs."
echo "Script: src/print_hej.<extension>"
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"
<interpreter> src/print_hej.<extension> "$@"
EOF
chmod +x bin/print_hej
echo "✓ Klart!"

Exempel:

C:

#!/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:

#!/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 <språk>/cmd/test.sh som kör språkets testramverk:

För språk med testramverk:

#!/bin/bash

# <Språk> Unit Tests - använder <testramverk>

SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"

echo "=== <Språk> Pi-beräkning Unit Tester (<testramverk>) ==="
echo ""

# Kör testramverket
<testkommando>

exit $?

Exempel per språk:

Python (pytest):

#!/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):

#!/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):

#!/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):

#!/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):

#!/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:

# Bygg programmet
cd <språk>
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:

# 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 <antal_decimaler>

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 ├── <nytt_språk>/ │ ├── 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 `<språk>/{bin,src,cmd}/`
2. Skapa `src/print_hej.<extension>` 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.