Skip to main content

nil_num/
triangle.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use 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}