summaryrefslogtreecommitdiff
path: root/src/solar.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/solar.rs')
-rw-r--r--src/solar.rs75
1 files changed, 36 insertions, 39 deletions
diff --git a/src/solar.rs b/src/solar.rs
index 06cffb3..3cf0c95 100644
--- a/src/solar.rs
+++ b/src/solar.rs
@@ -4,12 +4,11 @@
#![allow(dead_code)]
// based on https://prospertimes.neocities.org/solarterms.js
-use lazy_static::lazy_static;
use num::cast;
use std::{
- f64::consts::PI,
mem::MaybeUninit,
ops::{Div, Rem},
+ sync::LazyLock,
};
// this is so stupid. i should not have to put pub every single line
@@ -97,14 +96,11 @@ fn compute_ang(jd: f64) -> f64 {
let Lmean = (280.46646 + (36000.76983 * T) + (0.0003032 * T * T)) % 360.;
let M = (357.52911 + (35999.05029 * T) - (0.0001537 * T * T)) % 360.;
let C = ((1.914602 - (0.004817 * T) - (0.000014 * T * T))
- * (M * PI / 180.).sin())
- + ((0.019993 - (0.000101 * T)) * (2. * M * PI / 180.).sin())
- + (0.000289 * (3. * M * PI / 180.).sin());
+ * (M.to_radians()).sin())
+ + ((0.019993 - (0.000101 * T)) * (2. * M.to_radians()).sin())
+ + (0.000289 * (3. * M.to_radians()).sin());
let Ltrue = Lmean + C;
- let Lapp = Ltrue
- - 0.00569
- - (0.00478 * ((125.04 - 1934.136 * T) * PI / 180.).sin());
- Lapp
+ Ltrue - 0.00569 - (0.00478 * ((125.04 - 1934.136 * T).to_radians()).sin())
}
#[inline(always)]
@@ -120,7 +116,7 @@ fn bisect<T>(
T: Into<f64> + Copy,
{
while lo <= hi {
- let mid = ((*lo + *hi) / 2.).floor();
+ let mid = f64::midpoint(*lo, *hi).floor();
if compute_ang(JD!(y, m, base.into() + mid * scale.into())) < target {
*lo = mid + 1.;
} else {
@@ -171,7 +167,7 @@ where
{
let (a, to, zero) = (a.as_(), to.as_(), zero.as_());
let tmp = a + (to - zero);
- (tmp - to * (tmp >= to) as isize) as usize
+ (tmp - to * isize::from(tmp >= to)) as usize
}
#[inline(always)]
@@ -199,9 +195,9 @@ fn stday(i: usize, y: usize) -> f64 {
const YEARS: usize = 200;
// 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!(y < UNIT_YR + YEARS && UNIT_YR <= y);
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()];
@@ -220,47 +216,47 @@ fn stday(i: usize, y: usize) -> f64 {
}
}
-lazy_static! {
- static ref GANZHIS: Vec<String> = {
- const gan: [char; 10] = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
- const zhi: [char; 12] = [ '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉',
- '戌', '亥', ];
- let mut tmp: Vec<String> = vec![];
- tmp.reserve(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
- };
-}
+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 {
&GANZHIS[i]
}
#[inline(always)]
-fn int(x: f64) -> usize {
+const fn int(x: f64) -> usize {
x as usize // x.as_int_unchecked() // wont work on wasm
}
-lazy_static! {
- static ref JIAZI: usize = int(JD!(UNIT_YR, 1, 31));
-}
+static JIAZI: LazyLock<usize> = LazyLock::new(|| int(JD!(UNIT_YR, 1, 31)));
+
+#[must_use]
pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate {
let jdf = JD!(y, m, d);
let jd = int(jdf);
let a = compute_ang(jdf);
let ygz = (y
- UNIT_YR
- - ((m <= 2 && a < 316.) && (m < 2 || d < int(stday(2, y)))) as usize)
+ - usize::from((m <= 2 && a < 316.) && (m < 2 || d < int(stday(2, y)))))
% 60;
let rem = a % 15.;
let div = int(a.div(15.).floor());
- let mut dz = align((div + 1) / 2, 12, 9);
+ let mut dz = align(div.div_ceil(2), 12, 9);
let mut termb = rem > 14.;
let mut term: usize = unsafe { MaybeUninit::uninit().assume_init() };
if termb {
@@ -268,13 +264,13 @@ pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate {
let termday = stday(term, y);
termb = d == int(termday);
if (div & 1) == 0 {
- dz += termb as usize;
+ dz += usize::from(termb);
dz = align(dz, 12, 12);
}
}
let mut tmp = ygz.rem(5);
tmp = tmp * 2 + 2;
- tmp -= 10 * (tmp == 10) as usize;
+ tmp -= 10 * usize::from(tmp == 10);
let mgz = mod2ganzhi(tmp + align(dz, 12, 2).rem(10), dz);
let dgz = (jd - *JIAZI).rem(60);
SexagenaryDate {
@@ -286,12 +282,13 @@ pub fn solar(y: usize, m: usize, d: usize) -> SexagenaryDate {
}
// https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Disparate_variation
+#[must_use]
pub fn dow(y: usize, mut m: usize, d: usize) -> (&'static str, &'static str) {
- let Y = y - (m <= 2) as usize;
+ let Y = y - usize::from(m <= 2);
let y2 = Y % 100;
let c = Y / 100;
m += 9;
- m -= 12 * (m >= 12) as usize;
+ m -= 12 * usize::from(m >= 12);
let a = (d + (26 * (m + 1) - 2) / 10 + y2 + y2 / 4 + c / 4 - 2 * c) % 7;
[
("日", "Sun"),