1use std::cmp::Ordering;
8use std::fmt::{self, Debug, Display, Formatter, Octal};
9use std::hash::{Hash, Hasher};
10
11use serde::Serialize;
12
13#[cfg(test)]
14use test_strategy::Arbitrary;
15
16use super::super::subword::{right_half, split_halfword, split_halves};
17use super::error::ConversionFailed;
18use super::signed::{Signed5Bit, Signed6Bit, Signed9Bit, Signed12Bit, Signed18Bit, Signed36Bit};
19use super::{Signum, WordCommon};
20
21#[cfg(test)]
22mod tests;
23
24macro_rules! from_native_type_to_self {
27 ($SelfT:ty, $($from:ty)*) => {
28 $(
29 impl From<$from> for $SelfT {
30 fn from(n: $from) -> Self {
31 Self {
32 bits: n.into(),
33 }
34 }
35 }
36 )*
37 }
38}
39
40macro_rules! from_self_to_native_type {
43 ($SelfT:ty, $($to:ty)*) => {
44 $(
45 impl From<$SelfT> for $to {
46 fn from(n: $SelfT) -> $to {
47 n.bits as $to
56 }
57 }
58 )*
59 }
60}
61
62macro_rules! try_from_self_to_native_type {
66 ($SelfT:ty, $($to:ty)*) => {
67 $(
68 impl TryFrom<$SelfT> for $to {
69 type Error = ConversionFailed;
70 fn try_from(n: $SelfT) -> Result<$to, ConversionFailed> {
71 <$to>::try_from(n.bits).map_err(|_| ConversionFailed::TooLarge)
72 }
73 }
74 )*
75 }
76}
77
78macro_rules! try_from_native_type_to_self {
82 ($SelfT:ty, $InnerT:ty, $($from:ty)*) => {
83 $(
84 impl TryFrom<$from> for $SelfT {
85 type Error = ConversionFailed;
86 fn try_from(n: $from) -> Result<Self, ConversionFailed> {
87 let bits: $InnerT = match n.try_into() {
88 Err(_) => {
89 #[allow(unused_comparisons)]
97 if n < 0 {
98 return Err(ConversionFailed::TooSmall);
99 } else {
100 return Err(ConversionFailed::TooLarge);
101 }
102 }
103 Ok(value) if value > Self::VALUE_BITS => {
104 return Err(ConversionFailed::TooLarge);
105 }
106 Ok(value) => value,
107 };
108 Ok(
109 Self {
110 bits,
111 }
112 )
113 }
114 }
115 )*
116 }
117}
118
119macro_rules! unsigned_ones_complement_impl {
127 ($SelfT:ty, $BITS:expr_2021, $InnerT:ty, $SignedPeerT:ty) => {
128 impl $SelfT {
129 const MODULUS: $InnerT = (1 << $BITS);
130 const VALUE_BITS: $InnerT = Self::MODULUS - 1;
131
132 pub const MAX: Self = Self {
133 bits: Self::MODULUS - 1,
134 };
135
136 pub const ZERO: Self = Self { bits: 0 };
137 pub const ONE: Self = Self { bits: 1 };
138 pub const MIN: Self = Self::ZERO;
139
140 pub const fn new<const N: $InnerT>() -> $SelfT {
144 type Word = $SelfT;
145 struct Helper<const M: $InnerT>;
146 impl<const M: $InnerT> Helper<M> {
147 const U: Word = {
148 if M > Word::MAX.bits {
149 panic!("input value is out of range")
150 } else {
151 Word {
152 bits: Word::MAX.bits & M,
153 }
154 }
155 };
156 }
157 Helper::<N>::U
158 }
159
160 pub const fn is_zero(&self) -> bool {
161 self.bits == 0
162 }
163
164 pub const fn is_negative(&self) -> bool {
165 false
166 }
167
168 pub const fn is_positive(&self) -> bool {
169 true
170 }
171
172 pub const fn reinterpret_as_signed(&self) -> $SignedPeerT {
173 type T = $SignedPeerT;
174 T { bits: self.bits }
175 }
176
177 #[must_use]
178 pub fn wrapping_add(self, rhs: $SelfT) -> $SelfT {
179 let left = <$InnerT>::from(self);
180 let right = <$InnerT>::from(rhs);
181 let in_range_value: $InnerT = left.wrapping_add(right) & Self::VALUE_BITS;
182 Self::try_from(in_range_value).unwrap()
183 }
184
185 #[must_use]
186 pub fn wrapping_sub(self, rhs: $SelfT) -> $SelfT {
187 let left = <$InnerT>::from(self);
188 let right = <$InnerT>::from(rhs);
189 let in_range_value = (left + Self::MODULUS).wrapping_sub(right) & Self::VALUE_BITS;
190 Self::try_from(in_range_value).unwrap()
191 }
192
193 pub fn checked_add(self, rhs: $SelfT) -> Option<$SelfT> {
194 let left = <$InnerT>::from(self);
195 let right = <$InnerT>::from(rhs);
196 match left.checked_add(right) {
197 Some(result) => Self::try_from(result).ok(),
198 None => None,
199 }
200 }
201
202 pub fn checked_sub(self, rhs: $SelfT) -> Option<$SelfT> {
203 let left = <$InnerT>::from(self);
204 let right = <$InnerT>::from(rhs);
205 match left.checked_sub(right) {
206 Some(result) => Self::try_from(result).ok(),
207 None => None,
208 }
209 }
210
211 #[must_use]
212 pub fn wrapping_mul(self, rhs: $SelfT) -> $SelfT {
213 let left = <$InnerT>::from(self);
214 let right = <$InnerT>::from(rhs);
215 let in_range_value = left.wrapping_mul(right) & Self::VALUE_BITS;
216 Self::try_from(in_range_value).unwrap()
217 }
218
219 pub fn checked_mul(self, rhs: $SelfT) -> Option<$SelfT> {
220 let left = <$InnerT>::from(self);
221 let right = <$InnerT>::from(rhs);
222 match left.checked_mul(right) {
223 Some(result) => Self::try_from(result).ok(),
224 None => None,
225 }
226 }
227
228 pub fn checked_div(self, rhs: $SelfT) -> Option<$SelfT> {
229 let left = <$InnerT>::from(self);
230 let right = <$InnerT>::from(rhs);
231 match left.checked_div(right) {
232 Some(result) => Self::try_from(result).ok(),
233 None => None,
234 }
235 }
236
237 #[must_use]
238 pub const fn abs(self) -> Self {
239 self
240 }
241
242 pub const fn overflowing_abs(self) -> (Self, bool) {
243 (self, false)
244 }
245
246 #[must_use]
250 pub const fn and(self, mask: $InnerT) -> Self {
251 Self {
252 bits: self.bits & mask,
253 }
254 }
255
256 #[must_use]
260 pub const fn bitor(self, mask: $InnerT) -> Self {
261 Self {
262 bits: self.bits | mask,
263 }
264 }
265 }
266
267 impl WordCommon for $SelfT {
268 fn signum(&self) -> Signum {
269 if self.is_zero() {
270 Signum::Zero
271 } else if self.is_negative() {
272 Signum::Negative
273 } else {
274 Signum::Positive
275 }
276 }
277 }
278
279 impl Default for $SelfT {
280 fn default() -> Self {
281 Self { bits: 0 }
282 }
283 }
284
285 impl Display for $SelfT {
286 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
287 Octal::fmt(&self.bits, f)
288 }
289 }
290
291 impl Octal for $SelfT {
292 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
293 Octal::fmt(&self.bits, f)
294 }
295 }
296
297 impl Debug for $SelfT {
298 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
299 write!(f, concat!(stringify!($SelfT), "{{bits: {:#o}}}"), self.bits)
300 }
301 }
302
303 impl Hash for $SelfT {
304 fn hash<H>(&self, state: &mut H)
305 where
306 H: Hasher,
307 {
308 self.bits.hash(state)
309 }
310 }
311
312 impl<T> PartialEq<T> for $SelfT
313 where
314 T: TryInto<$SelfT> + Copy,
315 {
316 fn eq(&self, other: &T) -> bool {
317 let converted: Result<$SelfT, _> = (*other).try_into();
318 if let Ok(rhs) = converted {
319 match self.cmp(&rhs) {
320 Ordering::Equal => true,
321 _ => false,
322 }
323 } else {
324 false
325 }
326 }
327 }
328
329 impl Eq for $SelfT {}
330
331 impl PartialOrd<$SelfT> for $SelfT {
332 fn partial_cmp(&self, other: &$SelfT) -> Option<Ordering> {
333 Some(self.cmp(other))
334 }
335 }
336
337 impl PartialOrd<u32> for $SelfT {
338 fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
339 match <$SelfT>::try_from(*other) {
340 Ok(value) => Some(self.cmp(&value)),
341 Err(_) => Some(Ordering::Less),
344 }
345 }
346 }
347
348 impl PartialOrd<u64> for $SelfT {
349 fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
350 match <$SelfT>::try_from(*other) {
351 Ok(value) => Some(self.cmp(&value)),
352 Err(_) => Some(Ordering::Less),
355 }
356 }
357 }
358
359 impl Ord for $SelfT {
360 fn cmp(&self, other: &$SelfT) -> Ordering {
361 let lhs = <$InnerT>::from(*self);
363 let rhs = <$InnerT>::from(*other);
364 lhs.cmp(&rhs)
365 }
366 }
367
368 impl std::ops::Not for $SelfT {
369 type Output = Self;
370 fn not(self) -> Self {
371 Self {
372 bits: (!self.bits) & Self::VALUE_BITS,
373 }
374 }
375 }
376
377 impl std::ops::BitAnd<$InnerT> for $SelfT {
378 type Output = Self;
379 fn bitand(self, mask: $InnerT) -> Self {
380 Self {
381 bits: self.bits & mask,
382 }
383 }
384 }
385
386 impl std::ops::BitAnd<$SelfT> for $SelfT {
387 type Output = Self;
388 fn bitand(self, rhs: Self) -> Self {
389 self.bitand(rhs.bits)
390 }
391 }
392
393 impl std::ops::BitOr<$InnerT> for $SelfT {
394 type Output = Self;
395 fn bitor(self, mask: $InnerT) -> Self {
396 Self {
397 bits: self.bits | mask,
398 }
399 }
400 }
401
402 impl std::ops::BitOr for $SelfT {
403 type Output = Self;
404 fn bitor(self, rhs: Self) -> Self {
405 self.bitor(rhs.bits)
406 }
407 }
408
409 impl std::ops::BitXor<$InnerT> for $SelfT {
410 type Output = Self;
411 fn bitxor(self, mask: $InnerT) -> Self {
412 Self {
413 bits: self.bits ^ mask,
414 }
415 }
416 }
417
418 impl std::ops::BitXor for $SelfT {
419 type Output = Self;
420 fn bitxor(self, rhs: Self) -> Self {
421 self.bitxor(rhs.bits)
422 }
423 }
424
425 impl std::ops::Shr<$SelfT> for $SelfT {
426 type Output = $SelfT;
427 fn shr(self, rhs: Self) -> Self {
428 let shift_by = rhs.bits % $BITS;
429 let goners_mask: $InnerT = (1 << shift_by) - 1;
432
433 let saved = (self.bits & goners_mask) << ($BITS - shift_by);
440
441 let bits = (self.bits.shr(shift_by) | saved) & Self::VALUE_BITS;
442 Self { bits }
443 }
444 }
445
446 impl std::ops::Shr<u32> for $SelfT {
447 type Output = $SelfT;
448 fn shr(self, shift_by: u32) -> Self {
449 let goners_mask: $InnerT = (1 << shift_by) - 1;
452
453 let saved = (self.bits & goners_mask) << ($BITS - shift_by);
460
461 let bits = (self.bits.shr(shift_by) | saved) & Self::VALUE_BITS;
462 Self { bits }
463 }
464 }
465
466 impl std::iter::Sum for $SelfT {
467 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
468 iter.fold(Self::ZERO, |acc, n| {
469 acc.checked_add(n).expect("sum should not overflow")
470 })
471 }
472 }
473
474 impl std::ops::Shl<$SelfT> for $SelfT {
475 type Output = $SelfT;
476 fn shl(self, shift_by: $SelfT) -> Self {
477 #[allow(clippy::suspicious_arithmetic_impl)]
482 let shift: u32 = (shift_by.bits % $BITS) as u32;
483 self.shl(shift)
484 }
485 }
486
487 impl std::ops::Shl<u32> for $SelfT {
488 type Output = $SelfT;
489 fn shl(self, rhs: u32) -> Self {
490 let shift_by = rhs % $BITS;
491 let mask: $InnerT = (1 << shift_by) - 1; let goners_mask: $InnerT = mask << ($BITS - shift_by); let saved = (self.bits & goners_mask) >> ($BITS - shift_by);
504 let bits = ((self.bits << shift_by) | saved) & Self::VALUE_BITS;
505 Self { bits }
506 }
507 }
508 };
509}
510
511#[cfg_attr(test, derive(Arbitrary))]
514#[derive(Clone, Copy, Serialize)]
515pub struct Unsigned5Bit {
516 #[cfg_attr(test, strategy(0..32u8))]
517 pub(crate) bits: u8,
518}
519
520#[cfg_attr(test, derive(Arbitrary))]
523#[derive(Clone, Copy, Serialize)]
524pub struct Unsigned6Bit {
525 #[cfg_attr(test, strategy(0..64u8))]
526 pub(crate) bits: u8,
527}
528
529#[cfg_attr(test, derive(Arbitrary))]
533#[derive(Clone, Copy, Serialize)]
534pub struct Unsigned9Bit {
535 #[cfg_attr(test, strategy(0..512u16))]
536 pub(crate) bits: u16,
537}
538
539#[cfg_attr(test, derive(Arbitrary))]
541#[derive(Clone, Copy, Serialize)]
542pub struct Unsigned12Bit {
543 #[cfg_attr(test, strategy(0..4095u16))]
544 pub(crate) bits: u16,
545}
546
547#[cfg_attr(test, derive(Arbitrary))]
554#[derive(Clone, Copy, Serialize)]
555pub struct Unsigned18Bit {
556 #[cfg_attr(test, strategy(0..262_143u32))]
557 pub(crate) bits: u32,
558}
559
560#[cfg_attr(test, derive(Arbitrary))]
565#[derive(Clone, Copy, Serialize)]
566pub struct Unsigned36Bit {
567 #[cfg_attr(test, strategy(0..68_719_476_735u64))]
568 pub(crate) bits: u64,
569}
570
571unsigned_ones_complement_impl!(Unsigned5Bit, 5, u8, Signed5Bit);
572unsigned_ones_complement_impl!(Unsigned6Bit, 6, u8, Signed6Bit);
573unsigned_ones_complement_impl!(Unsigned9Bit, 9, u16, Signed9Bit);
574unsigned_ones_complement_impl!(Unsigned12Bit, 12, u16, Signed12Bit);
575unsigned_ones_complement_impl!(Unsigned18Bit, 18, u32, Signed18Bit);
576unsigned_ones_complement_impl!(Unsigned36Bit, 36, u64, Signed36Bit);
577
578from_self_to_native_type!(Unsigned5Bit, u8 i8 u16 i16 u32 i32 u64 i64 usize isize);
586try_from_native_type_to_self!(Unsigned5Bit, u8, i8 u8 u16 i16 u32 i32 u64 i64 usize isize);
590
591from_self_to_native_type!(Unsigned6Bit, u8 i8 u16 i16 u32 i32 u64 i64 usize isize);
599try_from_native_type_to_self!(Unsigned6Bit, u8, i8 u8 u16 i16 u32 i32 u64 i64 usize isize);
603
604impl From<Unsigned5Bit> for Unsigned6Bit {
605 fn from(n: Unsigned5Bit) -> Self {
606 Self { bits: n.bits }
607 }
608}
609
610impl TryFrom<Unsigned18Bit> for Unsigned6Bit {
611 type Error = ConversionFailed;
612 fn try_from(n: Unsigned18Bit) -> Result<Self, ConversionFailed> {
613 match u8::try_from(n.bits) {
614 Ok(n) => {
615 if n > Self::VALUE_BITS {
616 Err(ConversionFailed::TooLarge)
617 } else {
618 Ok(Self { bits: n })
619 }
620 }
621 Err(_) => Err(ConversionFailed::TooLarge),
622 }
623 }
624}
625
626from_native_type_to_self!(Unsigned9Bit, u8);
632from_self_to_native_type!(Unsigned9Bit, u16 i16 u32 i32 u64 i64 usize isize);
634try_from_self_to_native_type!(Unsigned9Bit, u8 i8);
636try_from_native_type_to_self!(Unsigned9Bit, u16, i8 u16 i16 u32 i32 u64 i64 usize isize);
638
639impl From<Unsigned5Bit> for Unsigned9Bit {
640 fn from(n: Unsigned5Bit) -> Self {
641 Self {
642 bits: n.bits.into(),
643 }
644 }
645}
646
647impl From<Unsigned6Bit> for Unsigned9Bit {
648 fn from(n: Unsigned6Bit) -> Self {
649 Self {
650 bits: n.bits.into(),
651 }
652 }
653}
654
655from_native_type_to_self!(Unsigned12Bit, u8);
661from_self_to_native_type!(Unsigned12Bit, u16 i16 u32 i32 u64 i64 usize isize);
663try_from_self_to_native_type!(Unsigned12Bit, u8 i8);
665try_from_native_type_to_self!(Unsigned12Bit, u16, i8 u16 i16 u32 i32 u64 i64);
667
668impl From<Unsigned5Bit> for Unsigned12Bit {
669 fn from(n: Unsigned5Bit) -> Self {
670 Self {
671 bits: n.bits.into(),
672 }
673 }
674}
675
676impl From<Unsigned6Bit> for Unsigned12Bit {
677 fn from(n: Unsigned6Bit) -> Self {
678 Self {
679 bits: n.bits.into(),
680 }
681 }
682}
683
684impl From<Unsigned9Bit> for Unsigned12Bit {
685 fn from(n: Unsigned9Bit) -> Self {
686 Self { bits: n.bits }
687 }
688}
689
690impl TryFrom<Unsigned18Bit> for Unsigned12Bit {
691 type Error = ConversionFailed;
692 fn try_from(n: Unsigned18Bit) -> Result<Self, ConversionFailed> {
693 match u16::try_from(n.bits) {
694 Ok(n) => {
695 if n > Self::VALUE_BITS {
696 Err(ConversionFailed::TooLarge)
697 } else {
698 Ok(Self { bits: n })
699 }
700 }
701 Err(_) => Err(ConversionFailed::TooLarge),
702 }
703 }
704}
705
706from_native_type_to_self!(Unsigned18Bit, u8 u16);
712from_self_to_native_type!(Unsigned18Bit, u32 i32 u64 i64 usize isize);
714try_from_self_to_native_type!(Unsigned18Bit, u8 i8 u16 i16);
716try_from_native_type_to_self!(Unsigned18Bit, u32, i8 i16 u32 i32 u64 i64);
718
719impl From<Unsigned5Bit> for Unsigned18Bit {
720 fn from(n: Unsigned5Bit) -> Self {
721 Self {
722 bits: n.bits.into(),
723 }
724 }
725}
726
727impl From<Unsigned9Bit> for Unsigned18Bit {
728 fn from(n: Unsigned9Bit) -> Self {
729 Self {
730 bits: n.bits.into(),
731 }
732 }
733}
734
735impl TryFrom<Unsigned36Bit> for Unsigned18Bit {
736 type Error = ConversionFailed;
737 fn try_from(n: Unsigned36Bit) -> Result<Self, ConversionFailed> {
738 let (high, low) = split_halves(n);
739 if high == Unsigned18Bit::ZERO {
740 Ok(low)
741 } else {
742 Err(ConversionFailed::TooLarge)
743 }
744 }
745}
746
747impl TryFrom<usize> for Unsigned18Bit {
748 type Error = ConversionFailed;
749 fn try_from(n: usize) -> Result<Self, ConversionFailed> {
750 match n.try_into() {
751 Ok(bits) => {
752 if bits > Unsigned18Bit::MAX.bits {
753 Err(ConversionFailed::TooLarge)
754 } else {
755 Ok(Unsigned18Bit { bits })
756 }
757 }
758 Err(_) => Err(ConversionFailed::TooLarge),
759 }
760 }
761}
762
763from_native_type_to_self!(Unsigned36Bit, u8 u16 u32);
769from_self_to_native_type!(Unsigned36Bit, u64 i64);
771try_from_self_to_native_type!(Unsigned36Bit, u8 i8 u16 i16 u32 i32);
773try_from_native_type_to_self!(Unsigned36Bit, u64, i8 i16 i32 u64 i64);
775
776impl TryFrom<Unsigned36Bit> for Unsigned6Bit {
777 type Error = ConversionFailed;
778 fn try_from(n: Unsigned36Bit) -> Result<Self, ConversionFailed> {
779 match u8::try_from(n.bits) {
780 Ok(n) => {
781 if n > Self::VALUE_BITS {
782 Err(ConversionFailed::TooLarge)
783 } else {
784 Ok(Self { bits: n })
785 }
786 }
787 Err(_) => Err(ConversionFailed::TooLarge),
788 }
789 }
790}
791
792impl From<Unsigned5Bit> for Unsigned36Bit {
793 fn from(n: Unsigned5Bit) -> Self {
794 Self {
795 bits: n.bits.into(),
796 }
797 }
798}
799
800impl From<Unsigned6Bit> for Unsigned36Bit {
801 fn from(n: Unsigned6Bit) -> Self {
802 Self {
803 bits: n.bits.into(),
804 }
805 }
806}
807
808impl From<Unsigned9Bit> for Unsigned36Bit {
809 fn from(n: Unsigned9Bit) -> Self {
810 Self {
811 bits: n.bits.into(),
812 }
813 }
814}
815
816impl From<Unsigned12Bit> for Unsigned36Bit {
817 fn from(n: Unsigned12Bit) -> Self {
818 Self {
819 bits: n.bits.into(),
820 }
821 }
822}
823
824impl From<Unsigned18Bit> for Unsigned36Bit {
825 fn from(n: Unsigned18Bit) -> Self {
826 Self {
827 bits: n.bits.into(),
828 }
829 }
830}
831
832impl std::ops::BitAnd<Unsigned18Bit> for Unsigned36Bit {
833 type Output = Unsigned18Bit;
834 fn bitand(self, rhs: Unsigned18Bit) -> Unsigned18Bit {
835 right_half(self).bitand(rhs)
836 }
837}
838
839impl std::ops::BitAnd<Unsigned9Bit> for Unsigned36Bit {
840 type Output = Unsigned9Bit;
841 fn bitand(self, rhs: Unsigned9Bit) -> Unsigned9Bit {
842 let (_q2, q1) = split_halfword(right_half(self));
843 q1.bitand(rhs)
844 }
845}
846
847impl std::ops::BitAnd<Unsigned6Bit> for Unsigned36Bit {
848 type Output = Unsigned6Bit;
849 fn bitand(self, rhs: Unsigned6Bit) -> Unsigned6Bit {
850 Unsigned6Bit {
851 bits: u8::try_from(self.bits & 0o77).expect("a six-bit quantity should be in-range")
852 & rhs.bits,
853 }
854 }
855}