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
use std::fmt::Debug;
use bevy_reflect::TypePath;
use crate::Float;

/// Rounding method for a floating point number.
pub trait Rounding: TypePath + Default + Debug + Copy + Send + Sync + 'static {
    /// Rounds to the an integer.
    fn round<F: Float>(input: F) -> F;
}

/// Rounds to 0.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, TypePath)]
pub struct Truncate;

impl Rounding for Truncate {
    fn round<F: Float>(input: F) -> F {
        input.trunc()
    }
}

/// Rounds to the largest integer smaller than the float.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, TypePath)]
pub struct Floor;

impl Rounding for Floor {
    fn round<F: Float>(input: F) -> F {
        input.floor()
    }
}

/// Rounds to the smallest integer larget than the float.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, TypePath)]
pub struct Ceil;

impl Rounding for Ceil {
    fn round<F: Float>(input: F) -> F {
        input.ceil()
    }
}

/// Rounds to the nearest integer.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, TypePath)]
pub struct Round;

impl Rounding for Round {
    fn round<F: Float>(input: F) -> F {
        input.round()
    }
}

/// Rounds `x > 0` to at least `1`,
/// rounds `x < 0` to at most `-1`.
/// rounds `x == 0` to `0`.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, TypePath)]
pub struct TruncateSigned;

impl Rounding for TruncateSigned {
    fn round<F: Float>(input: F) -> F {
        if input > F::ZERO {
            input.trunc().max(F::ONE)
        } else if input < F::ZERO {
            input.trunc().min(F::ZERO - F::ONE)
        } else {
            input
        }
    }
}