Files
print_hej/odin/src/print_hej.odin
T
Ein Anderssono 54d2fecee0 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
2026-04-23 00:26:18 +02:00

228 lines
5.4 KiB
Odin

package main
import "core:fmt"
import "core:os"
import "core:strings"
import "core:strconv"
// Simple BigInt implementation using base 10^9
BigInt :: struct {
digits: [dynamic]u64,
}
big_int_init :: proc(value: u64) -> BigInt {
result: BigInt
if value == 0 {
append(&result.digits, 0)
} else {
append(&result.digits, value)
}
return result
}
big_int_add :: proc(a: ^BigInt, b: BigInt) {
carry: u64 = 0
max_len := max(len(a.digits), len(b.digits))
for i in 0..<max_len {
x := a.digits[i] if i < len(a.digits) else 0
y := b.digits[i] if i < len(b.digits) else 0
sum := x + y + carry
if i < len(a.digits) {
a.digits[i] = sum % 1_000_000_000
} else {
append(&a.digits, sum % 1_000_000_000)
}
carry = sum / 1_000_000_000
}
if carry > 0 {
append(&a.digits, carry)
}
}
big_int_sub :: proc(a: ^BigInt, b: BigInt) {
borrow: i64 = 0
for i in 0..<len(a.digits) {
x := i64(a.digits[i])
y := i64(b.digits[i]) if i < len(b.digits) else 0
diff := x - y - borrow
if diff < 0 {
diff += 1_000_000_000
borrow = 1
} else {
borrow = 0
}
a.digits[i] = u64(diff)
}
// Remove leading zeros
for len(a.digits) > 1 && a.digits[len(a.digits) - 1] == 0 {
pop(&a.digits)
}
}
big_int_mul :: proc(a: BigInt, b: u64) -> BigInt {
result: BigInt
resize(&result.digits, len(a.digits))
carry: u64 = 0
for i in 0..<len(a.digits) {
prod := a.digits[i] * b + carry
result.digits[i] = prod % 1_000_000_000
carry = prod / 1_000_000_000
}
if carry > 0 {
append(&result.digits, carry)
}
return result
}
big_int_div :: proc(a: BigInt, divisor: u64) -> BigInt {
result: BigInt
resize(&result.digits, len(a.digits))
remainder: u64 = 0
for i in 0..<len(a.digits) {
j := len(a.digits) - 1 - i
cur := remainder * 1_000_000_000 + a.digits[j]
result.digits[j] = cur / divisor
remainder = cur % divisor
}
// Remove leading zeros
for len(result.digits) > 1 && result.digits[len(result.digits) - 1] == 0 {
pop(&result.digits)
}
return result
}
big_int_is_zero :: proc(a: BigInt) -> bool {
return len(a.digits) == 1 && a.digits[0] == 0
}
big_int_to_string :: proc(a: BigInt) -> string {
// Build string using dynamic array of bytes
result_bytes: [dynamic]u8
// Print digits from most significant to least significant
for i in 0..<len(a.digits) {
j := len(a.digits) - 1 - i
if j == len(a.digits) - 1 {
// Most significant digit - print without leading zeros
digit_str := fmt.aprintf("{}", a.digits[j])
append(&result_bytes, digit_str)
} else {
// Other digits - print with leading zeros to fill 9 positions
digit_str := fmt.aprintf("{}", a.digits[j])
// Pad with leading zeros if needed
for k in len(digit_str)..<9 {
append(&result_bytes, '0')
}
append(&result_bytes, digit_str)
}
}
return string(result_bytes[:])
}
pow10 :: proc(exp: int) -> BigInt {
result := big_int_init(1)
for i in 0..<exp {
temp := big_int_mul(result, 10)
result = temp
}
return result
}
arctan :: proc(x: u64, decimals: int) -> BigInt {
// Use base 10^9 for efficiency
num_digits := (decimals + 10) / 9 + 10
result := big_int_init(0)
term := big_int_init(1)
// Initialize term = 10^(decimals+10) / x
for i in 0..<(decimals + 10) {
temp := big_int_mul(term, 10)
term = temp
}
term = big_int_div(term, x)
x_squared := x * x
n: int = 0
for !big_int_is_zero(term) && n < decimals * 2 {
divisor := u64(2 * n + 1)
contrib := big_int_div(term, divisor)
if n % 2 == 0 {
big_int_add(&result, contrib)
} else {
big_int_sub(&result, contrib)
}
term = big_int_div(term, x_squared)
n += 1
}
return result
}
calculate_pi :: proc(decimals: int) -> string {
atan1_5 := arctan(5, decimals)
atan1_239 := arctan(239, decimals)
// pi = 16*arctan(1/5) - 4*arctan(1/239)
pi16 := big_int_mul(atan1_5, 16)
pi4 := big_int_mul(atan1_239, 4)
big_int_sub(&pi16, pi4)
pi_str := big_int_to_string(pi16)
// Format with decimal point using dynamic array of bytes
result_bytes: [dynamic]u8
// First digit before decimal point
if len(pi_str) > 0 {
append(&result_bytes, pi_str[0])
} else {
append(&result_bytes, '3')
}
append(&result_bytes, '.')
// Remaining digits after decimal point
for i in 1..<(len(pi_str)) {
if i <= decimals {
append(&result_bytes, pi_str[i])
}
}
// Pad with zeros if needed
for i in len(pi_str)..<(decimals + 1) {
append(&result_bytes, '0')
}
return string(result_bytes[:])
}
main :: proc() {
decimals: int = 100
if len(os.args) > 1 {
val, ok := strconv.parse_int(os.args[1])
if ok {
decimals = int(val)
}
}
pi := calculate_pi(decimals)
fmt.println(pi)
}