machine_check/types/
signed.rs

1use std::{
2    fmt::Debug,
3    ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub},
4};
5
6use mck::{
7    concr::{self, IntoMck},
8    forward::{Bitwise, HwArith, HwShift},
9};
10
11use crate::{traits::Ext, Bitvector, Unsigned};
12
13/// Signed bitvector.
14///
15/// The number of bits is specified in the generic parameter L.
16/// Signed bitvectors support bitwise operations and wrapping-arithmetic operations.
17/// Arithmetic bit extension is also possible (the sign bit is copied into any bits above it).
18/// Signed bitvectors be converted into [`Unsigned`] or [`Bitvector`].
19///
20/// Currently, it is not possible to create signed bitvectors directly, only convert into them.
21#[derive(Clone, Copy, Hash, PartialEq, Eq)]
22pub struct Signed<const L: u32>(pub(super) concr::Bitvector<L>);
23
24// --- BITWISE OPERATIONS ---
25
26impl<const L: u32> Not for Signed<L> {
27    type Output = Self;
28
29    fn not(self) -> Self::Output {
30        Self(self.0.bit_not())
31    }
32}
33
34impl<const L: u32> BitAnd<Signed<L>> for Signed<L> {
35    type Output = Self;
36
37    fn bitand(self, rhs: Signed<L>) -> Self::Output {
38        Self(self.0.bit_and(rhs.0))
39    }
40}
41impl<const L: u32> BitOr<Signed<L>> for Signed<L> {
42    type Output = Self;
43
44    fn bitor(self, rhs: Signed<L>) -> Self::Output {
45        Self(self.0.bit_or(rhs.0))
46    }
47}
48impl<const L: u32> BitXor<Signed<L>> for Signed<L> {
49    type Output = Self;
50
51    fn bitxor(self, rhs: Signed<L>) -> Self::Output {
52        Self(self.0.bit_xor(rhs.0))
53    }
54}
55
56// --- ARITHMETIC OPERATIONS ---
57
58impl<const L: u32> Add<Signed<L>> for Signed<L> {
59    type Output = Self;
60
61    fn add(self, rhs: Signed<L>) -> Self::Output {
62        Self(self.0.add(rhs.0))
63    }
64}
65
66impl<const L: u32> Sub<Signed<L>> for Signed<L> {
67    type Output = Self;
68
69    fn sub(self, rhs: Signed<L>) -> Self::Output {
70        Self(self.0.sub(rhs.0))
71    }
72}
73
74impl<const L: u32> Mul<Signed<L>> for Signed<L> {
75    type Output = Self;
76
77    fn mul(self, rhs: Signed<L>) -> Self::Output {
78        Self(self.0.mul(rhs.0))
79    }
80}
81
82impl<const L: u32> Div<Signed<L>> for Signed<L> {
83    type Output = Self;
84
85    fn div(self, rhs: Signed<L>) -> Self::Output {
86        Self(self.0.sdiv(rhs.0))
87    }
88}
89
90impl<const L: u32> Rem<Signed<L>> for Signed<L> {
91    type Output = Self;
92
93    fn rem(self, rhs: Signed<L>) -> Self::Output {
94        Self(self.0.srem(rhs.0))
95    }
96}
97
98impl<const L: u32> Shl<Signed<L>> for Signed<L> {
99    type Output = Self;
100
101    fn shl(self, rhs: Signed<L>) -> Self::Output {
102        Self(self.0.logic_shl(rhs.0))
103    }
104}
105
106impl<const L: u32> Shr<Signed<L>> for Signed<L> {
107    type Output = Self;
108
109    fn shr(self, rhs: Signed<L>) -> Self::Output {
110        Self(self.0.arith_shr(rhs.0))
111    }
112}
113
114// --- EXTENSION ---
115impl<const L: u32, const X: u32> Ext<X> for Signed<L> {
116    type Output = Signed<X>;
117
118    fn ext(self) -> Self::Output {
119        Signed::<X>(mck::forward::Ext::sext(self.0))
120    }
121}
122
123// --- ORDERING ---
124
125impl<const L: u32> PartialOrd for Signed<L> {
126    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
127        Some(self.cmp(other))
128    }
129}
130
131impl<const L: u32> Ord for Signed<L> {
132    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
133        self.0.signed_cmp(&other.0)
134    }
135}
136
137// --- CONVERSION ---
138impl<const L: u32> From<Unsigned<L>> for Signed<L> {
139    fn from(value: Unsigned<L>) -> Self {
140        Self(value.0)
141    }
142}
143
144impl<const L: u32> From<Bitvector<L>> for Signed<L> {
145    fn from(value: Bitvector<L>) -> Self {
146        Self(value.0)
147    }
148}
149
150// --- MISC ---
151
152impl<const L: u32> Debug for Signed<L> {
153    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154        std::fmt::Debug::fmt(&self.0, f)
155    }
156}
157
158// --- INTERNAL IMPLEMENTATIONS ---
159
160#[doc(hidden)]
161impl<const L: u32> IntoMck for Signed<L> {
162    type Type = mck::concr::Bitvector<L>;
163
164    fn into_mck(self) -> Self::Type {
165        self.0
166    }
167}