From baefff4bd85771409aade20f8fa300e9b84b6ed0 Mon Sep 17 00:00:00 2001 From: Nuutti Kotivuori Date: Tue, 6 Aug 2024 21:20:54 +0000 Subject: [PATCH 1/3] feat: Use `i8` instead of `u8` for all types --- src/lib.rs | 150 ++++++++++++++++++++++++++--------------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9379dd7..3c22533 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,77 +205,77 @@ pub const RD_SECONDS_MAX: i64 = RD_MAX as i64 * SECS_IN_DAY + SECS_IN_DAY - 1; /// library and the values are wholly unremarkable. pub mod consts { /// Minimum value for week - pub const WEEK_MIN: u8 = 1; + pub const WEEK_MIN: i8 = 1; /// Maximum value for week - pub const WEEK_MAX: u8 = 53; + pub const WEEK_MAX: i8 = 53; /// Minimum value for month - pub const MONTH_MIN: u8 = 1; + pub const MONTH_MIN: i8 = 1; /// Maximum value for month - pub const MONTH_MAX: u8 = 12; + pub const MONTH_MAX: i8 = 12; /// Minimum value for day of month - pub const DAY_MIN: u8 = 1; + pub const DAY_MIN: i8 = 1; /// Maximum value for day of month - pub const DAY_MAX: u8 = 31; + pub const DAY_MAX: i8 = 31; /// Minimum value for day of week - pub const WEEKDAY_MIN: u8 = 1; + pub const WEEKDAY_MIN: i8 = 1; /// Maximum value for day of week - pub const WEEKDAY_MAX: u8 = 7; + pub const WEEKDAY_MAX: i8 = 7; /// Minimum value for hours - pub const HOUR_MIN: u8 = 0; + pub const HOUR_MIN: i8 = 0; /// Maximum value for hours - pub const HOUR_MAX: u8 = 23; + pub const HOUR_MAX: i8 = 23; /// Minimum value for minutes - pub const MINUTE_MIN: u8 = 0; + pub const MINUTE_MIN: i8 = 0; /// Maximum value for minutes - pub const MINUTE_MAX: u8 = 59; + pub const MINUTE_MAX: i8 = 59; /// Minimum value for seconds - pub const SECOND_MIN: u8 = 0; + pub const SECOND_MIN: i8 = 0; /// Maximum value for seconds - pub const SECOND_MAX: u8 = 59; + pub const SECOND_MAX: i8 = 59; /// Minimum value for nanoseconds pub const NANOSECOND_MIN: u32 = 0; /// Maximum value for nanoseconds pub const NANOSECOND_MAX: u32 = 999_999_999; /// January month value - pub const JANUARY: u8 = 1; + pub const JANUARY: i8 = 1; /// February month value - pub const FEBRUARY: u8 = 2; + pub const FEBRUARY: i8 = 2; /// March month value - pub const MARCH: u8 = 3; + pub const MARCH: i8 = 3; /// April month value - pub const APRIL: u8 = 4; + pub const APRIL: i8 = 4; /// May month value - pub const MAY: u8 = 5; + pub const MAY: i8 = 5; /// June month value - pub const JUNE: u8 = 6; + pub const JUNE: i8 = 6; /// July month value - pub const JULY: u8 = 7; + pub const JULY: i8 = 7; /// August month value - pub const AUGUST: u8 = 8; + pub const AUGUST: i8 = 8; /// September month value - pub const SEPTEMBER: u8 = 9; + pub const SEPTEMBER: i8 = 9; /// October month value - pub const OCTOBER: u8 = 10; + pub const OCTOBER: i8 = 10; /// November month value - pub const NOVEMBER: u8 = 11; + pub const NOVEMBER: i8 = 11; /// December month value - pub const DECEMBER: u8 = 12; + pub const DECEMBER: i8 = 12; /// Monday day of week value - pub const MONDAY: u8 = 1; + pub const MONDAY: i8 = 1; /// Tuesday day of week value - pub const TUESDAY: u8 = 2; + pub const TUESDAY: i8 = 2; /// Wednesday day of week value - pub const WEDNESDAY: u8 = 3; + pub const WEDNESDAY: i8 = 3; /// Thursday day of week value - pub const THURSDAY: u8 = 4; + pub const THURSDAY: i8 = 4; /// Friday day of week value - pub const FRIDAY: u8 = 5; + pub const FRIDAY: i8 = 5; /// Saturday day of week value - pub const SATURDAY: u8 = 6; + pub const SATURDAY: i8 = 6; /// Sunday day of week value - pub const SUNDAY: u8 = 7; + pub const SUNDAY: i8 = 7; } // OPTIMIZATION NOTES: @@ -319,7 +319,7 @@ pub mod consts { /// > calendar algorithms*". Softw Pract Exper. 2022;1-34. doi: /// > [10.1002/spe.3172](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172). #[inline] -pub const fn rd_to_date(n: i32) -> (i32, u8, u8) { +pub const fn rd_to_date(n: i32) -> (i32, i8, i8) { debug_assert!(n >= RD_MIN && n <= RD_MAX, "given rata die is out of range"); let n = n.wrapping_add(DAY_OFFSET) as u32; // century @@ -341,12 +341,12 @@ pub const fn rd_to_date(n: i32) -> (i32, u8, u8) { let y = (y as i32).wrapping_sub(YEAR_OFFSET); let m = if j { m - 12 } else { m }; let d = d + 1; - (y, m as u8, d as u8) + (y, m as i8, d as i8) } /// Convert a Gregorian date to its Computational calendar's counterpart. #[inline] -const fn date_to_internal(y: i32, m: u8, d: u8) -> (u32, u32, u32, u32) { +const fn date_to_internal(y: i32, m: i8, d: i8) -> (u32, u32, u32, u32) { debug_assert!(y >= YEAR_MIN && y <= YEAR_MAX, "given year is out of range"); debug_assert!(m >= consts::MONTH_MIN && m <= consts::MONTH_MAX, "given month is out of range"); debug_assert!(d >= consts::DAY_MIN && d <= days_in_month(y, m), "given day is out of range"); @@ -397,7 +397,7 @@ const fn date_to_internal(y: i32, m: u8, d: u8) -> (u32, u32, u32, u32) { /// > calendar algorithms*". Softw Pract Exper. 2022;1-34. doi: /// > [10.1002/spe.3172](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172). #[inline] -pub const fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { +pub const fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { let (c, y, m, d) = date_to_internal(y, m, d); let d = d - 1; // year @@ -474,10 +474,10 @@ pub const fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { /// > approximation that works provided that `m` is not too large but, still, /// > large enough for our purposes. #[inline] -pub const fn rd_to_weekday(n: i32) -> u8 { +pub const fn rd_to_weekday(n: i32) -> i8 { debug_assert!(n >= RD_MIN && n <= RD_MAX, "given rata die is out of range"); const P64_OVER_SEVEN: u64 = ((1 << 63) / 7) << 1; // = (1 << 64) / 7 - (((n.wrapping_sub(RD_MIN) as u64 + 1).wrapping_mul(P64_OVER_SEVEN)) >> 61) as u8 + (((n.wrapping_sub(RD_MIN) as u64 + 1).wrapping_mul(P64_OVER_SEVEN)) >> 61) as i8 } /// Convert Gregorian date to day of week @@ -518,7 +518,7 @@ pub const fn rd_to_weekday(n: i32) -> u8 { /// Simple adaptation of `date_to_rd` to modulus 7 arithmetics. /// #[inline] -pub const fn date_to_weekday((y, m, d): (i32, u8, u8)) -> u8 { +pub const fn date_to_weekday((y, m, d): (i32, i8, i8)) -> i8 { let (c, y, m, d) = date_to_internal(y, m, d); // year let y = 5 * y / 4 - c + c / 4; @@ -527,7 +527,7 @@ pub const fn date_to_weekday((y, m, d): (i32, u8, u8)) -> u8 { // result let n = y + m + d; const P32_OVER_SEVEN: u32 = ((1 << 31) / 7) << 1; // = (1 << 32) / 7 - ((n.wrapping_mul(P32_OVER_SEVEN)) >> 29) as u8 + ((n.wrapping_mul(P32_OVER_SEVEN)) >> 29) as i8 } /// Calculate next Gregorian date given a Gregorian date @@ -559,7 +559,7 @@ pub const fn date_to_weekday((y, m, d): (i32, u8, u8)) -> u8 { /// Simple incrementation with manual overflow checking and carry. Relatively /// speedy, but not fully optimized. #[inline] -pub const fn next_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { +pub const fn next_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { debug_assert!(y >= YEAR_MIN && y <= YEAR_MAX, "given year is out of range"); debug_assert!(m >= consts::MONTH_MIN && m <= consts::MONTH_MAX, "given month is out of range"); debug_assert!(d >= consts::DAY_MIN && d <= days_in_month(y, m), "given day is out of range"); @@ -605,7 +605,7 @@ pub const fn next_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { /// Simple decrementation with manual underflow checking and carry. Relatively /// speedy, but not fully optimized. #[inline] -pub const fn prev_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { +pub const fn prev_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { debug_assert!(y >= YEAR_MIN && y <= YEAR_MAX, "given year is out of range"); debug_assert!(m >= consts::MONTH_MIN && m <= consts::MONTH_MAX, "given month is out of range"); debug_assert!(d >= consts::DAY_MIN && d <= days_in_month(y, m), "given day is out of range"); @@ -653,7 +653,7 @@ pub const fn prev_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { /// > calendar algorithms*". Softw Pract Exper. 2022;1-34. doi: /// > [10.1002/spe.3172](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.3172). #[inline] -pub const fn secs_to_dhms(secs: i64) -> (i32, u8, u8, u8) { +pub const fn secs_to_dhms(secs: i64) -> (i32, i8, i8, i8) { debug_assert!( secs >= RD_SECONDS_MIN && secs <= RD_SECONDS_MAX, "given seconds value is out of range" @@ -678,7 +678,7 @@ pub const fn secs_to_dhms(secs: i64) -> (i32, u8, u8, u8) { let mm = (prd as u32) / 71582789; // mins % 60 let days = (days as i32).wrapping_sub(DAY_OFFSET); - (days, hh as u8, mm as u8, ss as u8) + (days, hh as i8, mm as i8, ss as i8) } /// Combine days, hours, minutes and seconds to total seconds @@ -711,7 +711,7 @@ pub const fn secs_to_dhms(secs: i64) -> (i32, u8, u8, u8) { /// /// Algorithm is simple multiplication, method provided only as convenience. #[inline] -pub const fn dhms_to_secs((d, h, m, s): (i32, u8, u8, u8)) -> i64 { +pub const fn dhms_to_secs((d, h, m, s): (i32, i8, i8, i8)) -> i64 { debug_assert!(d >= RD_MIN && d <= RD_MAX, "given rata die is out of range"); debug_assert!(h >= consts::HOUR_MIN && h <= consts::HOUR_MAX, "given hour is out of range"); debug_assert!(m >= consts::MINUTE_MIN && m <= consts::MINUTE_MAX, "given minute is out of range"); @@ -750,7 +750,7 @@ pub const fn dhms_to_secs((d, h, m, s): (i32, u8, u8, u8)) -> i64 { /// /// Combination of existing functions for convenience only. #[inline] -pub const fn secs_to_datetime(secs: i64) -> (i32, u8, u8, u8, u8, u8) { +pub const fn secs_to_datetime(secs: i64) -> (i32, i8, i8, i8, i8, i8) { let (days, hh, mm, ss) = secs_to_dhms(secs); let (y, m, s) = rd_to_date(days); (y, m, s, hh, mm, ss) @@ -787,7 +787,7 @@ pub const fn secs_to_datetime(secs: i64) -> (i32, u8, u8, u8, u8, u8) { /// /// Algorithm is simple multiplication, method provided only as convenience. #[inline] -pub const fn datetime_to_secs((y, m, d, hh, mm, ss): (i32, u8, u8, u8, u8, u8)) -> i64 { +pub const fn datetime_to_secs((y, m, d, hh, mm, ss): (i32, i8, i8, i8, i8, i8)) -> i64 { let days = date_to_rd((y, m, d)); dhms_to_secs((days, hh, mm, ss)) } @@ -857,7 +857,7 @@ pub const fn is_leap_year(y: i32) -> bool { /// Algorithm is Neri-Schneider from C++now 2023 conference: /// > #[inline] -pub const fn days_in_month(y: i32, m: u8) -> u8 { +pub const fn days_in_month(y: i32, m: i8) -> i8 { debug_assert!(m >= consts::MONTH_MIN && m <= consts::MONTH_MAX, "given month is out of range"); if m != 2 { 30 | (m ^ (m >> 3)) @@ -903,14 +903,14 @@ pub const fn days_in_month(y: i32, m: u8) -> u8 { /// /// Algorithm is hand crafted and not significantly optimized. #[inline] -pub const fn rd_to_isoweekdate(rd: i32) -> (i32, u8, u8) { +pub const fn rd_to_isoweekdate(rd: i32) -> (i32, i8, i8) { debug_assert!(rd >= RD_MIN && rd <= RD_MAX, "given rata die is out of range"); let wd = rd_to_weekday(rd); let rdt = rd + (4 - wd as i32) % 7; let (y, _, _) = rd_to_date(rdt); let ys = date_to_rd((y, 1, 1)); let w = (rdt - ys) / 7 + 1; - (y, w as u8, wd) + (y, w as i8, wd) } /// Convert [ISO week date](https://en.wikipedia.org/wiki/ISO_week_date) to Rata Die @@ -951,7 +951,7 @@ pub const fn rd_to_isoweekdate(rd: i32) -> (i32, u8, u8) { /// /// Algorithm is hand crafted and not significantly optimized. #[inline] -pub const fn isoweekdate_to_rd((y, w, d): (i32, u8, u8)) -> i32 { +pub const fn isoweekdate_to_rd((y, w, d): (i32, i8, i8)) -> i32 { debug_assert!(y >= YEAR_MIN && y <= YEAR_MAX, "given year is out of range"); debug_assert!(w >= consts::WEEK_MIN && w <= isoweeks_in_year(y), "given week is out of range"); debug_assert!( @@ -1000,7 +1000,7 @@ pub const fn isoweekdate_to_rd((y, w, d): (i32, u8, u8)) -> i32 { /// /// Simply converts date to rata die and then rata die to ISO week date. #[inline] -pub const fn date_to_isoweekdate((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { +pub const fn date_to_isoweekdate((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { let rd = date_to_rd((y, m, d)); rd_to_isoweekdate(rd) } @@ -1042,7 +1042,7 @@ pub const fn date_to_isoweekdate((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { /// /// Simply converts ISO week date to rata die and then rata die to date. #[inline] -pub const fn isoweekdate_to_date((y, w, d): (i32, u8, u8)) -> (i32, u8, u8) { +pub const fn isoweekdate_to_date((y, w, d): (i32, i8, i8)) -> (i32, i8, i8) { let rd = isoweekdate_to_rd((y, w, d)); rd_to_date(rd) } @@ -1075,7 +1075,7 @@ pub const fn isoweekdate_to_date((y, w, d): (i32, u8, u8)) -> (i32, u8, u8) { /// /// Algorithm is hand crafted and not significantly optimized. #[inline] -pub const fn isoweeks_in_year(y: i32) -> u8 { +pub const fn isoweeks_in_year(y: i32) -> i8 { debug_assert!(y >= YEAR_MIN && y <= YEAR_MAX, "given year is out of range"); let wd = date_to_weekday((y, 1, 1)); let l = is_leap_year(y); @@ -1219,7 +1219,7 @@ pub fn secs_to_systemtime((secs, nsecs): (i64, u32)) -> Option { /// Combination of existing functions for convenience only. #[cfg(feature = "std")] #[inline] -pub fn systemtime_to_datetime(st: SystemTime) -> Option<(i32, u8, u8, u8, u8, u8, u32)> { +pub fn systemtime_to_datetime(st: SystemTime) -> Option<(i32, i8, i8, i8, i8, i8, u32)> { let (secs, nsecs) = systemtime_to_secs(st)?; let (days, hh, mm, ss) = secs_to_dhms(secs); let (year, month, day) = rd_to_date(days); @@ -1263,7 +1263,7 @@ pub fn systemtime_to_datetime(st: SystemTime) -> Option<(i32, u8, u8, u8, u8, u8 /// Combination of existing functions for convenience only. #[cfg(feature = "std")] #[inline] -pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> Option { +pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> Option { let days = date_to_rd((y, m, d)); let secs = dhms_to_secs((days, hh, mm, ss)); secs_to_systemtime((secs, nsec)) @@ -1277,43 +1277,43 @@ pub mod asm { use std::time::SystemTime; #[inline(never)] - pub const fn rd_to_date(n: i32) -> (i32, u8, u8) { + pub const fn rd_to_date(n: i32) -> (i32, i8, i8) { super::rd_to_date(n) } #[inline(never)] - pub const fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { + pub const fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { super::date_to_rd((y, m, d)) } #[inline(never)] - pub const fn rd_to_weekday(n: i32) -> u8 { + pub const fn rd_to_weekday(n: i32) -> i8 { super::rd_to_weekday(n) } #[inline(never)] - pub const fn date_to_weekday((y, m, d): (i32, u8, u8)) -> u8 { + pub const fn date_to_weekday((y, m, d): (i32, i8, i8)) -> i8 { super::date_to_weekday((y, m, d)) } #[inline(never)] - pub const fn next_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn next_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { super::next_date((y, m, d)) } #[inline(never)] - pub const fn prev_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn prev_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { super::prev_date((y, m, d)) } #[inline(never)] - pub const fn secs_to_dhms(secs: i64) -> (i32, u8, u8, u8) { + pub const fn secs_to_dhms(secs: i64) -> (i32, i8, i8, i8) { super::secs_to_dhms(secs) } #[inline(never)] - pub const fn dhms_to_secs((d, h, m, s): (i32, u8, u8, u8)) -> i64 { + pub const fn dhms_to_secs((d, h, m, s): (i32, i8, i8, i8)) -> i64 { super::dhms_to_secs((d, h, m, s)) } #[inline(never)] - pub const fn secs_to_datetime(secs: i64) -> (i32, u8, u8, u8, u8, u8) { + pub const fn secs_to_datetime(secs: i64) -> (i32, i8, i8, i8, i8, i8) { super::secs_to_datetime(secs) } #[inline(never)] - pub const fn datetime_to_secs((y, m, d, hh, mm, ss): (i32, u8, u8, u8, u8, u8)) -> i64 { + pub const fn datetime_to_secs((y, m, d, hh, mm, ss): (i32, i8, i8, i8, i8, i8)) -> i64 { super::datetime_to_secs((y, m, d, hh, mm, ss)) } #[inline(never)] @@ -1321,27 +1321,27 @@ pub mod asm { super::is_leap_year(y) } #[inline(never)] - pub const fn days_in_month(y: i32, m: u8) -> u8 { + pub const fn days_in_month(y: i32, m: i8) -> i8 { super::days_in_month(y, m) } #[inline(never)] - pub const fn rd_to_isoweekdate(rd: i32) -> (i32, u8, u8) { + pub const fn rd_to_isoweekdate(rd: i32) -> (i32, i8, i8) { super::rd_to_isoweekdate(rd) } #[inline(never)] - pub const fn isoweekdate_to_rd((y, w, d): (i32, u8, u8)) -> i32 { + pub const fn isoweekdate_to_rd((y, w, d): (i32, i8, i8)) -> i32 { super::isoweekdate_to_rd((y, w, d)) } #[inline(never)] - pub const fn date_to_isoweekdate((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn date_to_isoweekdate((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { super::date_to_isoweekdate((y, m, d)) } #[inline(never)] - pub const fn isoweekdate_to_date((y, w, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn isoweekdate_to_date((y, w, d): (i32, i8, i8)) -> (i32, i8, i8) { super::isoweekdate_to_date((y, w, d)) } #[inline(never)] - pub const fn isoweeks_in_year(y: i32) -> u8 { + pub const fn isoweeks_in_year(y: i32) -> i8 { super::isoweeks_in_year(y) } #[cfg(feature = "std")] @@ -1356,12 +1356,12 @@ pub mod asm { } #[cfg(feature = "std")] #[inline(never)] - pub fn systemtime_to_datetime(st: SystemTime) -> Option<(i32, u8, u8, u8, u8, u8, u32)> { + pub fn systemtime_to_datetime(st: SystemTime) -> Option<(i32, i8, i8, i8, i8, i8, u32)> { super::systemtime_to_datetime(st) } #[cfg(feature = "std")] #[inline(never)] - pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> Option { + pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> Option { super::datetime_to_systemtime((y, m, d, hh, mm, ss, nsec)) } } From 22e0dab9f4ebef7e040fdbed470446675dc8586e Mon Sep 17 00:00:00 2001 From: Nuutti Kotivuori Date: Tue, 6 Aug 2024 21:21:08 +0000 Subject: [PATCH 2/3] chore: Fix tests and benchmarks for `i8` --- benches/basic.rs | 26 +++---- benches/compare.rs | 184 ++++++++++++++++++++++---------------------- benches/iai.rs | 18 ++--- tests/quickcheck.rs | 48 ++++++------ 4 files changed, 138 insertions(+), 138 deletions(-) diff --git a/benches/basic.rs b/benches/basic.rs index 70dfe53..b4199c8 100644 --- a/benches/basic.rs +++ b/benches/basic.rs @@ -12,10 +12,10 @@ fn rand_rd() -> i32 { fastrand::i32(datealgo::RD_MIN..=datealgo::RD_MAX) } -fn rand_date() -> (i32, u8, u8) { +fn rand_date() -> (i32, i8, i8) { let y = rand_year(); - let m = fastrand::u8(1..=12); - let d = fastrand::u8(1..=datealgo::days_in_month(y, m)); + let m = fastrand::i8(1..=12); + let d = fastrand::i8(1..=datealgo::days_in_month(y, m)); (y, m, d) } @@ -23,28 +23,28 @@ fn rand_secs() -> i64 { fastrand::i64(datealgo::RD_SECONDS_MIN..=datealgo::RD_SECONDS_MAX) } -fn rand_hms() -> (u8, u8, u8) { - let h = fastrand::u8(0..=23); - let m = fastrand::u8(0..=59); - let s = fastrand::u8(0..=59); +fn rand_hms() -> (i8, i8, i8) { + let h = fastrand::i8(0..=23); + let m = fastrand::i8(0..=59); + let s = fastrand::i8(0..=59); (h, m, s) } -fn rand_dhms() -> (i32, u8, u8, u8) { +fn rand_dhms() -> (i32, i8, i8, i8) { let rd = rand_rd(); let (h, m, s) = rand_hms(); (rd, h, m, s) } -fn rand_dt() -> (i32, u8, u8, u8, u8, u8) { +fn rand_dt() -> (i32, i8, i8, i8, i8, i8) { let (y, m, d) = rand_date(); let (hh, mm, ss) = rand_hms(); (y, m, d, hh, mm, ss) } -fn rand_ym() -> (i32, u8) { +fn rand_ym() -> (i32, i8) { let y = rand_year(); - let m = fastrand::u8(1..=12); + let m = fastrand::i8(1..=12); (y, m) } @@ -58,13 +58,13 @@ fn rand_st() -> SystemTime { datealgo::secs_to_systemtime(rand_sn()).unwrap() } -fn rand_dtn() -> (i32, u8, u8, u8, u8, u8, u32) { +fn rand_dtn() -> (i32, i8, i8, i8, i8, i8, u32) { let (y, m, d, hh, mm, ss) = rand_dt(); let n = fastrand::u32(0..=999_999_999); (y, m, d, hh, mm, ss, n) } -fn rand_iwd() -> (i32, u8, u8) { +fn rand_iwd() -> (i32, i8, i8) { datealgo::rd_to_isoweekdate(rand_rd()) } diff --git a/benches/compare.rs b/benches/compare.rs index 1cb5bc2..588b9c7 100644 --- a/benches/compare.rs +++ b/benches/compare.rs @@ -12,10 +12,10 @@ fn rand_rd() -> i32 { fastrand::i32(datealgo::date_to_rd((1970, 1, 1))..=datealgo::date_to_rd((9999, 12, 31))) } -fn rand_date() -> (i32, u8, u8) { +fn rand_date() -> (i32, i8, i8) { let y = rand_year(); - let m = fastrand::u8(1..=12); - let d = fastrand::u8(1..=datealgo::days_in_month(y, m)); + let m = fastrand::i8(1..=12); + let d = fastrand::i8(1..=datealgo::days_in_month(y, m)); (y, m, d) } @@ -23,28 +23,28 @@ fn rand_secs() -> i64 { fastrand::i64(datealgo::datetime_to_secs((1970, 1, 1, 0, 0, 0))..=datealgo::datetime_to_secs((9999, 12, 31, 23, 59, 59))) } -fn rand_hms() -> (u8, u8, u8) { - let h = fastrand::u8(0..=23); - let m = fastrand::u8(0..=59); - let s = fastrand::u8(0..=59); +fn rand_hms() -> (i8, i8, i8) { + let h = fastrand::i8(0..=23); + let m = fastrand::i8(0..=59); + let s = fastrand::i8(0..=59); (h, m, s) } -fn rand_dhms() -> (i32, u8, u8, u8) { +fn rand_dhms() -> (i32, i8, i8, i8) { let rd = rand_rd(); let (h, m, s) = rand_hms(); (rd, h, m, s) } -fn rand_dt() -> (i32, u8, u8, u8, u8, u8) { +fn rand_dt() -> (i32, i8, i8, i8, i8, i8) { let (y, m, d) = rand_date(); let (hh, mm, ss) = rand_hms(); (y, m, d, hh, mm, ss) } -fn rand_ym() -> (i32, u8) { +fn rand_ym() -> (i32, i8) { let y = rand_year(); - let m = fastrand::u8(1..=12); + let m = fastrand::i8(1..=12); (y, m) } @@ -58,13 +58,13 @@ fn rand_st() -> SystemTime { datealgo::secs_to_systemtime(rand_sn()).unwrap() } -fn rand_dtn() -> (i32, u8, u8, u8, u8, u8, u32) { +fn rand_dtn() -> (i32, i8, i8, i8, i8, i8, u32) { let (y, m, d, hh, mm, ss) = rand_dt(); let n = fastrand::u32(0..=999_999_999); (y, m, d, hh, mm, ss, n) } -fn rand_iwd() -> (i32, u8, u8) { +fn rand_iwd() -> (i32, i8, i8) { datealgo::rd_to_isoweekdate(rand_rd()) } @@ -77,7 +77,7 @@ mod datealgo_alt { use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[inline] - pub const fn secs_to_dhms(secs: i64) -> (i32, u8, u8, u8) { + pub const fn secs_to_dhms(secs: i64) -> (i32, i8, i8, i8) { let secs = secs as u64; let ss = secs % 60; let secs = secs / 60; @@ -85,11 +85,11 @@ mod datealgo_alt { let secs = secs / 60; let hh = secs % 24; let secs = secs / 24; - (secs as i32, hh as u8, mm as u8, ss as u8) + (secs as i32, hh as i8, mm as i8, ss as i8) } #[inline] - pub const fn secs_to_dhms2(secs: i64) -> (i32, u8, u8, u8) { + pub const fn secs_to_dhms2(secs: i64) -> (i32, i8, i8, i8) { let secs = if secs > datealgo::RD_SECONDS_MAX { 0 } else { secs }; // allows compiler to optimize more let secs = secs.wrapping_add(SECS_OFFSET) as u64; let days = (secs / SECS_IN_DAY as u64) as u32; @@ -98,56 +98,56 @@ mod datealgo_alt { let mm = secs / 60 % 60; let hh = secs / 3600; let days = (days as i32).wrapping_sub(DAY_OFFSET); - (days, hh as u8, mm as u8, ss as u8) + (days, hh as i8, mm as i8, ss as i8) } #[inline] - pub const fn rd_to_weekday(n: i32) -> u8 { - (n + 4).rem_euclid(7) as u8 + pub const fn rd_to_weekday(n: i32) -> i8 { + (n + 4).rem_euclid(7) as i8 } #[inline] - pub const fn rd_to_weekday2(n: i32) -> u8 { + pub const fn rd_to_weekday2(n: i32) -> i8 { if n >= -4 { - ((n + 4) % 7) as u8 + ((n + 4) % 7) as i8 } else { - ((n + 5) % 7 + 6) as u8 + ((n + 5) % 7 + 6) as i8 } } #[inline] - pub const fn rd_to_weekday3(n: i32) -> u8 { - ((n.wrapping_add(DAY_OFFSET) as u32 + 2) % 7 + 1) as u8 + pub const fn rd_to_weekday3(n: i32) -> i8 { + ((n.wrapping_add(DAY_OFFSET) as u32 + 2) % 7 + 1) as i8 } #[inline] - pub const fn date_to_weekday((y, m, d): (i32, u8, u8)) -> u8 { + pub const fn date_to_weekday((y, m, d): (i32, i8, i8)) -> i8 { let y = y.wrapping_add(YEAR_OFFSET) as u32 - (m < 3) as u32; let t = [6u8, 2, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3]; let mut idx = m.wrapping_sub(1) as usize; if idx > 11 { idx = 0; } // ensure no bounds check - ((y + y / 4 - y / 100 + y / 400 + t[idx] as u32 + d as u32) % 7 + 1) as u8 + ((y + y / 4 - y / 100 + y / 400 + t[idx] as u32 + d as u32) % 7 + 1) as i8 } #[inline] - pub const fn date_to_weekday2((year, month, day): (i32, u8, u8)) -> u8 { + pub const fn date_to_weekday2((year, month, day): (i32, i8, i8)) -> i8 { let year = year.wrapping_add(YEAR_OFFSET) as u32; let adjustment = (14 - month) / 12; let mm = (month + 12 * adjustment - 2) as u32; let yy = year - adjustment as u32; - ((day as u32 + (13 * mm - 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400 + 6) % 7 + 1) as u8 + ((day as u32 + (13 * mm - 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400 + 6) % 7 + 1) as i8 } #[inline] - pub const fn next_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn next_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { let rd = datealgo::date_to_rd((y, m, d)); datealgo::rd_to_date(rd + 1) } #[inline] - pub const fn prev_date((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub const fn prev_date((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { let rd = datealgo::date_to_rd((y, m, d)); datealgo::rd_to_date(rd - 1) } @@ -183,14 +183,14 @@ mod datealgo_alt { } #[inline] - pub const fn days_in_month(y: i32, m: u8) -> u8 { + pub const fn days_in_month(y: i32, m: i8) -> i8 { // ensure compiler doesn't include a bounds check if m >= datealgo::consts::MONTH_MIN && m <= datealgo::consts::MONTH_MAX { let idx = m as usize - 1; if datealgo::is_leap_year(y) { - [31u8, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][idx] + [31i8, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][idx] } else { - [31u8, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][idx] + [31i8, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][idx] } } else { 0 @@ -198,7 +198,7 @@ mod datealgo_alt { } #[inline] - pub const fn days_in_month2(y: i32, m: u8) -> u8 { + pub const fn days_in_month2(y: i32, m: i8) -> i8 { if m == 2 { if datealgo::is_leap_year(y) { 29 @@ -229,7 +229,7 @@ mod httpdate { use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[inline] - pub fn rd_to_date(n: i32) -> (i32, u8, u8) { + pub fn rd_to_date(n: i32) -> (i32, i8, i8) { /* 2000-03-01 (mod 400 year, immediately after feb29 */ const LEAPOCH: i64 = 11017; const DAYS_PER_400Y: i64 = 365 * 400 + 97; @@ -283,11 +283,11 @@ mod httpdate { mon + 2 }; - (year as i32, mon as u8, mday as u8) + (year as i32, mon as i8, mday as i8) } #[inline] - pub fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { + pub fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { fn is_leap_year(y: u16) -> bool { y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) } @@ -317,7 +317,7 @@ mod httpdate { days as i32 } - pub fn systemtime_to_datetime(v: SystemTime) -> (i32, u8, u8, u8, u8, u8, u32) { + pub fn systemtime_to_datetime(v: SystemTime) -> (i32, i8, i8, i8, i8, i8, u32) { let dur = v.duration_since(UNIX_EPOCH).expect("all times should be after the epoch"); let secs_since_epoch = dur.as_secs(); @@ -386,16 +386,16 @@ mod httpdate { // }; ( year as i32, - mon as u8, - mday as u8, - (secs_of_day / 3600) as u8, - ((secs_of_day % 3600) / 60) as u8, - (secs_of_day % 60) as u8, + mon as i8, + mday as i8, + (secs_of_day / 3600) as i8, + ((secs_of_day % 3600) / 60) as i8, + (secs_of_day % 60) as i8, dur.subsec_nanos(), ) } - pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> SystemTime { + pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> SystemTime { fn is_leap_year(y: i32) -> bool { y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) } @@ -429,7 +429,7 @@ mod humantime { use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[inline] - pub fn rd_to_date(n: i32) -> (i32, u8, u8) { + pub fn rd_to_date(n: i32) -> (i32, i8, i8) { /* 2000-03-01 (mod 400 year, immediately after feb29 */ const LEAPOCH: i64 = 11017; const DAYS_PER_400Y: i64 = 365 * 400 + 97; @@ -483,11 +483,11 @@ mod humantime { mon + 2 }; - (year as i32, mon as u8, mday as u8) + (year as i32, mon as i8, mday as i8) } #[inline] - pub fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { + pub fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { fn is_leap_year(y: u64) -> bool { y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) } @@ -521,7 +521,7 @@ mod humantime { days as i32 } - pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> SystemTime { + pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> SystemTime { fn is_leap_year(y: u64) -> bool { y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) } @@ -565,7 +565,7 @@ mod humantime { UNIX_EPOCH + Duration::new(total_seconds, nsec) } - pub fn systemtime_to_datetime(v: SystemTime) -> (i32, u8, u8, u8, u8, u8, u32) { + pub fn systemtime_to_datetime(v: SystemTime) -> (i32, i8, i8, i8, i8, i8, u32) { let dur = v.duration_since(UNIX_EPOCH).expect("all times should be after the epoch"); let secs_since_epoch = dur.as_secs(); @@ -626,10 +626,10 @@ mod humantime { ( year as i32, mon, - mday as u8, - (secs_of_day / 3600) as u8, - (secs_of_day / 60 % 60) as u8, - (secs_of_day % 60) as u8, + mday as i8, + (secs_of_day / 3600) as i8, + (secs_of_day / 60 % 60) as i8, + (secs_of_day % 60) as i8, dur.subsec_nanos(), ) } @@ -655,34 +655,34 @@ mod chrono { } #[inline] - pub fn rd_to_date(n: i32) -> (i32, u8, u8) { + pub fn rd_to_date(n: i32) -> (i32, i8, i8) { let date = chrono::NaiveDate::from_num_days_from_ce_opt(n + 719162).unwrap(); - (date.year(), date.month() as u8, date.day() as u8) + (date.year(), date.month() as i8, date.day() as i8) } #[inline] - pub fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { + pub fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { let days = chrono::NaiveDate::from_ymd_opt(y, m as u32, d as u32).unwrap().num_days_from_ce(); days - 719162 } #[inline] - pub fn date_to_isoweekdate((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { + pub fn date_to_isoweekdate((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { let date = chrono::NaiveDate::from_ymd_opt(y, m as u32, d as u32).unwrap(); let iw = date.iso_week(); let (y, w, d) = (iw.year(), iw.week(), date.weekday().number_from_monday()); - (y, w as u8, d as u8) + (y, w as i8, d as i8) } #[inline] - pub fn isoweekdate_to_date((y, w, wd): (i32, u8, u8)) -> (i32, u8, u8) { - let wd = chrono::Weekday::try_from(wd - 1).unwrap(); + pub fn isoweekdate_to_date((y, w, wd): (i32, i8, i8)) -> (i32, i8, i8) { + let wd = chrono::Weekday::try_from((wd - 1) as u8).unwrap(); let date = chrono::NaiveDate::from_isoywd_opt(y, w as u32, wd).unwrap(); - (date.year(), date.month() as u8, date.day() as u8) + (date.year(), date.month() as i8, date.day() as i8) } #[inline] - pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> SystemTime { + pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> SystemTime { chrono::NaiveDate::from_ymd_opt(y as i32, m as u32, d as u32) .unwrap() .and_hms_nano_opt(hh as u32, mm as u32, ss as u32, nsec) @@ -693,15 +693,15 @@ mod chrono { } #[inline] - pub fn systemtime_to_datetime(v: SystemTime) -> (i32, u8, u8, u8, u8, u8, u32) { + pub fn systemtime_to_datetime(v: SystemTime) -> (i32, i8, i8, i8, i8, i8, u32) { let d: chrono::DateTime = v.into(); ( d.year() as i32, - d.month() as u8, - d.day() as u8, - d.hour() as u8, - d.minute() as u8, - d.second() as u8, + d.month() as i8, + d.day() as i8, + d.hour() as i8, + d.minute() as i8, + d.second() as i8, d.nanosecond(), ) } @@ -714,7 +714,7 @@ mod time { pub fn rand_date() -> time::Date { let (y, m, d) = super::rand_date(); - time::Date::from_calendar_date(y, m.try_into().unwrap(), d).unwrap() + time::Date::from_calendar_date(y, (m as u8).try_into().unwrap(), d as u8).unwrap() } #[inline] @@ -728,13 +728,13 @@ mod time { } #[inline] - pub fn rd_to_date(n: i32) -> (i32, u8, u8) { + pub fn rd_to_date(n: i32) -> (i32, i8, i8) { let date = time::Date::from_julian_day(n + UNIX_EPOCH_JULIAN_DAY).unwrap(); - (date.year(), date.month() as u8, date.day() as u8) + (date.year(), date.month() as i8, date.day() as i8) } #[inline] - pub fn date_to_rd((y, m, d): (i32, u8, u8)) -> i32 { + pub fn date_to_rd((y, m, d): (i32, i8, i8)) -> i32 { time::Date::from_calendar_date(y, time::Month::try_from(m as u8).unwrap(), d as u8) .unwrap() .to_julian_day() @@ -742,45 +742,45 @@ mod time { } #[inline] - pub fn date_to_isoweekdate((y, m, d): (i32, u8, u8)) -> (i32, u8, u8) { - let date = time::Date::from_calendar_date(y, m.try_into().unwrap(), d).unwrap(); + pub fn date_to_isoweekdate((y, m, d): (i32, i8, i8)) -> (i32, i8, i8) { + let date = time::Date::from_calendar_date(y, (m as u8).try_into().unwrap(), d as u8).unwrap(); let (y, w, wd) = date.to_iso_week_date(); - (y, w as u8, wd.number_from_monday()) + (y, w as i8, wd.number_from_monday() as i8) } #[inline] - pub fn isoweekdate_to_date((y, w, wd): (i32, u8, u8)) -> (i32, u8, u8) { - let d = time::Date::from_iso_week_date(y, w, time::Weekday::Sunday.nth_next(wd)).unwrap(); - (d.year(), d.month() as u8, d.day() as u8) + pub fn isoweekdate_to_date((y, w, wd): (i32, i8, i8)) -> (i32, i8, i8) { + let d = time::Date::from_iso_week_date(y, w as u8, time::Weekday::Sunday.nth_next(wd as u8)).unwrap(); + (d.year(), d.month() as i8, d.day() as i8) } #[inline] - pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, u8, u8, u8, u8, u8, u32)) -> SystemTime { + pub fn datetime_to_systemtime((y, m, d, hh, mm, ss, nsec): (i32, i8, i8, i8, i8, i8, u32)) -> SystemTime { time::Date::from_calendar_date(y, time::Month::try_from(m as u8).unwrap(), d as u8) .unwrap() - .with_hms_nano(hh, mm, ss, nsec) + .with_hms_nano(hh as u8, mm as u8, ss as u8, nsec) .unwrap() .assume_utc() .into() } #[inline] - pub fn systemtime_to_datetime(v: SystemTime) -> (i32, u8, u8, u8, u8, u8, u32) { + pub fn systemtime_to_datetime(v: SystemTime) -> (i32, i8, i8, i8, i8, i8, u32) { let d: time::OffsetDateTime = v.into(); ( d.year() as i32, - d.month() as u8, - d.day() as u8, - d.hour() as u8, - d.minute() as u8, - d.second() as u8, + d.month() as i8, + d.day() as i8, + d.hour() as i8, + d.minute() as i8, + d.second() as i8, d.nanosecond(), ) } } mod hinnant { - pub fn days_from_civil((y, m, d): (i32, u8, u8)) -> i32 { + pub fn days_from_civil((y, m, d): (i32, i8, i8)) -> i32 { let y = y as i32 - (m <= 2) as i32; let era = y.div_euclid(400); let yoe = y.rem_euclid(400) as u32; @@ -789,7 +789,7 @@ mod hinnant { era * 146097 + doe as i32 - 719468 } - pub fn days_from_civil_u((y, m, d): (i32, u8, u8)) -> i32 { + pub fn days_from_civil_u((y, m, d): (i32, i8, i8)) -> i32 { let y = y as u32 - (m <= 2) as u32; let era = y.div_euclid(400); let yoe = y.rem_euclid(400) as u32; @@ -798,7 +798,7 @@ mod hinnant { (era * 146097 + doe as u32 - 719468) as i32 } - pub fn civil_from_days(n: i32) -> (i32, u8, u8) { + pub fn civil_from_days(n: i32) -> (i32, i8, i8) { let z = n + 719468; let era = z.div_euclid(146097); let doe = z.rem_euclid(146097) as u32; @@ -808,10 +808,10 @@ mod hinnant { let mp = (5 * doy + 2) / 153; let d = doy - (153 * mp + 2) / 5 + 1; let m = if mp < 10 { mp + 3 } else { mp - 9 }; - (y + (m <= 2) as i32, m as u8, d as u8) + (y + (m <= 2) as i32, m as i8, d as i8) } - pub fn civil_from_days_u(n: i32) -> (i32, u8, u8) { + pub fn civil_from_days_u(n: i32) -> (i32, i8, i8) { let z = (n + 719468) as u32; let era = z.div_euclid(146097); let doe = z.rem_euclid(146097) as u32; @@ -821,7 +821,7 @@ mod hinnant { let mp = (5 * doy + 2) / 153; let d = doy - (153 * mp + 2) / 5 + 1; let m = if mp < 10 { mp + 3 } else { mp - 9 }; - ((y + (m <= 2) as u32) as i32, m as u8, d as u8) + ((y + (m <= 2) as u32) as i32, m as i8, d as i8) } } diff --git a/benches/iai.rs b/benches/iai.rs index 21e0b13..a33ad8e 100644 --- a/benches/iai.rs +++ b/benches/iai.rs @@ -2,7 +2,7 @@ use iai_callgrind::{black_box, library_benchmark, library_benchmark_group, main} use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[library_benchmark] -fn iai_rd_to_date() -> (i32, u8, u8) { +fn iai_rd_to_date() -> (i32, i8, i8) { datealgo::rd_to_date(black_box(19489)) } @@ -12,27 +12,27 @@ fn iai_date_to_rd() -> i32 { } #[library_benchmark] -fn iai_rd_to_weekday() -> u8 { +fn iai_rd_to_weekday() -> i8 { datealgo::rd_to_weekday(black_box(19489)) } #[library_benchmark] -fn iai_date_to_weekday() -> u8 { +fn iai_date_to_weekday() -> i8 { datealgo::date_to_weekday(black_box((2023, 5, 12))) } #[library_benchmark] -fn iai_next_date() -> (i32, u8, u8) { +fn iai_next_date() -> (i32, i8, i8) { datealgo::next_date(black_box((2023, 5, 12))) } #[library_benchmark] -fn iai_prev_date() -> (i32, u8, u8) { +fn iai_prev_date() -> (i32, i8, i8) { datealgo::prev_date(black_box((2023, 5, 12))) } #[library_benchmark] -fn iai_secs_to_dhms() -> (i32, u8, u8, u8) { +fn iai_secs_to_dhms() -> (i32, i8, i8, i8) { datealgo::secs_to_dhms(black_box(1684574678i64)) } @@ -42,7 +42,7 @@ fn iai_dhms_to_secs() -> i64 { } #[library_benchmark] -fn iai_secs_to_datetime() -> (i32, u8, u8, u8, u8, u8) { +fn iai_secs_to_datetime() -> (i32, i8, i8, i8, i8, i8) { datealgo::secs_to_datetime(black_box(1684574678i64)) } @@ -57,7 +57,7 @@ fn iai_is_leap_year() -> bool { } #[library_benchmark] -fn iai_days_in_month() -> u8 { +fn iai_days_in_month() -> i8 { datealgo::days_in_month(black_box(2000), black_box(2)) } @@ -72,7 +72,7 @@ fn iai_secs_to_systemtime() -> Option { } #[library_benchmark] -fn iai_systemtime_to_datetime() -> Option<(i32, u8, u8, u8, u8, u8, u32)> { +fn iai_systemtime_to_datetime() -> Option<(i32, i8, i8, i8, i8, i8, u32)> { datealgo::systemtime_to_datetime(black_box(UNIX_EPOCH + Duration::from_secs(1684574678))) } diff --git a/tests/quickcheck.rs b/tests/quickcheck.rs index a0443aa..d63af85 100644 --- a/tests/quickcheck.rs +++ b/tests/quickcheck.rs @@ -6,12 +6,12 @@ quickcheck! { fn quickcheck_rd_to_date(d: time::Date) -> TestResult { let rd = d.to_julian_day() - 2440588; let a = rd_to_date(rd); - let b = (d.year() as i32, d.month() as u8, d.day() as u8); + let b = (d.year() as i32, d.month() as i8, d.day() as i8); TestResult::from_bool(a == b) } fn quickcheck_date_to_rd(d: time::Date) -> TestResult { - let a = (d.year() as i32, d.month() as u8, d.day() as u8); + let a = (d.year() as i32, d.month() as i8, d.day() as i8); let rd = date_to_rd(a); TestResult::from_bool(rd == d.to_julian_day() - 2440588) } @@ -20,7 +20,7 @@ quickcheck! { let rd = d.to_julian_day() - 2440588; let wd_a = rd_to_weekday(rd); let wd_b = d.weekday().number_from_monday(); - TestResult::from_bool(wd_a as u8 == wd_b) + TestResult::from_bool(wd_a == wd_b as i8) } fn quickcheck_date_to_weekday(d: time::Date) -> TestResult { @@ -28,7 +28,7 @@ quickcheck! { let a = rd_to_date(rd); let wd_a = date_to_weekday(a); let wd_b = d.weekday().number_from_monday(); - TestResult::from_bool(wd_a as u8 == wd_b) + TestResult::from_bool(wd_a == wd_b as i8) } fn quickcheck_is_leap_year(y: i32) -> TestResult { @@ -40,7 +40,7 @@ quickcheck! { TestResult::from_bool(leap_a == leap_b) } - fn quickcheck_days_in_month(y: i32, m: u8) -> TestResult { + fn quickcheck_days_in_month(y: i32, m: i8) -> TestResult { if y < datealgo::YEAR_MIN || y > datealgo::YEAR_MAX { return TestResult::discard(); } @@ -48,18 +48,18 @@ quickcheck! { return TestResult::discard(); } let days_a = datealgo::days_in_month(y, m); - let days_b = time::util::days_in_year_month(y, m.try_into().unwrap()); - TestResult::from_bool(days_a == days_b) + let days_b = time::util::days_in_year_month(y, (m as u8).try_into().unwrap()); + TestResult::from_bool(days_a == days_b as i8) } fn quickcheck_next_date(d: time::Date) -> TestResult { if d == time::Date::MAX { return TestResult::discard(); } - let date = (d.year() as i32, d.month() as u8, d.day() as u8); + let date = (d.year() as i32, d.month() as i8, d.day() as i8); let next_date = datealgo::next_date(date); let nd = d + time::Duration::days(1); - let expected_date = (nd.year() as i32, nd.month() as u8, nd.day() as u8); + let expected_date = (nd.year() as i32, nd.month() as i8, nd.day() as i8); TestResult::from_bool(next_date == expected_date) } @@ -67,10 +67,10 @@ quickcheck! { if d == time::Date::MIN { return TestResult::discard(); } - let date = (d.year() as i32, d.month() as u8, d.day() as u8); + let date = (d.year() as i32, d.month() as i8, d.day() as i8); let prev_date = datealgo::prev_date(date); let pd = d - time::Duration::days(1); - let expected_date = (pd.year() as i32, pd.month() as u8, pd.day() as u8); + let expected_date = (pd.year() as i32, pd.month() as i8, pd.day() as i8); TestResult::from_bool(prev_date == expected_date) } @@ -78,12 +78,12 @@ quickcheck! { let rd = d.to_julian_day() - 2440588; let a = rd_to_isoweekdate(rd); let (y, w, wd) = d.to_iso_week_date(); - TestResult::from_bool(a == (y, w as u8, wd.number_from_monday())) + TestResult::from_bool(a == (y, w as i8, wd.number_from_monday() as i8)) } fn quickcheck_isoweekdate_to_rd(d: time::Date) -> TestResult { let (y, w, wd) = d.to_iso_week_date(); - let rd = isoweekdate_to_rd((y, w as u8, wd.number_from_monday())); + let rd = isoweekdate_to_rd((y, w as i8, wd.number_from_monday() as i8)); TestResult::from_bool(rd == d.to_julian_day() - 2440588) } @@ -93,7 +93,7 @@ quickcheck! { } let weeks_a = datealgo::isoweeks_in_year(y); let weeks_b = time::util::weeks_in_year(y); - TestResult::from_bool(weeks_a == weeks_b) + TestResult::from_bool(weeks_a == weeks_b as i8) } fn quickcheck_systemtime_to_datetime(s: time::PrimitiveDateTime) -> TestResult { @@ -101,11 +101,11 @@ quickcheck! { let a = systemtime_to_datetime(s.into()).unwrap(); let b = ( s.year() as i32, - s.month() as u8, - s.day() as u8, - s.hour() as u8, - s.minute() as u8, - s.second() as u8, + s.month() as i8, + s.day() as i8, + s.hour() as i8, + s.minute() as i8, + s.second() as i8, s.nanosecond(), ); TestResult::from_bool(a == b) @@ -115,11 +115,11 @@ quickcheck! { let s = s.assume_utc(); let dt = ( s.year() as i32, - s.month() as u8, - s.day() as u8, - s.hour() as u8, - s.minute() as u8, - s.second() as u8, + s.month() as i8, + s.day() as i8, + s.hour() as i8, + s.minute() as i8, + s.second() as i8, s.nanosecond(), ); let a = datetime_to_systemtime(dt).unwrap(); From 6cc8e315b8c4b9a04c09c96692e1ba2589caf3d0 Mon Sep 17 00:00:00 2001 From: Nuutti Kotivuori Date: Tue, 6 Aug 2024 21:32:20 +0000 Subject: [PATCH 3/3] chore: Update asm after `i8` change --- asm/date_to_isoweekdate.asm | 49 +++++++++++++++-------------- asm/date_to_rd.asm | 47 ++++++++++++++-------------- asm/date_to_weekday.asm | 47 ++++++++++++++-------------- asm/datetime_to_secs.asm | 25 ++++++++------- asm/datetime_to_systemtime.asm | 57 +++++++++++++++++----------------- asm/days_in_month.asm | 2 +- asm/dhms_to_secs.asm | 25 +++++++-------- asm/isoweekdate_to_date.asm | 45 +++++++++++++-------------- asm/isoweekdate_to_rd.asm | 43 ++++++++++++------------- asm/next_date.asm | 8 ++--- asm/prev_date.asm | 4 +-- 11 files changed, 175 insertions(+), 177 deletions(-) diff --git a/asm/date_to_isoweekdate.asm b/asm/date_to_isoweekdate.asm index e610f1e..fd71806 100644 --- a/asm/date_to_isoweekdate.asm +++ b/asm/date_to_isoweekdate.asm @@ -1,30 +1,31 @@ datealgo::asm::date_to_isoweekdate: - movabs rax, 281474976710655 - and rax, rdi - mov rcx, rax - shr rcx, 32 - cmp cl, 3 - sbb edi, 0 - movzx edx, cl - lea esi, [rdx + 12] - cmp cl, 3 - cmovae esi, edx - shr rax, 40 - add edi, 1468000 - imul rcx, rdi, 1374389535 - mov rdx, rcx - shr rdx, 37 - imul edi, edi, 1461 - shr edi, 2 + mov rax, rdi + shr rax, 32 + movsx ecx, al + lea edx, [rcx + 12] + xor esi, esi + cmp al, 3 + setl sil + cmovge edx, ecx + mov eax, edi + sub eax, esi + add eax, 1468000 + imul rcx, rax, 1374389535 + mov rsi, rcx + shr rsi, 37 + shr rdi, 16 + sar edi, 24 + imul eax, eax, 1461 + shr eax, 2 shr rcx, 39 - imul esi, esi, 979 - add esi, -2919 - shr esi, 5 - sub eax, edx - add ecx, edi + imul edx, edx, 979 + add edx, -2919 + shr edx, 5 + sub edi, esi add ecx, eax - lea eax, [rcx + rsi] - add ecx, esi + add ecx, edi + lea eax, [rcx + rdx] + add ecx, edx add ecx, -307 movsxd rcx, ecx movabs rdx, 2635249153387078802 diff --git a/asm/date_to_rd.asm b/asm/date_to_rd.asm index 79b35f2..7a80a0c 100644 --- a/asm/date_to_rd.asm +++ b/asm/date_to_rd.asm @@ -1,28 +1,29 @@ datealgo::asm::date_to_rd: - movabs rax, 281474976710655 - and rax, rdi - mov rcx, rax - shr rcx, 32 - cmp cl, 3 - sbb edi, 0 - movzx edx, cl - lea esi, [rdx + 12] - cmp cl, 3 - cmovae esi, edx - shr rax, 40 - add edi, 1468000 - imul rcx, rdi, 1374389535 - mov rdx, rcx - shr rdx, 37 - imul edi, edi, 1461 - shr edi, 2 + mov rax, rdi + shr rax, 32 + movsx ecx, al + lea edx, [rcx + 12] + xor esi, esi + cmp al, 3 + cmovge edx, ecx + setl sil + mov eax, edi + sub eax, esi + add eax, 1468000 + imul rcx, rax, 1374389535 + mov rsi, rcx + shr rsi, 37 + shr rdi, 16 + sar edi, 24 + imul eax, eax, 1461 + shr eax, 2 shr rcx, 39 - imul esi, esi, 979 - add esi, -2919 - shr esi, 5 - sub eax, edx - add ecx, edi + imul edx, edx, 979 + add edx, -2919 + shr edx, 5 + sub edi, esi add ecx, eax - lea eax, [rsi + rcx] + add ecx, edi + lea eax, [rdx + rcx] add eax, -536895459 ret diff --git a/asm/date_to_weekday.asm b/asm/date_to_weekday.asm index e46d3bc..e701d0f 100644 --- a/asm/date_to_weekday.asm +++ b/asm/date_to_weekday.asm @@ -1,29 +1,30 @@ datealgo::asm::date_to_weekday: - movabs rax, 281474976710655 - and rax, rdi - mov rcx, rax - shr rcx, 32 - cmp cl, 3 - sbb edi, 0 - movzx edx, cl - lea esi, [rdx + 12] - cmp cl, 3 - cmovae esi, edx - shr rax, 40 - add edi, 1468000 - imul rcx, rdi, 1374389535 - mov rdx, rcx - shr rdx, 37 - lea edi, [rdi + 4*rdi] - shr edi, 2 + mov rax, rdi + shr rax, 32 + movsx ecx, al + lea edx, [rcx + 12] + xor esi, esi + cmp al, 3 + setl sil + cmovge edx, ecx + mov eax, edi + sub eax, esi + add eax, 1468000 + imul rcx, rax, 1374389535 + mov rsi, rcx + shr rsi, 37 + shr rdi, 16 + sar edi, 24 + lea eax, [rax + 4*rax] + shr eax, 2 shr rcx, 39 - imul esi, esi, 979 - add esi, -2855 - shr esi, 5 - sub eax, edx - add ecx, edi + imul edx, edx, 979 + add edx, -2855 + shr edx, 5 + sub edi, esi add ecx, eax - add ecx, esi + add ecx, edi + add ecx, edx imul eax, ecx, 613566756 shr eax, 29 ret diff --git a/asm/datetime_to_secs.asm b/asm/datetime_to_secs.asm index c0af942..76a5d9e 100644 --- a/asm/datetime_to_secs.asm +++ b/asm/datetime_to_secs.asm @@ -1,34 +1,35 @@ datealgo::asm::datetime_to_secs: mov ecx, dword ptr [rdi] - movzx eax, byte ptr [rdi + 4] - cmp eax, 3 - sbb ecx, 0 + movsx eax, byte ptr [rdi + 4] lea edx, [rax + 12] + xor esi, esi cmp eax, 3 - cmovae edx, eax - movzx esi, byte ptr [rdi + 5] + setl sil + movsx r8d, byte ptr [rdi + 5] + cmovge edx, eax + sub ecx, esi add ecx, 1468000 imul rax, rcx, 1374389535 - mov r8, rax - shr r8, 37 + mov rsi, rax + shr rsi, 37 imul r9d, ecx, 1461 shr r9d, 2 shr rax, 39 imul ecx, edx, 979 add ecx, -2919 shr ecx, 5 - sub esi, r8d + sub r8d, esi add eax, r9d - add eax, esi + add eax, r8d lea edx, [rcx + rax] add edx, -307 cmp edx, 1073719447 ja .LBB9_1 add eax, ecx add eax, -536895459 - movzx ecx, byte ptr [rdi + 8] - movzx edx, byte ptr [rdi + 7] - movzx esi, byte ptr [rdi + 6] + movsx rcx, byte ptr [rdi + 8] + movsx rdx, byte ptr [rdi + 7] + movsx rsi, byte ptr [rdi + 6] cdqe imul rdi, rax, 86400 imul rsi, rsi, 3600 diff --git a/asm/datetime_to_systemtime.asm b/asm/datetime_to_systemtime.asm index 8976555..4ff3101 100644 --- a/asm/datetime_to_systemtime.asm +++ b/asm/datetime_to_systemtime.asm @@ -1,35 +1,36 @@ datealgo::asm::datetime_to_systemtime: - movzx eax, byte ptr [rdi + 4] - cmp eax, 3 - mov ecx, dword ptr [rdi] + movsx ecx, byte ptr [rdi + 4] + lea esi, [rcx + 12] + xor r8d, r8d + cmp ecx, 3 + setl r8b + movsx eax, byte ptr [rdi + 5] + mov r9d, dword ptr [rdi] mov edx, dword ptr [rdi + 12] - sbb ecx, 0 - lea esi, [rax + 12] - cmp eax, 3 - cmovae esi, eax - movzx r8d, byte ptr [rdi + 5] - add ecx, 1468000 - imul rax, rcx, 1374389535 - mov r9, rax - shr r9, 37 - imul r10d, ecx, 1461 - shr r10d, 2 - shr rax, 39 - imul ecx, esi, 979 - add ecx, -2919 - shr ecx, 5 - sub r8d, r9d - add eax, r10d - add eax, r8d - lea esi, [rcx + rax] - add esi, -307 - cmp esi, 1073719447 + cmovge esi, ecx + sub r9d, r8d + add r9d, 1468000 + imul rcx, r9, 1374389535 + mov r8, rcx + shr r8, 37 + imul r9d, r9d, 1461 + shr r9d, 2 + shr rcx, 39 + imul esi, esi, 979 + add esi, -2919 + shr esi, 5 + sub eax, r8d + add ecx, r9d + add ecx, eax + lea eax, [rsi + rcx] + add eax, -307 + cmp eax, 1073719447 ja .LBB20_1 - add eax, ecx + lea eax, [rsi + rcx] add eax, -536895459 - movzx ecx, byte ptr [rdi + 8] - movzx esi, byte ptr [rdi + 7] - movzx edi, byte ptr [rdi + 6] + movsx rcx, byte ptr [rdi + 8] + movsx rsi, byte ptr [rdi + 7] + movsx rdi, byte ptr [rdi + 6] cdqe imul rax, rax, 86400 imul rdi, rdi, 3600 diff --git a/asm/days_in_month.asm b/asm/days_in_month.asm index 83a7d77..8d510c1 100644 --- a/asm/days_in_month.asm +++ b/asm/days_in_month.asm @@ -13,7 +13,7 @@ datealgo::asm::days_in_month: ret .LBB11_2: mov eax, esi - shr al, 3 + sar al, 3 xor al, sil or al, 30 ret diff --git a/asm/dhms_to_secs.asm b/asm/dhms_to_secs.asm index 7ab352c..3fd3fb2 100644 --- a/asm/dhms_to_secs.asm +++ b/asm/dhms_to_secs.asm @@ -2,22 +2,21 @@ datealgo::asm::dhms_to_secs: lea eax, [rdi + 536895152] cmp eax, 1073719447 ja .LBB7_1 + movsxd rax, edi + imul rcx, rax, 86400 mov rax, rdi - shr rax, 48 - movzx eax, al - mov rcx, rdi - shr rcx, 40 - mov rdx, rdi - shr rdx, 32 - movsxd rsi, edi - imul rsi, rsi, 86400 - add rsi, rax - movzx eax, dl + shr rax, 32 + movsx rax, al imul rdx, rax, 3600 - add rdx, rsi - movzx eax, cl - imul rax, rax, 60 + mov rax, rdi + shr rax, 40 + movsx rax, al + imul rsi, rax, 60 + shr rdi, 48 + movsx rax, dil + add rax, rcx add rax, rdx + add rax, rsi ret .LBB7_1: xor eax, eax diff --git a/asm/isoweekdate_to_date.asm b/asm/isoweekdate_to_date.asm index c6f6f50..b63d8c4 100644 --- a/asm/isoweekdate_to_date.asm +++ b/asm/isoweekdate_to_date.asm @@ -1,33 +1,30 @@ datealgo::asm::isoweekdate_to_date: - mov rax, rdi - shr rax, 32 - mov rcx, rdi - shr rcx, 40 - movzx ecx, cl - add edi, 1467999 - imul rdx, rdi, 1374389535 - mov rsi, rdx - shr rsi, 37 - imul edi, edi, 1461 - shr edi, 2 - shr rdx, 39 - sub edx, esi - movzx eax, al - lea esi, [8*rax] - sub esi, eax - add esi, ecx - add esi, edi - add esi, edx - lea eax, [rdx + rdi] + lea ecx, [rdi + 1467999] + imul rax, rcx, 1374389535 + mov rdx, rax + shr rdx, 37 + imul ecx, ecx, 1461 + shr ecx, 2 + shr rax, 39 + sub eax, edx + mov rdx, rdi + shr rdx, 8 + sar edx, 24 + lea esi, [8*rdx] + sub esi, edx + shr rdi, 16 + sar edi, 24 + add edi, esi + add edi, ecx + add edi, eax + add eax, ecx add eax, 4 cdqe movabs rcx, 2635249153387078802 imul rcx, rax shr rcx, 61 - dec ecx - movzx eax, cl - sub esi, eax - lea eax, [4*rsi + 1207] + sub edi, ecx + lea eax, [4*rdi + 1211] imul rcx, rax, 963315389 shr rcx, 47 imul edx, ecx, 146097 diff --git a/asm/isoweekdate_to_rd.asm b/asm/isoweekdate_to_rd.asm index 4cf2530..bd2040a 100644 --- a/asm/isoweekdate_to_rd.asm +++ b/asm/isoweekdate_to_rd.asm @@ -1,31 +1,28 @@ datealgo::asm::isoweekdate_to_rd: - mov rax, rdi - shr rax, 32 - mov rcx, rdi - shr rcx, 40 - movzx ecx, cl - add edi, 1467999 - imul rdx, rdi, 1374389535 - mov rsi, rdx - shr rsi, 37 - imul edi, edi, 1461 - shr edi, 2 - shr rdx, 39 - sub edx, esi - movzx esi, al - lea eax, [8*rsi] - sub eax, esi - add eax, ecx + lea eax, [rdi + 1467999] + imul rcx, rax, 1374389535 + mov rdx, rcx + shr rdx, 37 + imul esi, eax, 1461 + shr esi, 2 + shr rcx, 39 + sub ecx, edx + mov rdx, rdi + shr rdx, 8 + sar edx, 24 + lea eax, [8*rdx] + sub eax, edx + shr rdi, 16 + sar edi, 24 add eax, edi - add eax, edx - lea ecx, [rdx + rdi] + add eax, esi + add eax, ecx + add ecx, esi add ecx, 4 movsxd rcx, ecx movabs rdx, 2635249153387078802 imul rdx, rcx shr rdx, 61 - dec edx - movzx ecx, dl - sub eax, ecx - add eax, -536895157 + sub eax, edx + add eax, -536895156 ret diff --git a/asm/next_date.asm b/asm/next_date.asm index 74e7b3d..20a49c8 100644 --- a/asm/next_date.asm +++ b/asm/next_date.asm @@ -7,7 +7,7 @@ datealgo::asm::next_date: mov rsi, rdi shr rsi, 40 cmp sil, 28 - jae .LBB4_1 + jge .LBB4_1 .LBB4_3: add rdi, rcx movabs rcx, 280375465082880 @@ -36,13 +36,13 @@ datealgo::asm::next_date: jmp .LBB4_7 .LBB4_2: mov r8d, edx - shr r8b, 3 + sar r8b, 3 xor r8b, dl or r8b, 30 cmp r8b, sil - ja .LBB4_3 + jg .LBB4_3 cmp dl, 12 - jae .LBB4_5 + jge .LBB4_5 .LBB4_7: inc rdx jmp .LBB4_8 diff --git a/asm/prev_date.asm b/asm/prev_date.asm index 654ca93..12d5e9b 100644 --- a/asm/prev_date.asm +++ b/asm/prev_date.asm @@ -6,12 +6,12 @@ datealgo::asm::prev_date: mov rdx, rdi shr rdx, 40 cmp dl, 1 - jbe .LBB5_1 + jle .LBB5_1 dec dl jmp .LBB5_6 .LBB5_1: cmp cl, 1 - jbe .LBB5_2 + jle .LBB5_2 dec cl cmp cl, 2 jne .LBB5_5