1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use num_traits::ops::checked::CheckedAdd;
use num_traits::Num;
use core::cmp::PartialOrd;
use core::ops::{Div, Neg, Sub, SubAssign};
#[must_use]
pub fn increment_overflow<T: Num + CheckedAdd + Copy>(ip: &mut T, j: T) -> bool {
let res = ip.checked_add(&j);
if let Some(value) = res {
*ip = value;
false
} else {
true
}
}
pub fn normalize_overflow<T>(
ip: &mut T,
unit: &mut T,
base: T,
) -> bool where T: Num
+ Sub<Output = T>
+ Div<Output = T>
+ Neg<Output = T>
+ CheckedAdd
+ SubAssign
+ PartialOrd
+ Copy {
let time_delta = if *unit >= T::zero() {
*unit / base
} else {
-T::one() - (-T::one() - *unit) / base
};
*unit -= time_delta * base;
increment_overflow(ip, time_delta)
}
#[inline]
pub fn is_leap_year(y: i64) -> bool {
((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)
}
#[inline]
fn get_leap_days_not_neg(y: i64) -> i64 {
y / 4 - y / 100 + y / 400
}
#[inline]
pub fn get_leap_days(y: i64) -> i64 {
if y < 0 {
-1 - get_leap_days_not_neg(-1 - y)
} else {
get_leap_days_not_neg(y)
}
}
#[cfg(test)]
mod test {
#[test]
fn test_leap_year() {
use crate::utils::is_leap_year;
assert_eq!(is_leap_year(-100), false);
assert_eq!(is_leap_year(0), true);
assert_eq!(is_leap_year(1970), false);
assert_eq!(is_leap_year(1980), true);
assert_eq!(is_leap_year(1990), false);
assert_eq!(is_leap_year(2000), true);
assert_eq!(is_leap_year(2010), false);
assert_eq!(is_leap_year(2020), true);
}
#[test]
fn test_get_leap_days() {
use crate::utils::get_leap_days;
assert_eq!(get_leap_days(12), 3);
assert_eq!(get_leap_days(8), 2);
assert_eq!(get_leap_days(4), 1);
assert_eq!(get_leap_days(1), 0);
assert_eq!(get_leap_days(0), 0);
assert_eq!(get_leap_days(-1), -1);
}
}