tfhe/core_crypto/commons/numeric/
mod.rs

1//! Generic numeric traits.
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:
25    Sized
26    + Copy
27    + PartialEq
28    + PartialOrd
29    + CastFrom<Self>
30    + bytemuck::Pod
31    + std::fmt::Debug
32    + Sync
33    + Send
34    + 'static
35{
36    /// This size of the type in bits.
37    const BITS: usize;
38
39    /// The null element of the type.
40    const ZERO: Self;
41
42    /// The identity element of the type.
43    const ONE: Self;
44
45    /// A value of two.
46    const TWO: Self;
47
48    /// The largest value that can be encoded by the type.
49    const MAX: Self;
50}
51
52pub trait UnsignedNumeric: Numeric {
53    /// The signed type of the same precision
54    ///
55    /// The name is long and explicit to avoid clash with the
56    /// same associated type in [UnsignedInteger]
57    type NumericSignedType: SignedNumeric<NumericUnsignedType = Self> + CastFrom<Self>;
58}
59pub trait SignedNumeric: Numeric {
60    /// The unsigned type of the same precision
61    ///
62    /// The name is long and explicit to avoid clash with the
63    /// same associated type in [SignedInteger]
64    type NumericUnsignedType: UnsignedNumeric<NumericSignedType = Self> + CastFrom<Self>;
65}
66
67/// A trait that allows to generically cast one type from another.
68///
69/// This type is similar to the [`std::convert::From`] trait, but the conversion between the two
70/// types is deferred to the individual `as` casting. If in doubt about the semantics of such a
71/// casting, refer to
72/// [the rust reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions).
73pub trait CastFrom<Input> {
74    fn cast_from(input: Input) -> Self;
75}
76
77/// A trait that allows to generically cast one type into another.
78///
79/// This type is similar to the [`std::convert::Into`] trait, but the conversion between the two
80/// types is deferred to the individual `as` casting. If in doubt about the semantics of such a
81/// casting, refer to
82/// [the rust reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions).
83pub trait CastInto<Output> {
84    fn cast_into(self) -> Output;
85}
86
87impl<Input, Output> CastInto<Output> for Input
88where
89    Output: CastFrom<Input>,
90{
91    fn cast_into(self) -> Output {
92        Output::cast_from(self)
93    }
94}
95
96macro_rules! implement_cast {
97    ($Input:ty, {$($Output:ty),*}) => {
98        $(
99        impl CastFrom<$Input> for $Output {
100            #[inline]
101            fn cast_from(input: $Input) -> $Output {
102                input as $Output
103            }
104        }
105        )*
106    };
107    ($Input: ty) => {
108        implement_cast!($Input, {f32, f64, usize, u8, u16, u32, u64, u128, isize, i8, i16, i32,
109        i64, i128});
110    };
111    ($($Input: ty),*) => {
112        $(
113        implement_cast!($Input);
114        )*
115    }
116}
117
118implement_cast!(f32, f64, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
119
120impl<Num> CastFrom<bool> for Num
121where
122    Num: Numeric,
123{
124    #[inline]
125    fn cast_from(input: bool) -> Num {
126        if input {
127            Num::ONE
128        } else {
129            Num::ZERO
130        }
131    }
132}
133
134pub trait OverflowingAdd<Rhs> {
135    type Output;
136
137    fn overflowing_add(self, other: Rhs) -> (Self::Output, bool);
138}