Initial commit: Pi calculation benchmark with 34 languages
- Added implementations for: 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 - All implementations use Machin's formula: π/4 = 4*arctan(1/5) - arctan(1/239) - Build system with ./build.sh, test system with ./test.sh - Performance testing with ./run_all.sh - Comprehensive README.md explaining performance differences - Test framework verifies correctness against known π values
This commit is contained in:
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Nim Build Script
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== Nim Build ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera Nim-programmet
|
||||
nim c -o:bin/print_hej src/print_hej.nim
|
||||
|
||||
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
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Nim Unit Tests
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== Nim Pi-beräkning Unit Tester ==="
|
||||
echo ""
|
||||
|
||||
cd src
|
||||
nim c -r test_pi.nim
|
||||
|
||||
exit $?
|
||||
@@ -0,0 +1,142 @@
|
||||
import std/strutils
|
||||
import std/os
|
||||
|
||||
type BigInt = object
|
||||
digits: seq[uint64]
|
||||
|
||||
proc initBigInt(value: int = 0): BigInt =
|
||||
if value == 0:
|
||||
result.digits = @[0'u64]
|
||||
else:
|
||||
result.digits = @[uint64(abs(value))]
|
||||
|
||||
proc initBigInt(value: uint64): BigInt =
|
||||
result.digits = @[value]
|
||||
|
||||
proc `+`(a: BigInt, b: BigInt): BigInt =
|
||||
result.digits = @[]
|
||||
var carry: uint64 = 0
|
||||
let maxLen = max(a.digits.len, b.digits.len)
|
||||
|
||||
for i in 0..<maxLen:
|
||||
let x = if i < a.digits.len: a.digits[i] else: 0'u64
|
||||
let y = if i < b.digits.len: b.digits[i] else: 0'u64
|
||||
let sum = x + y + carry
|
||||
result.digits.add(sum mod 1_000_000_000)
|
||||
carry = sum div 1_000_000_000
|
||||
|
||||
if carry > 0:
|
||||
result.digits.add(carry)
|
||||
|
||||
proc `-`(a: BigInt, b: BigInt): BigInt =
|
||||
result.digits = a.digits
|
||||
var borrow: int64 = 0
|
||||
|
||||
for i in 0..<result.digits.len:
|
||||
let x = int64(result.digits[i])
|
||||
let y = if i < b.digits.len: int64(b.digits[i]) else: 0'i64
|
||||
var diff = x - y - borrow
|
||||
|
||||
if diff < 0:
|
||||
diff += 1_000_000_000
|
||||
borrow = 1
|
||||
else:
|
||||
borrow = 0
|
||||
|
||||
result.digits[i] = uint64(diff)
|
||||
|
||||
# Remove leading zeros
|
||||
while result.digits.len > 1 and result.digits[^1] == 0:
|
||||
result.digits.delete(result.digits.len - 1)
|
||||
|
||||
proc `*`(a: BigInt, b: uint64): BigInt =
|
||||
result.digits = newSeq[uint64](a.digits.len)
|
||||
var carry: uint64 = 0
|
||||
|
||||
for i in 0..<a.digits.len:
|
||||
let prod = a.digits[i] * b + carry
|
||||
result.digits[i] = prod mod 1_000_000_000
|
||||
carry = prod div 1_000_000_000
|
||||
|
||||
if carry > 0:
|
||||
result.digits.add(carry)
|
||||
|
||||
proc `div`(a: BigInt, divisor: uint64): BigInt =
|
||||
result.digits = newSeq[uint64](a.digits.len)
|
||||
var remainder: uint64 = 0
|
||||
|
||||
for i in countdown(a.digits.len - 1, 0):
|
||||
let cur = remainder * 1_000_000_000 + a.digits[i]
|
||||
result.digits[i] = cur div divisor
|
||||
remainder = cur mod divisor
|
||||
|
||||
# Remove leading zeros
|
||||
while result.digits.len > 1 and result.digits[^1] == 0:
|
||||
result.digits.delete(result.digits.len - 1)
|
||||
|
||||
proc `$`(b: BigInt): string =
|
||||
result = ""
|
||||
for i in countdown(b.digits.len - 1, 0):
|
||||
if i == b.digits.len - 1:
|
||||
result.add($b.digits[i])
|
||||
else:
|
||||
result.add(align($b.digits[i], 9, '0'))
|
||||
|
||||
proc pow10(exp: int): BigInt =
|
||||
result = initBigInt(1)
|
||||
for i in 0..<exp:
|
||||
result = result * 10'u64
|
||||
|
||||
proc arctan(x: uint64, decimals: int): BigInt =
|
||||
let scale = pow10(decimals + 10)
|
||||
let xSquared = x * x
|
||||
|
||||
var term = scale div x
|
||||
result = initBigInt(0)
|
||||
var n = 0
|
||||
|
||||
while term.digits.len > 1 or term.digits[0] > 0:
|
||||
let divisor = uint64(2 * n + 1)
|
||||
let contrib = term div divisor
|
||||
|
||||
if n mod 2 == 0:
|
||||
result = result + contrib
|
||||
else:
|
||||
result = result - contrib
|
||||
|
||||
term = term div xSquared
|
||||
n += 1
|
||||
|
||||
proc calculatePi(decimals: int): string =
|
||||
let atan1_5 = arctan(5, decimals)
|
||||
let atan1_239 = arctan(239, decimals)
|
||||
|
||||
# pi = 16*arctan(1/5) - 4*arctan(1/239)
|
||||
var pi = atan1_5 * 16'u64
|
||||
let pi4 = atan1_239 * 4'u64
|
||||
pi = pi - pi4
|
||||
|
||||
let piStr = $pi
|
||||
|
||||
# Format with decimal point
|
||||
result = "3."
|
||||
let start = 1
|
||||
var i = 0
|
||||
|
||||
while i < decimals:
|
||||
if start + i < piStr.len:
|
||||
result.add(piStr[start + i])
|
||||
else:
|
||||
result.add('0')
|
||||
i += 1
|
||||
|
||||
# Main
|
||||
let decimals = if paramCount() > 0:
|
||||
try:
|
||||
parseInt(paramStr(1))
|
||||
except:
|
||||
100
|
||||
else:
|
||||
100
|
||||
|
||||
echo calculatePi(decimals)
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
import unittest
|
||||
import osproc
|
||||
import strutils
|
||||
|
||||
const SCRIPT_PATH = "/Users/einand/Code/test/nim/print_hej"
|
||||
|
||||
proc runScript(decimals: int = -1): string =
|
||||
var cmd = SCRIPT_PATH
|
||||
if decimals >= 0:
|
||||
cmd = cmd & " " & $decimals
|
||||
|
||||
let (output, exitCode) = execCmdEx(cmd)
|
||||
result = output.strip()
|
||||
|
||||
suite "Pi calculation tests":
|
||||
test "10 decimals":
|
||||
let result = runScript(10)
|
||||
let expected = "3.1415926535"
|
||||
check result == expected
|
||||
|
||||
test "5 decimals":
|
||||
let result = runScript(5)
|
||||
let expected = "3.14159"
|
||||
check result == expected
|
||||
|
||||
test "1 decimal":
|
||||
let result = runScript(1)
|
||||
let expected = "3.1"
|
||||
check result == expected
|
||||
|
||||
test "100 decimals":
|
||||
let result = runScript(100)
|
||||
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||
check result == expected
|
||||
|
||||
test "default 100 decimals":
|
||||
let result = runScript()
|
||||
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||
check result == expected
|
||||
|
||||
test "10000 decimals":
|
||||
let result = runScript(10000)
|
||||
# Check length: "3." + 10000 digits = 10002 characters
|
||||
check len(result) == 10002
|
||||
check result.startsWith("3.14159")
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,47 @@
|
||||
import unittest
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
SCRIPT_PATH = "/Users/einand/Code/test/nim/print_hej"
|
||||
|
||||
def run_script(decimals=None):
|
||||
cmd = [SCRIPT_PATH]
|
||||
if decimals is not None:
|
||||
cmd.append(str(decimals))
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return result.stdout.strip()
|
||||
|
||||
class TestPi(unittest.TestCase):
|
||||
def test_10_decimals(self):
|
||||
result = run_script(10)
|
||||
expected = "3.1415926535"
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_5_decimals(self):
|
||||
result = run_script(5)
|
||||
expected = "3.14159"
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_1_decimal(self):
|
||||
result = run_script(1)
|
||||
expected = "3.1"
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_100_decimals(self):
|
||||
result = run_script(100)
|
||||
expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_default_100_decimals(self):
|
||||
result = run_script()
|
||||
expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_10000_decimals(self):
|
||||
result = run_script(10000)
|
||||
# Check length: "3." + 10000 digits = 10002 characters
|
||||
self.assertEqual(len(result), 10002)
|
||||
self.assertTrue(result.startswith("3.14159"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user