1use num_traits::ToPrimitive;
5
6#[inline]
7pub const fn triangle(n: u32) -> u32 {
8 n.saturating_mul(n + 1) / 2
9}
10
11pub fn nearest_triangle(value: impl Into<f64>) -> u32 {
12 let value: f64 = value.into();
13 let delta = 1.0 + (8.0 * value);
14 if !delta.is_finite() || delta < 0.0 {
15 return 0;
16 }
17
18 f64::midpoint(-1.0, delta.sqrt())
19 .floor()
20 .max(0.0)
21 .to_u32()
22 .unwrap_or(0)
23}
24
25#[cfg(test)]
26mod tests {
27 #[test]
28 fn triangle() {
29 assert_eq!(super::triangle(0), 0);
30 assert_eq!(super::triangle(1), 1);
31 assert_eq!(super::triangle(2), 3);
32 assert_eq!(super::triangle(3), 6);
33 assert_eq!(super::triangle(4), 10);
34 assert_eq!(super::triangle(5), 15);
35 assert_eq!(super::triangle(6), 21);
36 assert_eq!(super::triangle(7), 28);
37 assert_eq!(super::triangle(8), 36);
38 assert_eq!(super::triangle(9), 45);
39 assert_eq!(super::triangle(10), 55);
40 }
41
42 #[test]
43 fn nearest_triangle() {
44 assert_eq!(super::nearest_triangle(0u32), 0);
45 assert_eq!(super::nearest_triangle(1u32), 1);
46 assert_eq!(super::nearest_triangle(2u32), 1);
47 assert_eq!(super::nearest_triangle(3u32), 2);
48 assert_eq!(super::nearest_triangle(4u32), 2);
49 assert_eq!(super::nearest_triangle(5u32), 2);
50 assert_eq!(super::nearest_triangle(6u32), 3);
51 assert_eq!(super::nearest_triangle(7u32), 3);
52 assert_eq!(super::nearest_triangle(8u32), 3);
53 assert_eq!(super::nearest_triangle(9u32), 3);
54 assert_eq!(super::nearest_triangle(10u32), 4);
55
56 assert_eq!(super::nearest_triangle(-1i32), 0);
57 assert_eq!(super::nearest_triangle(-1.0f64), 0);
58
59 assert_eq!(super::nearest_triangle(f64::NAN), 0);
60 assert_eq!(super::nearest_triangle(f64::INFINITY), 0);
61 assert_eq!(super::nearest_triangle(f64::NEG_INFINITY), 0);
62 }
63}