Skip to content

Instantly share code, notes, and snippets.

@FranchuFranchu
Created March 14, 2025 18:24
Show Gist options
  • Save FranchuFranchu/a0bc75272b9ee5cad47ec1ddd2dd5276 to your computer and use it in GitHub Desktop.
Save FranchuFranchu/a0bc75272b9ee5cad47ec1ddd2dd5276 to your computer and use it in GitHub Desktop.
A parallel Pi approximator in Vine
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