diff options
Diffstat (limited to 'src/solar.rs')
| -rw-r--r-- | src/solar.rs | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/src/solar.rs b/src/solar.rs index 4bff33a..1266a23 100644 --- a/src/solar.rs +++ b/src/solar.rs @@ -8,7 +8,7 @@ use num::cast; use std::{ marker::Freeze, mem::{transmute, MaybeUninit}, - ops::{Div, Rem}, + ops::{Div, Index, IndexMut, Rem}, sync::LazyLock, }; @@ -192,34 +192,40 @@ where align(6 * g - 5 * z, 60, 0) } +// need to do this because +// 1. unsafecell doesnt implement Sync +// 2. mutating a slice directly will put it in .rodata for normal targets +// where i test this on struct Cell<T: ?Sized> { val: T, } -impl<T: ?Sized> Cell<T> { - pub fn get(&self) -> &mut T { - unsafe { transmute(&self.val) } - } -} +// SAFETY(lol): wasm isolates are single-core. unsafe impl<T: ?Sized + Send> Sync for Cell<T> {} // technically i dont need this because wasm mutable globals are enabled, // and Freeze is only needed for targets with a separate .rodata // i dont really care either way but this is how UnsafeCell does it +// // lang = "unsafe_cell" (apparently an extremely integral part of rust) // does additional stuff but this is sufficient for the compiler to not -// put it on .rodata for normal targets +// put it in .rodata for normal targets impl<T: ?Sized> !Freeze for Cell<T> {} +impl<T: ?Sized + IndexMut<usize> + Index<usize>> Cell<T> { + pub fn get(&self, i: usize) -> &mut T::Output { + // SAFETY: see above + let a: &mut T = unsafe { transmute(&self.val) }; + &mut a[i] + } +} fn stday(i: usize, y: usize) -> f64 { const YEARS: usize = 200; const ARRLEN: usize = YEARS * TERMS.len(); - static STDAYS: Cell<[f64; ARRLEN]> = Cell { - val: [0.; ARRLEN], - }; // rust doesnt have (*a)[n], | @ least ill have2 use a cr8 4 it // also lazy_static doesnt work with mutables (im not using mutex) - assert!((UNIT_YR..UNIT_YR + YEARS).contains(&y)); + static STDAYS: Cell<[f64; ARRLEN]> = Cell { val: [0.; ARRLEN] }; let idx = y - UNIT_YR; - let ret = &mut STDAYS.get()[idx * TERMS.len() + i]; + assert!((0..YEARS).contains(&idx)); + let ret = STDAYS.get(idx * TERMS.len() + i); (if int(*ret) != 0 { *ret } else { @@ -239,15 +245,10 @@ pub fn ganzhi(i: usize) -> &'static str { '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', ]; - let mut tmp: Vec<String> = Vec::with_capacity(60); - (0..60).for_each(|i| { - // looks so much worse than using format!() - // cant be bothered to benchmark - let mut s = gan[i % 10].to_string(); - s.push(zhi[i % 12]); - tmp.push(s); - }); - tmp + (0..60).fold(Vec::with_capacity(60), |mut v, i| { + v.push([gan[i % 10], zhi[i % 12]].iter().collect()); + v + }) }); &GANZHIS[i] } @@ -271,6 +272,7 @@ pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate { let div = int(a.div(15.).floor()); let mut dz = align(div.div_ceil(2), 12, 9); let mut termb = rem > 14.; + // SAFETY: guarded by termb let mut term: usize = unsafe { MaybeUninit::uninit().assume_init() }; if termb { term = align(div, 24, 18); |
