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.. 0 { append(&a.digits, carry) } } big_int_sub :: proc(a: ^BigInt, b: BigInt) { borrow: i64 = 0 for i in 0.. 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.. 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.. 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.. BigInt { result := big_int_init(1) for i in 0.. 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) }