concrete_commons/numeric/
mod.rs

1//! Generic numeric types.
2//!
3//! This module contains types and traits to manipulate numeric types in a generic manner. For
4//! instance, in the standard library, the `f32` and `f64` trait share a lot of methods of the
5//! same name and same semantics. Still, it is not possible to use them generically. This module
6//! provides the [`FloatingPoint`] trait, implemented by both of those type, to remedy the
7//! situation.
8//!
9//! # Note
10//!
11//! The current implementation of those traits does not strive to be general, in the sense that
12//! not all the common methods of the same kind of types are exposed. Only were included the ones
13//! that are used in the rest of the library.
14
15pub use float::*;
16pub use signed::*;
17pub use unsigned::*;
18
19mod float;
20mod signed;
21mod unsigned;
22
23/// A trait implemented by any generic numeric type suitable for computations.
24pub trait Numeric: Sized + Copy + PartialEq + PartialOrd {
25    /// This size of the type in bits.
26    const BITS: usize;
27
28    /// The null element of the type.
29    const ZERO: Self;
30
31    /// The identity element of the type.
32    const ONE: Self;
33
34    /// A value of two.
35    const TWO: Self;
36
37    /// The largest value that can be encoded by the type.
38    const MAX: Self;
39}
40
41/// A trait that allows to generically cast one type from another.
42///
43/// This type is similar to the [`std::convert::From`] trait, but the conversion between the two
44/// types is deferred to the individual `as` casting. If in doubt about the semantics of such a
45/// casting, refer to
46/// [the rust reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions).
47pub trait CastFrom<Input> {
48    fn cast_from(input: Input) -> Self;
49}
50
51/// A trait that allows to generically cast one type into another.
52///
53/// This type is similar to the [`std::convert::Into`] trait, but the conversion between the two
54/// types is deferred to the individual `as` casting. If in doubt about the semantics of such a
55/// casting, refer to
56/// [the rust reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions).
57pub trait CastInto<Output> {
58    fn cast_into(self) -> Output;
59}
60
61impl<Input, Output> CastInto<Output> for Input
62where
63    Output: CastFrom<Input>,
64{
65    fn cast_into(self) -> Output {
66        Output::cast_from(self)
67    }
68}
69
70macro_rules! implement_cast {
71    ($Input:ty, {$($Output:ty),*}) => {
72        $(
73        impl CastFrom<$Input> for $Output {
74            fn cast_from(input: $Input) -> $Output {
75                input as $Output
76            }
77        }
78        )*
79    };
80    ($Input: ty) => {
81        implement_cast!($Input, {f32, f64, usize, u8, u16, u32, u64, u128, isize, i8, i16, i32,
82        i64, i128});
83    };
84    ($($Input: ty),*) => {
85        $(
86        implement_cast!($Input);
87        )*
88    }
89}
90
91implement_cast!(f32, f64, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
92
93impl<Num> CastFrom<bool> for Num
94where
95    Num: Numeric,
96{
97    fn cast_from(input: bool) -> Num {
98        if input {
99            Num::ONE
100        } else {
101            Num::ZERO
102        }
103    }
104}