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
|
||||
|
||||
# C Build Script
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== C Build ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera C-programmet med GMP
|
||||
gcc -I/opt/homebrew/opt/gmp/include -L/opt/homebrew/opt/gmp/lib -o bin/print_hej src/print_hej.c -lgmp
|
||||
|
||||
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
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# C Unit Tests
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== C Pi-beräkning Unit Tester ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera och kör pi_test
|
||||
gcc -o bin/pi_test src/pi_test.c -lgmp
|
||||
if [ $? -eq 0 ]; then
|
||||
./bin/pi_test
|
||||
exit $?
|
||||
else
|
||||
echo "✗ Kompilering av tester misslyckades!"
|
||||
exit 1
|
||||
fi
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define SCRIPT_PATH "/Users/einand/Code/test/c/print_hej"
|
||||
|
||||
char* run_script(const char* args) {
|
||||
char cmd[256];
|
||||
if (args && strlen(args) > 0) {
|
||||
snprintf(cmd, sizeof(cmd), "%s %s", SCRIPT_PATH, args);
|
||||
} else {
|
||||
snprintf(cmd, sizeof(cmd), "%s", SCRIPT_PATH);
|
||||
}
|
||||
|
||||
FILE* pipe = popen(cmd, "r");
|
||||
if (!pipe) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* result = malloc(100000);
|
||||
if (!result) {
|
||||
pclose(pipe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fgets(result, 100000, pipe) == NULL) {
|
||||
free(result);
|
||||
pclose(pipe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Remove trailing newline
|
||||
size_t len = strlen(result);
|
||||
if (len > 0 && result[len-1] == '\n') {
|
||||
result[len-1] = '\0';
|
||||
}
|
||||
|
||||
pclose(pipe);
|
||||
return result;
|
||||
}
|
||||
|
||||
void test_10_decimals() {
|
||||
char* result = run_script("10");
|
||||
const char* expected = "3.1415926535";
|
||||
assert(strcmp(result, expected) == 0);
|
||||
printf("✓ Test 10 decimals passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
void test_5_decimals() {
|
||||
char* result = run_script("5");
|
||||
const char* expected = "3.14159";
|
||||
assert(strcmp(result, expected) == 0);
|
||||
printf("✓ Test 5 decimals passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
void test_1_decimal() {
|
||||
char* result = run_script("1");
|
||||
const char* expected = "3.1";
|
||||
assert(strcmp(result, expected) == 0);
|
||||
printf("✓ Test 1 decimal passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
void test_100_decimals() {
|
||||
char* result = run_script("100");
|
||||
const char* expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
assert(strcmp(result, expected) == 0);
|
||||
printf("✓ Test 100 decimals passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
void test_default_100_decimals() {
|
||||
char* result = run_script("");
|
||||
const char* expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
assert(strcmp(result, expected) == 0);
|
||||
printf("✓ Test default 100 decimals passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
void test_10000_decimals() {
|
||||
char* result = run_script("10000");
|
||||
// Check length: "3." + 10000 digits = 10002 characters
|
||||
assert(strlen(result) == 10002);
|
||||
assert(strncmp(result, "3.14159", 7) == 0);
|
||||
printf("✓ Test 10000 decimals passed\n");
|
||||
free(result);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Running C unit tests...\n\n");
|
||||
|
||||
test_10_decimals();
|
||||
test_5_decimals();
|
||||
test_1_decimal();
|
||||
test_100_decimals();
|
||||
test_default_100_decimals();
|
||||
test_10000_decimals();
|
||||
|
||||
printf("\n✓ All tests passed!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gmp.h>
|
||||
|
||||
// Calculate arctan(1/x) using Taylor series
|
||||
// arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ...
|
||||
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);
|
||||
|
||||
// Scale factor: 10^(decimals + 10) for precision
|
||||
mpz_t scale;
|
||||
mpz_init(scale);
|
||||
mpz_ui_pow_ui(scale, 10, decimals + 10);
|
||||
|
||||
// x_squared = x * x
|
||||
mpz_set_ui(x_squared, x);
|
||||
mpz_mul_ui(x_squared, x_squared, x);
|
||||
|
||||
// term = scale / x (first term: 1/x)
|
||||
mpz_fdiv_q_ui(term, scale, x);
|
||||
|
||||
// result = 0
|
||||
mpz_set_ui(result, 0);
|
||||
|
||||
// Iterate through Taylor series
|
||||
unsigned long n = 0;
|
||||
int sign = 1;
|
||||
|
||||
while (mpz_cmp_ui(term, 0) != 0 && n < decimals * 3) {
|
||||
// Divide by (2n+1)
|
||||
mpz_fdiv_q_ui(contrib, term, 2 * n + 1);
|
||||
|
||||
if (sign > 0) {
|
||||
mpz_add(result, result, contrib);
|
||||
} else {
|
||||
mpz_sub(result, result, contrib);
|
||||
}
|
||||
|
||||
// Next term: divide by x^2
|
||||
mpz_fdiv_q(term, term, x_squared);
|
||||
|
||||
// Alternate sign
|
||||
sign = -sign;
|
||||
n++;
|
||||
|
||||
// Stop when term becomes negligible
|
||||
if (n > decimals * 2) break;
|
||||
}
|
||||
|
||||
mpz_clear(term);
|
||||
mpz_clear(x_squared);
|
||||
mpz_clear(contrib);
|
||||
mpz_clear(scale);
|
||||
}
|
||||
|
||||
void calculate_pi(mpz_t result, unsigned long decimals) {
|
||||
mpz_t arctan_1_5, arctan_1_239;
|
||||
mpz_init(arctan_1_5);
|
||||
mpz_init(arctan_1_239);
|
||||
|
||||
// Calculate arctan(1/5)
|
||||
arctan(arctan_1_5, 5, decimals);
|
||||
|
||||
// Calculate arctan(1/239)
|
||||
arctan(arctan_1_239, 239, decimals);
|
||||
|
||||
// pi/4 = 4*arctan(1/5) - arctan(1/239)
|
||||
// pi = 16*arctan(1/5) - 4*arctan(1/239)
|
||||
mpz_mul_ui(arctan_1_5, arctan_1_5, 16);
|
||||
mpz_mul_ui(arctan_1_239, arctan_1_239, 4);
|
||||
mpz_sub(result, arctan_1_5, arctan_1_239);
|
||||
|
||||
mpz_clear(arctan_1_5);
|
||||
mpz_clear(arctan_1_239);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned long decimals = 100;
|
||||
|
||||
if (argc > 1) {
|
||||
decimals = strtoul(argv[1], NULL, 10);
|
||||
if (decimals == 0) {
|
||||
decimals = 100;
|
||||
}
|
||||
}
|
||||
|
||||
mpz_t pi;
|
||||
mpz_init(pi);
|
||||
|
||||
calculate_pi(pi, decimals);
|
||||
|
||||
// Convert to string
|
||||
char *pi_str = mpz_get_str(NULL, 10, pi);
|
||||
size_t len = strlen(pi_str);
|
||||
|
||||
// Print with decimal point
|
||||
if (len > 0) {
|
||||
putchar('3');
|
||||
if (decimals > 0) {
|
||||
putchar('.');
|
||||
// Print decimals, skipping the leading "3"
|
||||
size_t start = 1;
|
||||
size_t end = start + decimals;
|
||||
if (end > len) end = len;
|
||||
for (size_t i = start; i < end && i < len; i++) {
|
||||
putchar(pi_str[i]);
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
free(pi_str);
|
||||
mpz_clear(pi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user