cqlib_core/circuit/
bit.rs1use std::{fmt, hash::Hash};
29use thiserror::Error;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
33pub enum QubitError {
34 #[error("qubit index must be non-negative, got {0}")]
36 NegativeIndex(i128),
37 #[error("qubit index {0} exceeds u32::MAX")]
39 IndexTooLarge(u128),
40}
41
42#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
66#[repr(transparent)]
67pub struct Qubit(u32);
68
69impl fmt::Display for Qubit {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "Q{}", self.0)
75 }
76}
77
78impl Qubit {
79 #[inline]
84 pub const fn new(id: u32) -> Self {
85 Self(id)
86 }
87
88 #[inline]
92 pub const fn id(&self) -> u32 {
93 self.0
94 }
95
96 #[inline]
102 pub const fn index(&self) -> usize {
103 self.0 as usize
104 }
105}
106
107macro_rules! impl_qubit_from_unsigned {
108 ($($t:ty),*) => {
109 $(
110 impl From<$t> for Qubit {
111 fn from(idx: $t) -> Self {
112 Self(idx as u32)
113 }
114 }
115 )*
116 };
117}
118macro_rules! impl_qubit_try_from_signed {
119 ($($t:ty),*) => {
120 $(
121 impl TryFrom<$t> for Qubit {
122 type Error = QubitError;
123
124 fn try_from(idx: $t) -> Result<Self, Self::Error> {
125 if idx < 0 {
126 Err(QubitError::NegativeIndex(idx as i128))
127 } else if idx as u128 > u32::MAX as u128 {
128 Err(QubitError::IndexTooLarge(idx as u128))
129 } else {
130 Ok(Self(idx as u32))
131 }
132 }
133 }
134 )*
135 };
136}
137
138impl_qubit_from_unsigned!(u32, u16, u8);
140impl_qubit_try_from_signed!(i8, i16, i32, isize);
141
142macro_rules! impl_qubit_try_from_unsigned {
143 ($($t:ty),*) => {
144 $(
145 impl TryFrom<$t> for Qubit {
146 type Error = QubitError;
147
148 fn try_from(idx: $t) -> Result<Self, Self::Error> {
149 if idx as u128 > u32::MAX as u128 {
150 Err(QubitError::IndexTooLarge(idx as u128))
151 } else {
152 Ok(Self(idx as u32))
153 }
154 }
155 }
156 )*
157 };
158}
159
160impl_qubit_try_from_unsigned!(usize);
161
162#[test]
163fn test_qubit_creation_and_display() {
164 let q0 = Qubit(0);
165 let q1 = Qubit(1);
166
167 assert_eq!(q0.id(), 0);
168 assert_eq!(q1.id(), 1);
169 assert_ne!(q0, q1);
170
171 assert_eq!(format!("{}", q0), "Q0");
172 assert_eq!(format!("{}", q1), "Q1");
173
174 let q0_1 = Qubit(0);
175 assert_eq!(q0, q0_1);
176}
177
178#[test]
179fn test_qubit_try_from_usize() {
180 assert!(Qubit::try_from(0usize).is_ok());
182 assert!(Qubit::try_from(100usize).is_ok());
183 if usize::BITS >= 32 {
184 assert!(Qubit::try_from(u32::MAX as usize).is_ok());
185 }
186
187 if usize::BITS > 32 {
189 let overflow_idx = (u32::MAX as usize) + 1;
190 let result = Qubit::try_from(overflow_idx);
191 assert!(result.is_err());
192 assert_eq!(
193 result.unwrap_err(),
194 QubitError::IndexTooLarge(overflow_idx as u128)
195 );
196 }
197}
198
199#[test]
200fn test_qubit_try_from_isize() {
201 assert!(Qubit::try_from(0isize).is_ok());
203 assert!(Qubit::try_from(100isize).is_ok());
204 if isize::BITS > 32 {
205 assert!(Qubit::try_from(u32::MAX as isize).is_ok());
206 } else {
207 assert!(Qubit::try_from(isize::MAX).is_ok());
208 }
209
210 let result = Qubit::try_from(-1isize);
212 assert!(result.is_err());
213 assert_eq!(result.unwrap_err(), QubitError::NegativeIndex(-1));
214
215 if isize::BITS > 32 {
217 let overflow_idx = (u32::MAX as isize) + 1;
218 let result = Qubit::try_from(overflow_idx);
219 assert!(result.is_err());
220 assert_eq!(
221 result.unwrap_err(),
222 QubitError::IndexTooLarge(overflow_idx as u128)
223 );
224 }
225}
226
227#[test]
228fn test_qubit_from_small_types() {
229 let _: Qubit = 0u8.into();
231 let _: Qubit = 100u8.into();
232 let _: Qubit = 0u16.into();
233 let _: Qubit = 1000u16.into();
234 let _: Qubit = 0u32.into();
235 let _: Qubit = 100000u32.into();
236
237 assert_eq!(Qubit::try_from(0i8), Ok(Qubit::new(0)));
238 assert_eq!(Qubit::try_from(100i8), Ok(Qubit::new(100)));
239 assert_eq!(Qubit::try_from(1000i16), Ok(Qubit::new(1000)));
240 assert_eq!(Qubit::try_from(100000i32), Ok(Qubit::new(100000)));
241 assert_eq!(Qubit::try_from(-1i8), Err(QubitError::NegativeIndex(-1)));
242 assert_eq!(Qubit::try_from(-1i16), Err(QubitError::NegativeIndex(-1)));
243 assert_eq!(Qubit::try_from(-1i32), Err(QubitError::NegativeIndex(-1)));
244}