use crate::extended::Extended;
use ::core::num::NonZeroU8;
use hifitime::{MonthName, Weekday};
fn montu008_ceil(m: Extended<MonthName>) -> u8 {
match m {
Extended::NegInf => 0,
Extended::Finite(month) => month as u8 + 1,
Extended::PosInf => 13,
}
}
fn montu008_inner(u: u8) -> Extended<MonthName> {
match u {
0 => Extended::NegInf,
n @ 1..=12 => Extended::Finite(MonthName::from(n)),
_ => Extended::PosInf,
}
}
crate::conn_l! {
pub MONTU008 : Extended<MonthName> => u8 {
ceil: montu008_ceil,
inner: montu008_inner,
}
}
fn montn008_ceil(m: Extended<MonthName>) -> NonZeroU8 {
let n = match m {
Extended::NegInf => 1,
Extended::Finite(month) => month as u8 + 1,
Extended::PosInf => 13,
};
match NonZeroU8::new(n) {
Some(nz) => nz,
None => unreachable!("ceil produces values in [1, 13], never zero"),
}
}
fn montn008_inner(nz: NonZeroU8) -> Extended<MonthName> {
let n = nz.get();
match n {
1..=12 => Extended::Finite(MonthName::from(n)),
_ => Extended::PosInf,
}
}
crate::conn_l! {
pub MONTN008 : Extended<MonthName> => NonZeroU8 {
ceil: montn008_ceil,
inner: montn008_inner,
}
}
fn wkdyu008_ceil(w: Extended<Weekday>) -> u8 {
match w {
Extended::NegInf => 0,
Extended::Finite(day) => day as u8,
Extended::PosInf => 7,
}
}
fn wkdyu008_inner(u: u8) -> Extended<Weekday> {
match u {
0..=6 => Extended::Finite(Weekday::from(u)),
_ => Extended::PosInf,
}
}
crate::conn_l! {
pub WKDYU008 : Extended<Weekday> => u8 {
ceil: wkdyu008_ceil,
inner: wkdyu008_inner,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(unused_imports)]
use crate::conn::{ConnL, ConnR};
use crate::prop::arb::{arb_extended_hifi_month, arb_extended_hifi_weekday};
use crate::prop::conn as conn_laws;
use proptest::prelude::*;
fn arb_u8_calendar() -> impl Strategy<Value = u8> {
prop_oneof![
1 => Just(0_u8),
1 => Just(1_u8),
1 => Just(6_u8),
1 => Just(7_u8),
1 => Just(12_u8),
1 => Just(13_u8),
1 => Just(254_u8),
1 => Just(u8::MAX),
8 => any::<u8>(),
]
}
fn arb_nz_u8_calendar() -> impl Strategy<Value = NonZeroU8> {
prop_oneof![
1 => Just(NonZeroU8::new(1).unwrap()),
1 => Just(NonZeroU8::new(12).unwrap()),
1 => Just(NonZeroU8::new(13).unwrap()),
1 => Just(NonZeroU8::new(254).unwrap()),
1 => Just(NonZeroU8::new(u8::MAX).unwrap()),
8 => (1u8..=u8::MAX).prop_map(|n| NonZeroU8::new(n).unwrap()),
]
}
#[test]
fn montu008_january_is_one() {
assert_eq!(MONTU008.ceil(Extended::Finite(MonthName::January)), 1);
assert_eq!(MONTU008.upper(1), Extended::Finite(MonthName::January));
}
#[test]
fn montu008_december_is_twelve() {
assert_eq!(MONTU008.ceil(Extended::Finite(MonthName::December)), 12);
assert_eq!(MONTU008.upper(12), Extended::Finite(MonthName::December));
}
#[test]
fn montu008_zero_saturates_neg_inf() {
assert_eq!(MONTU008.upper(0), Extended::NegInf);
}
#[test]
fn montu008_thirteen_saturates_pos_inf() {
assert_eq!(MONTU008.upper(13), Extended::PosInf);
}
#[test]
fn montu008_extended_extremes() {
assert_eq!(MONTU008.ceil(Extended::NegInf), 0);
assert_eq!(MONTU008.ceil(Extended::PosInf), 13);
}
#[test]
fn montu008_round_trip_all_months() {
let months = [
MonthName::January,
MonthName::February,
MonthName::March,
MonthName::April,
MonthName::May,
MonthName::June,
MonthName::July,
MonthName::August,
MonthName::September,
MonthName::October,
MonthName::November,
MonthName::December,
];
for (i, &m) in months.iter().enumerate() {
let canon = (i + 1) as u8;
assert_eq!(MONTU008.ceil(Extended::Finite(m)), canon);
assert_eq!(MONTU008.upper(canon), Extended::Finite(m));
}
}
#[test]
fn montn008_january_is_nonzero_one() {
let one = NonZeroU8::new(1).unwrap();
assert_eq!(MONTN008.ceil(Extended::Finite(MonthName::January)), one);
}
#[test]
fn montn008_december_is_nonzero_twelve() {
let twelve = NonZeroU8::new(12).unwrap();
assert_eq!(MONTN008.ceil(Extended::Finite(MonthName::December)), twelve);
}
#[test]
fn montn008_thirteen_saturates_pos_inf() {
let thirteen = NonZeroU8::new(13).unwrap();
assert_eq!(MONTN008.upper(thirteen), Extended::PosInf);
}
#[test]
fn montn008_neg_inf_collapses_to_one() {
let one = NonZeroU8::new(1).unwrap();
assert_eq!(MONTN008.ceil(Extended::NegInf), one);
}
#[test]
fn montn008_one_recovers_january_not_neg_inf() {
let one = NonZeroU8::new(1).unwrap();
assert_eq!(MONTN008.upper(one), Extended::Finite(MonthName::January),);
}
#[test]
fn wkdyu008_monday_is_zero() {
assert_eq!(WKDYU008.ceil(Extended::Finite(Weekday::Monday)), 0);
assert_eq!(WKDYU008.upper(0), Extended::Finite(Weekday::Monday));
}
#[test]
fn wkdyu008_sunday_is_six() {
assert_eq!(WKDYU008.ceil(Extended::Finite(Weekday::Sunday)), 6);
assert_eq!(WKDYU008.upper(6), Extended::Finite(Weekday::Sunday));
}
#[test]
fn wkdyu008_seven_saturates_pos_inf() {
assert_eq!(WKDYU008.upper(7), Extended::PosInf);
}
#[test]
fn wkdyu008_neg_inf_collapses_to_zero() {
assert_eq!(WKDYU008.ceil(Extended::NegInf), 0);
}
#[test]
fn wkdyu008_round_trip_all_weekdays() {
let weekdays = [
Weekday::Monday,
Weekday::Tuesday,
Weekday::Wednesday,
Weekday::Thursday,
Weekday::Friday,
Weekday::Saturday,
Weekday::Sunday,
];
for (i, &w) in weekdays.iter().enumerate() {
let canon = i as u8;
assert_eq!(WKDYU008.ceil(Extended::Finite(w)), canon);
assert_eq!(WKDYU008.upper(canon), Extended::Finite(w));
}
}
proptest! {
#[test]
fn montu008_galois_l(a in arb_extended_hifi_month(), b in arb_u8_calendar()) {
prop_assert!(conn_laws::galois_l(&MONTU008, a, b));
}
#[test]
fn montu008_closure_l(a in arb_extended_hifi_month()) {
prop_assert!(conn_laws::closure_l(&MONTU008, a));
}
#[test]
fn montu008_kernel_l(b in arb_u8_calendar()) {
prop_assert!(conn_laws::kernel_l(&MONTU008, b));
}
#[test]
fn montu008_monotone_l(a1 in arb_extended_hifi_month(),
a2 in arb_extended_hifi_month()) {
prop_assert!(conn_laws::monotone_l(&MONTU008, a1, a2));
}
#[test]
fn montu008_idempotent(a in arb_extended_hifi_month()) {
prop_assert!(conn_laws::idempotent(&MONTU008, a));
}
#[test]
fn montn008_galois_l(a in arb_extended_hifi_month(), b in arb_nz_u8_calendar()) {
prop_assert!(conn_laws::galois_l(&MONTN008, a, b));
}
#[test]
fn montn008_closure_l(a in arb_extended_hifi_month()) {
prop_assert!(conn_laws::closure_l(&MONTN008, a));
}
#[test]
fn montn008_kernel_l(b in arb_nz_u8_calendar()) {
prop_assert!(conn_laws::kernel_l(&MONTN008, b));
}
#[test]
fn montn008_monotone_l(a1 in arb_extended_hifi_month(),
a2 in arb_extended_hifi_month()) {
prop_assert!(conn_laws::monotone_l(&MONTN008, a1, a2));
}
#[test]
fn montn008_idempotent(a in arb_extended_hifi_month()) {
prop_assert!(conn_laws::idempotent(&MONTN008, a));
}
#[test]
fn wkdyu008_galois_l(a in arb_extended_hifi_weekday(), b in arb_u8_calendar()) {
prop_assert!(conn_laws::galois_l(&WKDYU008, a, b));
}
#[test]
fn wkdyu008_closure_l(a in arb_extended_hifi_weekday()) {
prop_assert!(conn_laws::closure_l(&WKDYU008, a));
}
#[test]
fn wkdyu008_kernel_l(b in arb_u8_calendar()) {
prop_assert!(conn_laws::kernel_l(&WKDYU008, b));
}
#[test]
fn wkdyu008_monotone_l(a1 in arb_extended_hifi_weekday(),
a2 in arb_extended_hifi_weekday()) {
prop_assert!(conn_laws::monotone_l(&WKDYU008, a1, a2));
}
#[test]
fn wkdyu008_idempotent(a in arb_extended_hifi_weekday()) {
prop_assert!(conn_laws::idempotent(&WKDYU008, a));
}
}
}