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:
Ein Anderssono
2026-04-23 00:26:18 +02:00
commit 54d2fecee0
182 changed files with 17471 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "print_hej",
targets: [
.executableTarget(
name: "print_hej",
path: "."),
.testTarget(
name: "PiTests",
dependencies: ["print_hej"],
path: "."),
]
)
+75
View File
@@ -0,0 +1,75 @@
import XCTest
@testable import print_hej
class PiTests: XCTestCase {
let scriptPath = "/Users/einand/Code/test/swift/print_hej"
func runScript(_ args: String? = nil) -> String {
let process = Process()
process.executableURL = URL(fileURLWithPath: scriptPath)
if let args = args {
process.arguments = [args]
}
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe
do {
try process.run()
process.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
return String(data: data, encoding: .utf8)?.trimmingCharacters(in: .newlines) ?? ""
} catch {
return ""
}
}
func test10Decimals() {
let result = runScript("10")
let expected = "3.1415926535"
XCTAssertEqual(result, expected)
}
func test5Decimals() {
let result = runScript("5")
let expected = "3.14159"
XCTAssertEqual(result, expected)
}
func test1Decimal() {
let result = runScript("1")
let expected = "3.1"
XCTAssertEqual(result, expected)
}
func test100Decimals() {
let result = runScript("100")
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
XCTAssertEqual(result, expected)
}
func testDefault100Decimals() {
let result = runScript()
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
XCTAssertEqual(result, expected)
}
func test10000Decimals() {
let result = runScript("10000")
// Check length: "3." + 10000 digits = 10002 characters
XCTAssertEqual(result.count, 10002)
XCTAssertTrue(result.hasPrefix("3.14159"))
}
static var allTests = [
("test10Decimals", test10Decimals),
("test5Decimals", test5Decimals),
("test1Decimal", test1Decimal),
("test100Decimals", test100Decimals),
("testDefault100Decimals", testDefault100Decimals),
("test10000Decimals", test10000Decimals),
]
}
+196
View File
@@ -0,0 +1,196 @@
import Foundation
// Simple BigInt implementation for arbitrary precision
class BigInt {
var digits: [UInt64]
init(_ value: Int = 0) {
if value == 0 {
digits = [0]
} else {
digits = [UInt64(abs(value))]
}
}
init(_ value: UInt64) {
digits = [value]
}
func add(_ other: BigInt) {
var carry: UInt64 = 0
let maxLen = max(digits.count, other.digits.count)
for i in 0..<maxLen {
let a = i < digits.count ? digits[i] : 0
let b = i < other.digits.count ? other.digits[i] : 0
let sum = a + b + carry
if i < digits.count {
digits[i] = sum % 1_000_000_000
} else {
digits.append(sum % 1_000_000_000)
}
carry = sum / 1_000_000_000
}
if carry > 0 {
digits.append(carry)
}
}
func subtract(_ other: BigInt) {
var borrow: Int64 = 0
for i in 0..<digits.count {
let a = Int64(digits[i])
let b = i < other.digits.count ? Int64(other.digits[i]) : 0
var diff = a - b - borrow
if diff < 0 {
diff += 1_000_000_000
borrow = 1
} else {
borrow = 0
}
digits[i] = UInt64(diff)
}
// Remove leading zeros
while digits.count > 1 && digits.last! == 0 {
digits.removeLast()
}
}
func multiply(_ other: BigInt) -> BigInt {
let result = BigInt()
result.digits = Array(repeating: 0, count: digits.count + other.digits.count)
for i in 0..<digits.count {
var carry: UInt64 = 0
for j in 0..<other.digits.count {
let prod = digits[i] * other.digits[j] + result.digits[i + j] + carry
result.digits[i + j] = prod % 1_000_000_000
carry = prod / 1_000_000_000
}
if carry > 0 {
result.digits[i + other.digits.count] += carry
}
}
// Remove leading zeros
while result.digits.count > 1 && result.digits.last! == 0 {
result.digits.removeLast()
}
return result
}
func divide(_ divisor: UInt64) -> BigInt {
let result = BigInt()
result.digits = Array(repeating: 0, count: digits.count)
var remainder: UInt64 = 0
for i in (0..<digits.count).reversed() {
let cur = remainder * 1_000_000_000 + digits[i]
result.digits[i] = cur / divisor
remainder = cur % divisor
}
// Remove leading zeros
while result.digits.count > 1 && result.digits.last! == 0 {
result.digits.removeLast()
}
return result
}
func toString() -> String {
var result = ""
for i in (0..<digits.count).reversed() {
if i == digits.count - 1 {
result += String(digits[i])
} else {
result += String(format: "%09d", digits[i])
}
}
return result
}
}
func pow10(_ exp: Int) -> BigInt {
let result = BigInt(1)
for _ in 0..<exp {
let temp = result.multiply(BigInt(10))
result.digits = temp.digits
}
return result
}
func arctan(_ x: UInt64, decimals: Int) -> BigInt {
let scale = pow10(decimals + 10)
let xSquared = x * x
var term = scale.divide(x)
var result = BigInt(0)
var n = 0
while term.digits.count > 1 || term.digits[0] > 0 {
let divisor = UInt64(2 * n + 1)
let contrib = term.divide(divisor)
if n % 2 == 0 {
result.add(contrib)
} else {
result.subtract(contrib)
}
term = term.divide(xSquared)
n += 1
}
return result
}
func calculatePi(_ decimals: Int) -> String {
let atan1_5 = arctan(5, decimals: decimals)
let atan1_239 = arctan(239, decimals: decimals)
// pi = 16*arctan(1/5) - 4*arctan(1/239)
let pi16 = atan1_5.multiply(BigInt(16))
let pi4 = atan1_239.multiply(BigInt(4))
pi16.subtract(pi4)
let piStr = pi16.toString()
// Format with decimal point
var result = "3."
let start = piStr.index(piStr.startIndex, offsetBy: 1)
let digits = piStr[start...]
var i = 0
for char in digits {
if i >= decimals { break }
result.append(char)
i += 1
}
// Pad with zeros if needed
while i < decimals {
result.append("0")
i += 1
}
return result
}
// Main
let decimals: Int
if CommandLine.arguments.count > 1 {
decimals = Int(CommandLine.arguments[1]) ?? 100
} else {
decimals = 100
}
let pi = calculatePi(decimals)
print(pi)