summaryrefslogtreecommitdiff
path: root/src/solar.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/solar.rs')
-rw-r--r--src/solar.rs91
1 files changed, 52 insertions, 39 deletions
diff --git a/src/solar.rs b/src/solar.rs
index 3cf0c95..4bff33a 100644
--- a/src/solar.rs
+++ b/src/solar.rs
@@ -6,7 +6,8 @@
// based on https://prospertimes.neocities.org/solarterms.js
use num::cast;
use std::{
- mem::MaybeUninit,
+ marker::Freeze,
+ mem::{transmute, MaybeUninit},
ops::{Div, Rem},
sync::LazyLock,
};
@@ -191,50 +192,63 @@ where
align(6 * g - 5 * z, 60, 0)
}
+struct Cell<T: ?Sized> {
+ val: T,
+}
+impl<T: ?Sized> Cell<T> {
+ pub fn get(&self) -> &mut T {
+ unsafe { transmute(&self.val) }
+ }
+}
+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
+impl<T: ?Sized> !Freeze for Cell<T> {}
+
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)
- static mut STDAYS: Vec<f64> = vec![];
- static mut INIT: bool = false;
- assert!((UNIT_YR..YEARS + UNIT_YR).contains(&y));
- unsafe {
- if !INIT {
- STDAYS = vec![0.; YEARS * TERMS.len()];
- INIT = true;
- }
- let idx = y - UNIT_YR;
- let ret = &mut STDAYS[idx * TERMS.len() + i];
- (if int(*ret) != 0 {
- *ret
- } else {
- let d = compute_solarterm_day(i, y);
- *ret = d;
- d
- })
- .floor()
- }
+ assert!((UNIT_YR..UNIT_YR + YEARS).contains(&y));
+ let idx = y - UNIT_YR;
+ let ret = &mut STDAYS.get()[idx * TERMS.len() + i];
+ (if int(*ret) != 0 {
+ *ret
+ } else {
+ let d = compute_solarterm_day(i, y);
+ *ret = d;
+ d
+ })
+ .floor()
}
-static GANZHIS: LazyLock<Vec<String>> = LazyLock::new(|| {
- const gan: [char; 10] =
- ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
- const zhi: [char; 12] = [
- '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥',
- ];
- 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
-});
-
#[must_use]
pub fn ganzhi(i: usize) -> &'static str {
+ static GANZHIS: LazyLock<Vec<String>> = LazyLock::new(|| {
+ const gan: [char; 10] =
+ ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
+ const zhi: [char; 12] = [
+ '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌',
+ '亥',
+ ];
+ 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
+ });
&GANZHIS[i]
}
@@ -243,10 +257,9 @@ const fn int(x: f64) -> usize {
x as usize // x.as_int_unchecked() // wont work on wasm
}
-static JIAZI: LazyLock<usize> = LazyLock::new(|| int(JD!(UNIT_YR, 1, 31)));
-
#[must_use]
pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate {
+ static JIAZI: LazyLock<usize> = LazyLock::new(|| int(JD!(UNIT_YR, 1, 31)));
let jdf = JD!(y, m, d);
let jd = int(jdf);
let a = compute_ang(jdf);