Created
March 14, 2025 18:24
-
-
Save FranchuFranchu/a0bc75272b9ee5cad47ec1ddd2dd5276 to your computer and use it in GitHub Desktop.
A parallel Pi approximator in Vine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::numeric::F32; | |
use std::ops::Cast; | |
use std::unicode::ToString; | |
struct Decimal { | |
m_sign: Bool, | |
mantissa: N32, | |
e_sign: Bool, | |
exponent: N32, | |
} | |
mod Decimal { | |
pub fn .times10(self: Decimal) -> Decimal { | |
if self.e_sign && self.exponent > 0 { | |
self.exponent -= 1 | |
} else if !self.e_sign { | |
self.exponent += 1 | |
} else { | |
self.e_sign = false | |
self.exponent += 1 | |
} | |
self | |
} | |
pub fn .divide10(self: Decimal) -> Decimal { | |
if !self.e_sign && self.exponent > 0 { | |
self.exponent -= 1 | |
} else if self.e_sign { | |
self.exponent += 1 | |
} else { | |
self.e_sign = true | |
self.exponent += 1 | |
} | |
self | |
} | |
pub fn .with_m(self: Decimal, m: N32) -> Decimal { | |
self.mantissa = m | |
self | |
} | |
pub fn .with_m_sign(self: Decimal, m: Bool) -> Decimal { | |
self.m_sign = m | |
self | |
} | |
} | |
pub impl to_string: ToString[Decimal] { | |
fn .to_string(self: Decimal) -> String { | |
self.mantissa.to_string() ++ "e" ++ if self.e_sign { "-" } else { "" } ++ self.exponent.to_string() | |
} | |
} | |
fn from_decimal(decimal: Decimal) -> F32 { | |
let num: F32 = decimal.mantissa.cast[N32, F32](); | |
let fact = if !decimal.e_sign { 10.0 } else { 1.0 / 10.0 }; | |
while decimal.exponent > 0 { | |
decimal.exponent -= 1 | |
num *= fact | |
} | |
num | |
} | |
fn is_between(a: F32, b: Decimal, c: Decimal) -> Bool { | |
a.lt(from_decimal(c)) && a.gt(from_decimal(b)) | |
} | |
pub fn approximate(&io: &IO, num: F32, prec: F32) -> Decimal { | |
let candidate = Decimal({ | |
m_sign: num.lt(0.0), | |
mantissa: 1, | |
e_sign: false, | |
exponent: 0, | |
}) | |
// tweak exponent | |
loop { | |
if num.lt(from_decimal(candidate)) { | |
candidate = candidate.divide10() | |
} else if num.gt(from_decimal(candidate.times10())) { | |
candidate = candidate.times10() | |
} else { | |
break; | |
} | |
} | |
// tweak mantissa | |
io.println(candidate.to_string()) | |
loop { | |
io.println(candidate.to_string()) | |
loop { | |
if num.lt(from_decimal(candidate)) { | |
candidate.mantissa -= 1 | |
} else if num.gt(from_decimal(candidate.with_m(candidate.mantissa + 1))) { | |
candidate.mantissa += 1 | |
} else { | |
break; | |
} | |
} | |
candidate = candidate.divide10() | |
if prec.gt(from_decimal(candidate.with_m(10).with_m_sign(false))) { | |
break; | |
} | |
} | |
candidate | |
} | |
pub fn f32_to_string(&io: &IO, num: F32, prec: F32) -> String { | |
approximate(&io, num, prec).to_string() | |
} | |
pub fn approximate_pi(steps: N32) -> F32 { | |
let approximation = 0.0; | |
let denom = 1.0; | |
let num = 4.0; | |
while steps > 0 { | |
approximation += num / denom | |
num *= -1.0 | |
denom += 2.0 | |
steps -= 1 | |
} | |
approximation | |
} | |
pub fn approximate_pi_bisect(start: N32, end: N32) -> F32 { | |
let len = end - start | |
if len == 0 { | |
return 0.0 | |
} else if len == 1 { | |
let num = if start % 2 == 0 { | |
4.0 | |
} else { | |
-4.0 | |
} | |
let denom = start.cast[N32, F32]() * 2.0 + 1.0 | |
return num / denom | |
} else { | |
approximate_pi_bisect(start, start + len / 2) + approximate_pi_bisect(start + len / 2, end) | |
} | |
} | |
pub fn main(&io: &IO) { | |
io.println("Calculating PI..."); | |
let approx = approximate_pi_bisect(0, 30000000) | |
io.println("Calculated PI. Now stringifying"); | |
f32_to_string(&io, approx, 0.00001); | |
io.println("Happy PI day!"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment