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
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
# Zig Build Script
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"
echo "=== Zig Build ==="
echo ""
# Kompilera Zig-programmet
cd src
zig build-exe print_hej.zig -femit-bin=../bin/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
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# Zig Unit Tests
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$SCRIPT_DIR"
echo "=== Zig Pi-beräkning Unit Tester ==="
echo ""
cd src
zig test pi_test.zig
exit $?
+82
View File
@@ -0,0 +1,82 @@
const std = @import("std");
const process = std.process;
const mem = std.mem;
const SCRIPT_PATH = "/Users/einand/Code/test/zig/print_hej";
fn runScript(allocator: mem.Allocator, args: ?[]const u8) ![]u8 {
var argv = std.ArrayList([]const u8).initCapacity(allocator, 2) catch unreachable;
defer argv.deinit();
argv.appendAssumeCapacity(SCRIPT_PATH);
if (args) |a| {
argv.appendAssumeCapacity(a);
}
var child = process.Child.run(.{
.allocator = allocator,
.argv = argv.items,
}) catch unreachable;
// Remove trailing newline
if (child.stdout.len > 0 and child.stdout[child.stdout.len - 1] == '\n') {
return child.stdout[0 .. child.stdout.len - 1];
}
return child.stdout;
}
test "10 decimals" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, "10");
defer allocator.free(result);
const expected = "3.1415926535";
try std.testing.expectEqualStrings(expected, result);
}
test "5 decimals" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, "5");
defer allocator.free(result);
const expected = "3.14159";
try std.testing.expectEqualStrings(expected, result);
}
test "1 decimal" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, "1");
defer allocator.free(result);
const expected = "3.1";
try std.testing.expectEqualStrings(expected, result);
}
test "100 decimals" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, "100");
defer allocator.free(result);
const expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
try std.testing.expectEqualStrings(expected, result);
}
test "default 100 decimals" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, null);
defer allocator.free(result);
const expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
try std.testing.expectEqualStrings(expected, result);
}
test "10000 decimals" {
const allocator = std.testing.allocator;
const result = try runScript(allocator, "10000");
defer allocator.free(result);
// Check length: "3." + 10000 digits = 10002 characters
try std.testing.expectEqual(@as(usize, 10002), result.len);
try std.testing.expect(mem.startsWith(u8, result, "3.14159"));
}
+233
View File
@@ -0,0 +1,233 @@
const std = @import("std");
pub fn main(init: std.process.Init) !void {
var args_iter = std.process.Args.Iterator.init(init.minimal.args);
_ = args_iter.skip();
const decimals: usize = if (args_iter.next()) |arg_str|
std.fmt.parseInt(usize, arg_str, 10) catch 100
else
100;
const pi = try calculatePi(init.gpa, decimals);
defer init.gpa.free(pi);
try std.Io.File.writeStreamingAll(.stdout(), init.io, pi);
try std.Io.File.writeStreamingAll(.stdout(), init.io, "\n");
}
// Simple BigInt using array of u32 (base 10^9)
const BigInt = struct {
digits: []u32,
len: usize,
allocator: std.mem.Allocator,
fn init(allocator: std.mem.Allocator, size: usize) !BigInt {
const digits = try allocator.alloc(u32, size);
@memset(digits, 0);
return .{ .digits = digits, .len = 1, .allocator = allocator };
}
fn deinit(self: *BigInt) void {
self.allocator.free(self.digits);
}
fn set(self: *BigInt, value: u32) void {
@memset(self.digits, 0);
self.digits[0] = value;
self.len = 1;
}
fn copyFrom(self: *BigInt, other: *const BigInt) void {
@memcpy(self.digits[0..other.len], other.digits[0..other.len]);
self.len = other.len;
}
fn add(self: *BigInt, other: *const BigInt) void {
var carry: u32 = 0;
var i: usize = 0;
const max_len = @max(self.len, other.len);
while (i < max_len or carry > 0) : (i += 1) {
const a = if (i < self.len) self.digits[i] else 0;
const b = if (i < other.len) other.digits[i] else 0;
const sum = a + b + carry;
self.digits[i] = sum % 1000000000;
carry = sum / 1000000000;
}
self.len = i;
}
fn sub(self: *BigInt, other: *const BigInt) void {
var borrow: i32 = 0;
var i: usize = 0;
while (i < self.len) : (i += 1) {
const a: i64 = @as(i64, self.digits[i]);
const b: i64 = if (i < other.len) @as(i64, other.digits[i]) else 0;
var diff = a - b - borrow;
if (diff < 0) {
diff += 1000000000;
borrow = 1;
} else {
borrow = 0;
}
self.digits[i] = @as(u32, @intCast(diff));
}
while (self.len > 1 and self.digits[self.len - 1] == 0) {
self.len -= 1;
}
}
fn mulSmall(self: *BigInt, multiplier: u32) void {
var carry: u64 = 0;
var i: usize = 0;
while (i < self.len or carry > 0) : (i += 1) {
const prod = @as(u64, self.digits[i]) * @as(u64, multiplier) + carry;
self.digits[i] = @as(u32, @intCast(prod % 1000000000));
carry = prod / 1000000000;
}
self.len = i;
}
fn divSmall(self: *BigInt, divisor: u32) void {
var remainder: u64 = 0;
var i: usize = self.len;
while (i > 0) {
i -= 1;
const cur = remainder * 1000000000 + @as(u64, self.digits[i]);
self.digits[i] = @as(u32, @intCast(cur / @as(u64, divisor)));
remainder = cur % @as(u64, divisor);
}
while (self.len > 1 and self.digits[self.len - 1] == 0) {
self.len -= 1;
}
}
fn isZero(self: *const BigInt) bool {
return self.len == 1 and self.digits[0] == 0;
}
};
fn calculatePi(allocator: std.mem.Allocator, decimals: usize) ![]u8 {
const num_digits = (decimals + 10) / 9 + 10;
const atan1_5 = try arctanBigInt(allocator, 5, decimals, num_digits);
defer allocator.free(atan1_5);
const atan1_239 = try arctanBigInt(allocator, 239, decimals, num_digits);
defer allocator.free(atan1_239);
return formatPiBigInt(allocator, atan1_5, atan1_239, decimals, num_digits);
}
fn arctanBigInt(allocator: std.mem.Allocator, x: u32, decimals: usize, num_digits: usize) ![]u32 {
var term = try BigInt.init(allocator, num_digits);
defer term.deinit();
var result = try BigInt.init(allocator, num_digits);
defer result.deinit();
var temp = try BigInt.init(allocator, num_digits);
defer temp.deinit();
term.set(1);
var i: usize = 0;
while (i < decimals + 10) : (i += 9) {
term.mulSmall(1000000000);
}
term.divSmall(x);
var n: usize = 0;
const x_squared = x * x;
while (!term.isZero() and n < decimals * 2) : (n += 1) {
const divisor: u32 = @intCast(2 * n + 1);
temp.copyFrom(&term);
temp.divSmall(divisor);
if (n % 2 == 0) {
result.add(&temp);
} else {
result.sub(&temp);
}
term.divSmall(x_squared);
}
const output = try allocator.alloc(u32, result.len);
@memcpy(output, result.digits[0..result.len]);
return output;
}
fn formatPiBigInt(allocator: std.mem.Allocator, atan1_5: []const u32, atan1_239: []const u32, decimals: usize, num_digits: usize) ![]u8 {
var result_big = try BigInt.init(allocator, num_digits);
defer result_big.deinit();
var temp = try BigInt.init(allocator, num_digits);
defer temp.deinit();
@memcpy(result_big.digits[0..atan1_5.len], atan1_5[0..atan1_5.len]);
result_big.len = atan1_5.len;
result_big.mulSmall(16);
@memcpy(temp.digits[0..atan1_239.len], atan1_239[0..atan1_239.len]);
temp.len = atan1_239.len;
temp.mulSmall(4);
result_big.sub(&temp);
return formatBigInt(allocator, &result_big, decimals);
}
fn formatBigInt(allocator: std.mem.Allocator, num: *BigInt, decimals: usize) ![]u8 {
var result = try allocator.alloc(u8, decimals + 2);
const first_digit = num.digits[num.len - 1];
var temp_buf: [20]u8 = undefined;
const first_str = try std.fmt.bufPrint(&temp_buf, "{}", .{first_digit});
if (first_str.len > 0) {
result[0] = first_str[0];
} else {
result[0] = 48;
}
result[1] = 46;
var pos: usize = 2;
if (first_str.len > 1) {
var j: usize = 1;
while (j < first_str.len and pos < decimals + 2) : (j += 1) {
result[pos] = first_str[j];
pos += 1;
}
}
if (num.len > 1) {
var i: usize = num.len - 2;
while (true) : (i -= 1) {
const group = num.digits[i];
const group_str = try std.fmt.bufPrint(&temp_buf, "{d:09}", .{group});
var j: usize = 0;
while (j < group_str.len and pos < decimals + 2) : (j += 1) {
result[pos] = group_str[j];
pos += 1;
}
if (i == 0) break;
}
}
while (pos < decimals + 2) : (pos += 1) {
result[pos] = 48;
}
return result;
}