concrete_commons/numeric/
signed.rs1use std::ops::{
2 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
3 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
4};
5
6use crate::numeric::CastInto;
7
8use super::{CastFrom, Numeric, UnsignedInteger};
9
10pub trait SignedInteger:
12 Numeric
13 + Neg<Output = Self>
14 + Add<Self, Output = Self>
15 + AddAssign<Self>
16 + Div<Self, Output = Self>
17 + DivAssign<Self>
18 + Mul<Self, Output = Self>
19 + MulAssign<Self>
20 + Rem<Self, Output = Self>
21 + RemAssign<Self>
22 + Sub<Self, Output = Self>
23 + SubAssign<Self>
24 + BitAnd<Self, Output = Self>
25 + BitAndAssign<Self>
26 + BitOr<Self, Output = Self>
27 + BitOrAssign<Self>
28 + BitXor<Self, Output = Self>
29 + BitXorAssign<Self>
30 + Not<Output = Self>
31 + Shl<usize, Output = Self>
32 + ShlAssign<usize>
33 + Shr<usize, Output = Self>
34 + ShrAssign<usize>
35 + CastFrom<f64>
36 + CastInto<f64>
37{
38 type Unsigned: UnsignedInteger<Signed = Self> + CastFrom<Self>;
40
41 fn into_unsigned(self) -> Self::Unsigned;
43
44 fn to_bits_string(&self, block_length: usize) -> String;
47}
48
49macro_rules! implement {
50 ($Type: tt, $UnsignedType:ty, $bits:expr) => {
51 impl Numeric for $Type {
52 const BITS: usize = $bits;
53 const ZERO: Self = 0;
54 const ONE: Self = 1;
55 const TWO: Self = 2;
56 const MAX: Self = <$Type>::MAX;
57 }
58 impl SignedInteger for $Type {
59 type Unsigned = $UnsignedType;
60 fn into_unsigned(self) -> Self::Unsigned {
61 Self::Unsigned::cast_from(self)
62 }
63 fn to_bits_string(&self, break_every: usize) -> String {
64 let mut strn = match <$Type as Numeric>::BITS {
65 8 => format!("{:08b}", self),
66 16 => format!("{:016b}", self),
67 32 => format!("{:032b}", self),
68 64 => format!("{:064b}", self),
69 128 => format!("{:0128b}", self),
70 _ => unreachable!(),
71 };
72 for i in (1..(<$Type as Numeric>::BITS / break_every)).rev() {
73 strn.insert(i * break_every, ' ');
74 }
75 strn
76 }
77 }
78 };
79}
80
81implement!(i8, u8, 8);
82implement!(i16, u16, 16);
83implement!(i32, u32, 32);
84implement!(i64, u64, 64);
85implement!(i128, u128, 128);
86
87#[cfg(test)]
88mod test {
89 use super::*;
90
91 #[test]
92 fn test_sint8_binary_rep() {
93 let a: i8 = -100;
94 let b = a.to_bits_string(4);
95 assert_eq!(b, "1001 1100".to_string());
96 }
97
98 #[test]
99 fn test_sint16_binary_rep() {
100 let a: i16 = -25702;
101 let b = a.to_bits_string(4);
102 assert_eq!(b, "1001 1011 1001 1010".to_string());
103 }
104
105 #[test]
106 fn test_sint32_binary_rep() {
107 let a: i32 = -1684411356;
108 let b = a.to_bits_string(4);
109 assert_eq!(b, "1001 1011 1001 1001 1110 1100 0010 0100".to_string());
110 }
111
112 #[test]
113 fn test_sint64_binary_rep() {
114 let a: i64 = -7_234_491_689_707_068_824;
115 let b = a.to_bits_string(4);
116 assert_eq!(
117 b,
118 "1001 1011 1001 1001 1110 1100 0010 0011 \
119 0110 0000 0111 1110 1010 0010 0110 1000"
120 .to_string()
121 );
122 }
123
124 #[test]
125 fn test_sint128_binary_rep() {
126 let a: i128 = -124_282_366_920_938_463_463_374_121_543_098_288_434;
127 let b = a.to_bits_string(4);
128 assert_eq!(
129 b,
130 "1010 0010 1000 0000 0001 0110 0011 1000 \
131 0111 0001 1001 1101 1111 1010 0100 1111 \
132 0100 0111 1100 1111 1110 1111 0110 1001 \
133 1100 0101 1001 0010 0011 0110 1100 1110"
134 .to_string()
135 );
136 }
137}