apint/uint.rs
1use apint::ApInt;
2use traits::Width;
3use digit::Bit;
4use bitwidth::BitWidth;
5use errors::Result;
6use apint::{ShiftAmount};
7use bitpos::{BitPos};
8use int::Int;
9use utils::{try_forward_bin_mut_impl, forward_mut_impl, forward_bin_mut_impl};
10
11#[cfg(feature = "rand_support")]
12use rand;
13
14use std::cmp::Ordering;
15use std::ops::{
16 Not,
17 BitAnd,
18 BitOr,
19 BitXor,
20 BitAndAssign,
21 BitOrAssign,
22 BitXorAssign,
23 Add,
24 Sub,
25 Mul,
26 Div,
27 Rem,
28 AddAssign,
29 SubAssign,
30 MulAssign,
31 DivAssign,
32 RemAssign
33};
34
35/// Unsigned machine integer with arbitrary bitwidths and modulo arithmetics.
36///
37/// Thin convenience wrapper around `ApInt` for static unsigned interpretation of the value.
38///
39/// This very cheaply transformes to and from `ApInt` and `Int` instances and together with
40/// `Int` offers a more elegant and higher-level abstraction interface to the lower-level `ApInt`.
41#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
42pub struct UInt {
43 value: ApInt,
44}
45
46impl From<ApInt> for UInt {
47 fn from(value: ApInt) -> UInt {
48 UInt { value }
49 }
50}
51
52impl UInt {
53 /// Transforms this `UInt` into an equivalent `ApInt` instance.
54 pub fn into_apint(self) -> ApInt {
55 self.value
56 }
57
58 /// Transforms this `UInt` into an equivalent `Int` instance.
59 pub fn into_signed(self) -> Int {
60 Int::from(self.value)
61 }
62}
63
64/// # Constructors
65impl UInt {
66 /// Creates a new `UInt` from the given `Bit` value with a bit width of `1`.
67 ///
68 /// This function is generic over types that are convertible to `Bit` such as `bool`.
69 pub fn from_bit<B>(bit: B) -> UInt
70 where
71 B: Into<Bit>,
72 {
73 UInt::from(ApInt::from_bit(bit))
74 }
75
76 /// Creates a new `UInt` from a given `u8` value with a bit-width of 8.
77 #[inline]
78 pub fn from_u8(val: u8) -> UInt {
79 UInt::from(ApInt::from_u8(val))
80 }
81
82 /// Creates a new `UInt` from a given `u16` value with a bit-width of 16.
83 #[inline]
84 pub fn from_u16(val: u16) -> UInt {
85 UInt::from(ApInt::from_u16(val))
86 }
87
88 /// Creates a new `UInt` from a given `u32` value with a bit-width of 32.
89 #[inline]
90 pub fn from_u32(val: u32) -> UInt {
91 UInt::from(ApInt::from_u32(val))
92 }
93
94 /// Creates a new `UInt` from a given `u64` value with a bit-width of 64.
95 #[inline]
96 pub fn from_u64(val: u64) -> UInt {
97 UInt::from(ApInt::from_u64(val))
98 }
99
100 /// Creates a new `UInt` from a given `u64` value with a bit-width of 64.
101 pub fn from_u128(val: u128) -> UInt {
102 UInt::from(ApInt::from_u128(val))
103 }
104
105 /// Creates a new `UInt` with the given bit width that represents zero.
106 pub fn zero(width: BitWidth) -> UInt {
107 UInt::from(ApInt::zero(width))
108 }
109
110 /// Creates a new `UInt` with the given bit width that represents one.
111 pub fn one(width: BitWidth) -> UInt {
112 UInt::from(ApInt::one(width))
113 }
114
115 /// Creates a new `UInt` with the given bit width that has all bits unset.
116 ///
117 /// **Note:** This is equal to calling `UInt::zero` with the given `width`.
118 pub fn all_unset(width: BitWidth) -> UInt {
119 UInt::zero(width)
120 }
121
122 /// Creates a new `UInt` with the given bit width that has all bits set.
123 ///
124 /// # Note
125 ///
126 /// - This is equal to minus one on any twos-complement machine.
127 pub fn all_set(width: BitWidth) -> UInt {
128 UInt::from(ApInt::all_set(width))
129 }
130
131 /// Returns the smallest `UInt` that can be represented by the given `BitWidth`.
132 pub fn min_value(width: BitWidth) -> UInt {
133 UInt::from(ApInt::unsigned_min_value(width))
134 }
135
136 /// Returns the largest `UInt` that can be represented by the given `BitWidth`.
137 pub fn max_value(width: BitWidth) -> UInt {
138 UInt::from(ApInt::unsigned_max_value(width))
139 }
140}
141
142impl<B> From<B> for UInt
143 where B: Into<Bit>
144{
145 #[inline]
146 fn from(bit: B) -> UInt {
147 UInt::from_bit(bit)
148 }
149}
150
151impl From<u8> for UInt {
152 fn from(val: u8) -> UInt {
153 UInt::from_u8(val)
154 }
155}
156
157impl From<u16> for UInt {
158 fn from(val: u16) -> UInt {
159 UInt::from_u16(val)
160 }
161}
162
163impl From<u32> for UInt {
164 fn from(val: u32) -> UInt {
165 UInt::from_u32(val)
166 }
167}
168
169impl From<u64> for UInt {
170 fn from(val: u64) -> UInt {
171 UInt::from_u64(val)
172 }
173}
174
175impl From<u128> for UInt {
176 fn from(val: u128) -> UInt {
177 UInt::from_u128(val)
178 }
179}
180
181macro_rules! impl_from_array_for_uint {
182 ($n:expr) => {
183 impl From<[u64; $n]> for UInt {
184 fn from(val: [u64; $n]) -> UInt {
185 UInt::from(ApInt::from(val))
186 }
187 }
188 }
189}
190
191impl_from_array_for_uint!(2); // 128 bits
192impl_from_array_for_uint!(3); // 192 bits
193impl_from_array_for_uint!(4); // 256 bits
194impl_from_array_for_uint!(5); // 320 bits
195impl_from_array_for_uint!(6); // 384 bits
196impl_from_array_for_uint!(7); // 448 bits
197impl_from_array_for_uint!(8); // 512 bits
198impl_from_array_for_uint!(16); // 1024 bits
199impl_from_array_for_uint!(32); // 2048 bits
200
201/// # Utilities
202impl UInt {
203 /// Returns `true` if this `UInt` represents the value zero (`0`).
204 ///
205 /// # Note
206 ///
207 /// - Zero (`0`) is also called the additive neutral element.
208 /// - This operation is more efficient than comparing two instances
209 /// of `UInt` for the same reason.
210 pub fn is_zero(&self) -> bool {
211 self.value.is_zero()
212 }
213
214 /// Returns `true` if this `UInt` represents the value one (`1`).
215 ///
216 /// # Note
217 ///
218 /// - One (`1`) is also called the multiplicative neutral element.
219 /// - This operation is more efficient than comparing two instances
220 /// of `UInt` for the same reason.
221 pub fn is_one(&self) -> bool {
222 self.value.is_one()
223 }
224
225 /// Returns `true` if this `UInt` represents an even number.
226 pub fn is_even(&self) -> bool {
227 self.value.is_even()
228 }
229
230 /// Returns `true` if this `UInt` represents an odd number.
231 pub fn is_odd(&self) -> bool {
232 self.value.is_odd()
233 }
234}
235
236impl UInt {
237
238 /// Less-than (`lt`) comparison between `self` and `rhs`.
239 ///
240 /// # Note
241 ///
242 /// - Returns `Ok(true)` if `self < rhs`.
243 /// - Interprets both `UInt` instances as **unsigned** values.
244 ///
245 /// # Errors
246 ///
247 /// - If `self` and `rhs` have unmatching bit widths.
248 pub fn checked_lt(&self, rhs: &UInt) -> Result<bool> {
249 self.value.checked_ult(&rhs.value)
250 }
251
252 /// Less-equals (`le`) comparison between `self` and `rhs`.
253 ///
254 /// # Note
255 ///
256 /// - Returns `Ok(true)` if `self <= rhs`.
257 /// - Interprets both `UInt` instances as **unsigned** values.
258 ///
259 /// # Errors
260 ///
261 /// - If `self` and `rhs` have unmatching bit widths.
262 #[inline]
263 pub fn checked_le(&self, rhs: &UInt) -> Result<bool> {
264 self.value.checked_ule(&rhs.value)
265 }
266
267 /// Greater-than (`gt`) comparison between `self` and `rhs`.
268 ///
269 /// # Note
270 ///
271 /// - Returns `Ok(true)` if `self > rhs`.
272 /// - Interprets both `UInt` instances as **unsigned** values.
273 ///
274 /// # Errors
275 ///
276 /// - If `self` and `rhs` have unmatching bit widths.
277 #[inline]
278 pub fn checked_gt(&self, rhs: &UInt) -> Result<bool> {
279 self.value.checked_ugt(&rhs.value)
280 }
281
282 /// Greater-equals (`ge`) comparison between `self` and `rhs`.
283 ///
284 /// # Note
285 ///
286 /// - Returns `Ok(true)` if `self >= rhs`.
287 /// - Interprets both `UInt` instances as **unsigned** values.
288 ///
289 /// # Errors
290 ///
291 /// - If `self` and `rhs` have unmatching bit widths.
292 #[inline]
293 pub fn checked_ge(&self, rhs: &UInt) -> Result<bool> {
294 self.value.checked_uge(&rhs.value)
295 }
296}
297
298impl PartialOrd for UInt {
299 fn partial_cmp(&self, rhs: &UInt) -> Option<Ordering> {
300 if self.value.width() != rhs.value.width() {
301 return None;
302 }
303 if self.checked_lt(rhs).unwrap() {
304 return Some(Ordering::Less);
305 }
306 if self.value == rhs.value {
307 return Some(Ordering::Equal);
308 }
309 Some(Ordering::Greater)
310 }
311
312 fn lt(&self, rhs: &UInt) -> bool {
313 self.checked_lt(rhs).unwrap_or(false)
314 }
315
316 fn le(&self, rhs: &UInt) -> bool {
317 self.checked_le(rhs).unwrap_or(false)
318 }
319
320 fn gt(&self, rhs: &UInt) -> bool {
321 self.checked_gt(rhs).unwrap_or(false)
322 }
323
324 fn ge(&self, rhs: &UInt) -> bool {
325 self.checked_ge(rhs).unwrap_or(false)
326 }
327}
328
329/// # To Primitive (Resize)
330impl UInt {
331 /// Resizes this `UInt` to a `bool` primitive type.
332 ///
333 /// Bits in this `UInt` that are not within the bounds
334 /// of the `bool` are being ignored.
335 ///
336 /// # Note
337 ///
338 /// - Basically this returns `true` if the least significant
339 /// bit of this `UInt` is `1` and `false` otherwise.
340 pub fn resize_to_bool(&self) -> bool {
341 self.value.resize_to_bool()
342 }
343
344 /// Resizes this `UInt` to a `u8` primitive type.
345 ///
346 /// # Note
347 ///
348 /// - All bits but the least significant `8` bits are
349 /// being ignored by this operation to construct the
350 /// result.
351 pub fn resize_to_u8(&self) -> u8 {
352 self.value.resize_to_u8()
353 }
354
355 /// Resizes this `UInt` to a `u16` primitive type.
356 ///
357 /// # Note
358 ///
359 /// - All bits but the least significant `16` bits are
360 /// being ignored by this operation to construct the
361 /// result.
362 pub fn resize_to_u16(&self) -> u16 {
363 self.value.resize_to_u16()
364 }
365
366 /// Resizes this `UInt` to a `u32` primitive type.
367 ///
368 /// # Note
369 ///
370 /// - All bits but the least significant `32` bits are
371 /// being ignored by this operation to construct the
372 /// result.
373 pub fn resize_to_u32(&self) -> u32 {
374 self.value.resize_to_u32()
375 }
376
377 /// Resizes this `UInt` to a `u64` primitive type.
378 ///
379 /// # Note
380 ///
381 /// - All bits but the least significant `64` bits are
382 /// being ignored by this operation to construct the
383 /// result.
384 pub fn resize_to_u64(&self) -> u64 {
385 self.value.resize_to_u64()
386 }
387
388 /// Resizes this `UInt` to a `u128` primitive type.
389 ///
390 /// # Note
391 ///
392 /// - All bits but the least significant `128` bits are
393 /// being ignored by this operation to construct the
394 /// result.
395 pub fn resize_to_u128(&self) -> u128 {
396 self.value.resize_to_u128()
397 }
398}
399
400/// # To Primitive (Try-Cast)
401impl UInt {
402 /// Tries to represent the value of this `UInt` as a `bool`.
403 ///
404 /// # Note
405 ///
406 /// This returns `true` if the value represented by this `UInt`
407 /// is `1`, returns `false` if the value represented by this
408 /// `UInt` is `0` and returns an error otherwise.
409 ///
410 /// # Errors
411 ///
412 /// - If the value represented by this `UInt` can not be
413 /// represented by a `bool`.
414 pub fn try_to_bool(&self) -> Result<bool> {
415 self.value.try_to_bool()
416 }
417
418 /// Tries to represent the value of this `UInt` as a `u8`.
419 ///
420 /// # Note
421 ///
422 /// - This conversion is possible as long as the value represented
423 /// by this `UInt` does not exceed the maximum value of `u8`.
424 ///
425 /// # Errors
426 ///
427 /// - If the value represented by this `UInt` can not be
428 /// represented by a `u8`.
429 pub fn try_to_u8(&self) -> Result<u8> {
430 self.value.try_to_u8()
431 }
432
433 /// Tries to represent the value of this `UInt` as a `u16`.
434 ///
435 /// # Note
436 ///
437 /// - This conversion is possible as long as the value represented
438 /// by this `UInt` does not exceed the maximum value of `u16`.
439 ///
440 /// # Errors
441 ///
442 /// - If the value represented by this `UInt` can not be
443 /// represented by a `u16`.
444 pub fn try_to_u16(&self) -> Result<u16> {
445 self.value.try_to_u16()
446 }
447
448 /// Tries to represent the value of this `UInt` as a `u32`.
449 ///
450 /// # Note
451 ///
452 /// - This conversion is possible as long as the value represented
453 /// by this `UInt` does not exceed the maximum value of `u32`.
454 ///
455 /// # Errors
456 ///
457 /// - If the value represented by this `UInt` can not be
458 /// represented by a `u32`.
459 pub fn try_to_u32(&self) -> Result<u32> {
460 self.value.try_to_u32()
461 }
462
463 /// Tries to represent the value of this `UInt` as a `u64`.
464 ///
465 /// # Note
466 ///
467 /// - This conversion is possible as long as the value represented
468 /// by this `UInt` does not exceed the maximum value of `u64`.
469 ///
470 /// # Errors
471 ///
472 /// - If the value represented by this `UInt` can not be
473 /// represented by a `u64`.
474 pub fn try_to_u64(&self) -> Result<u64> {
475 self.value.try_to_u64()
476 }
477
478 /// Tries to represent the value of this `UInt` as a `u128`.
479 ///
480 /// # Note
481 ///
482 /// - This conversion is possible as long as the value represented
483 /// by this `UInt` does not exceed the maximum value of `u128`.
484 ///
485 /// # Complexity
486 ///
487 /// - 𝒪(n) where n is the number of digits of this `UInt`.
488 ///
489 /// # Errors
490 ///
491 /// - If the value represented by this `UInt` can not be
492 /// represented by a `u128`.
493 pub fn try_to_u128(&self) -> Result<u128> {
494 self.value.try_to_u128()
495 }
496}
497
498/// # Shifts
499impl UInt {
500 /// Shift this `UInt` left by the given `shift_amount` bits.
501 ///
502 /// This operation is inplace and will **not** allocate memory.
503 ///
504 /// # Errors
505 ///
506 /// - If the given `shift_amount` is invalid for the bit width of this `UInt`.
507 pub fn checked_shl_assign<S>(&mut self, shift_amount: S) -> Result<()>
508 where S: Into<ShiftAmount>
509 {
510 self.value.checked_shl_assign(shift_amount)
511 }
512
513 /// Shift this `UInt` left by the given `shift_amount` bits and returns the result.
514 ///
515 /// This operation is inplace and will **not** allocate memory.
516 ///
517 /// # Errors
518 ///
519 /// - If the given `shift_amount` is invalid for the bit width of this `UInt`.
520 pub fn into_checked_shl<S>(self, shift_amount: S) -> Result<UInt>
521 where S: Into<ShiftAmount>
522 {
523 self.value.into_checked_shl(shift_amount).map(UInt::from)
524 }
525
526 /// Right-shifts this `UInt` by the given `shift_amount` bits.
527 ///
528 /// This operation is inplace and will **not** allocate memory.
529 ///
530 /// # Errors
531 ///
532 /// - If the given `shift_amount` is invalid for the bit width of this `UInt`.
533 pub fn checked_shr_assign<S>(&mut self, shift_amount: S) -> Result<()>
534 where S: Into<ShiftAmount>
535 {
536 self.value.checked_lshr_assign(shift_amount)
537 }
538
539 /// Right-shifts this `UInt` by the given `shift_amount` bits
540 /// and returns the result.
541 ///
542 /// This operation is inplace and will **not** allocate memory.
543 ///
544 /// # Errors
545 ///
546 /// - If the given `shift_amount` is invalid for the bit width of this `UInt`.
547 pub fn into_checked_shr<S>(self, shift_amount: S) -> Result<UInt>
548 where S: Into<ShiftAmount>
549 {
550 self.value.into_checked_lshr(shift_amount).map(UInt::from)
551 }
552}
553
554use std::ops::{Shl, ShlAssign, Shr, ShrAssign};
555
556impl<S> Shl<S> for UInt
557 where S: Into<ShiftAmount>
558{
559 type Output = UInt;
560
561 fn shl(self, shift_amount: S) -> Self::Output {
562 self.into_checked_shl(shift_amount).unwrap()
563 }
564}
565
566impl<S> Shr<S> for UInt
567 where S: Into<ShiftAmount>
568{
569 type Output = UInt;
570
571 fn shr(self, shift_amount: S) -> Self::Output {
572 self.into_checked_shr(shift_amount).unwrap()
573 }
574}
575
576impl<S> ShlAssign<S> for UInt
577 where S: Into<ShiftAmount>
578{
579 fn shl_assign(&mut self, shift_amount: S) {
580 self.checked_shl_assign(shift_amount).unwrap()
581 }
582}
583
584impl<S> ShrAssign<S> for UInt
585 where S: Into<ShiftAmount>
586{
587 fn shr_assign(&mut self, shift_amount: S) {
588 self.checked_shr_assign(shift_amount).unwrap()
589 }
590}
591
592/// # Random Utilities using `rand` crate.
593#[cfg(feature = "rand_support")]
594impl UInt {
595 /// Creates a new `UInt` with the given `BitWidth` and random `Digit`s.
596 pub fn random_with_width(width: BitWidth) -> UInt {
597 UInt::from(ApInt::random_with_width(width))
598 }
599
600 /// Creates a new `UInt` with the given `BitWidth` and random `Digit`s
601 /// using the given random number generator.
602 ///
603 /// **Note:** This is useful for cryptographic or testing purposes.
604 pub fn random_with_width_using<R>(width: BitWidth, rng: &mut R) -> UInt
605 where R: rand::Rng
606 {
607 UInt::from(ApInt::random_with_width_using(width, rng))
608 }
609
610 /// Randomizes the digits of this `UInt` inplace.
611 ///
612 /// This won't change its `BitWidth`.
613 pub fn randomize(&mut self) {
614 self.value.randomize()
615 }
616
617 /// Randomizes the digits of this `UInt` inplace using the given
618 /// random number generator.
619 ///
620 /// This won't change its `BitWidth`.
621 pub fn randomize_using<R>(&mut self, rng: &mut R)
622 where R: rand::Rng
623 {
624 self.value.randomize_using(rng)
625 }
626}
627
628impl UInt {
629 /// Assigns `rhs` to this `UInt`.
630 ///
631 /// This mutates digits and may affect the bitwidth of `self`
632 /// which **might result in an expensive operations**.
633 ///
634 /// After this operation `rhs` and `self` are equal to each other.
635 pub fn assign(&mut self, rhs: &UInt) {
636 self.value.assign(&rhs.value)
637 }
638
639 /// Strictly assigns `rhs` to this `UInt`.
640 ///
641 /// After this operation `rhs` and `self` are equal to each other.
642 ///
643 /// **Note:** Strict assigns protect against mutating the bit width
644 /// of `self` and thus return an error instead of executing a probably
645 /// expensive `assign` operation.
646 ///
647 /// # Errors
648 ///
649 /// - If `rhs` and `self` have unmatching bit widths.
650 pub fn strict_assign(&mut self, rhs: &UInt) -> Result<()> {
651 self.value.strict_assign(&rhs.value)
652 }
653}
654
655/// # Casting: Truncation & Extension
656impl UInt {
657 /// Tries to truncate this `UInt` inplace to the given `target_width`
658 /// and returns the result.
659 ///
660 /// # Note
661 ///
662 /// - This is useful for method chaining.
663 /// - For more details look into
664 /// [`truncate`](struct.UInt.html#method.truncate).
665 ///
666 /// # Errors
667 ///
668 /// - If the `target_width` is greater than the current width.
669 pub fn into_truncate<W>(self, target_width: W) -> Result<UInt>
670 where W: Into<BitWidth>
671 {
672 try_forward_bin_mut_impl(self, target_width, UInt::truncate)
673 }
674
675 /// Tries to truncate this `UInt` inplace to the given `target_width`.
676 ///
677 /// # Note
678 ///
679 /// - This is a no-op if `self.width()` and `target_width` are equal.
680 /// - This operation is inplace as long as `self.width()` and `target_width`
681 /// require the same amount of digits for their representation.
682 ///
683 /// # Errors
684 ///
685 /// - If the `target_width` is greater than the current width.
686 pub fn truncate<W>(&mut self, target_width: W) -> Result<()>
687 where W: Into<BitWidth>
688 {
689 self.value.truncate(target_width)
690 }
691
692 // ========================================================================
693
694 /// Tries to zero-extend this `UInt` inplace to the given `target_width`
695 /// and returns the result.
696 ///
697 /// # Note
698 ///
699 /// - This is useful for method chaining.
700 /// - For more details look into
701 /// [`extend`](struct.UInt.html#method.extend).
702 ///
703 /// # Errors
704 ///
705 /// - If the `target_width` is less than the current width.
706 pub fn into_extend<W>(self, target_width: W) -> Result<UInt>
707 where W: Into<BitWidth>
708 {
709 try_forward_bin_mut_impl(self, target_width, UInt::extend)
710 }
711
712 /// Tries to extend this `UInt` inplace to the given `target_width`.
713 ///
714 /// # Note
715 ///
716 /// - This is a no-op if `self.width()` and `target_width` are equal.
717 /// - This operation is inplace as long as `self.width()` and `target_width`
718 /// require the same amount of digits for their representation.
719 ///
720 /// # Errors
721 ///
722 /// - If the `target_width` is less than the current width.
723 pub fn extend<W>(&mut self, target_width: W) -> Result<()>
724 where W: Into<BitWidth>
725 {
726 self.value.zero_extend(target_width)
727 }
728
729 // ========================================================================
730
731 /// Resizes this `UInt` to the given `target_width`
732 /// and returns the result.
733 ///
734 /// # Note
735 ///
736 /// - This is useful for method chaining.
737 /// - For more details look into
738 /// [`resize`](struct.UInt.html#method.resize).
739 pub fn into_resize<W>(self, target_width: W) -> UInt
740 where W: Into<BitWidth>
741 {
742 forward_bin_mut_impl(self, target_width, UInt::resize)
743 }
744
745 /// Resizes the given `UInt` inplace.
746 ///
747 /// # Note
748 ///
749 /// This operation will forward to
750 ///
751 /// - [`truncate`](struct.UInt.html#method.truncate)
752 /// if `target_width` is less than or equal to the width of
753 /// the given `UInt`
754 /// - [`extend`](struct.UInt.html#method.extend)
755 /// otherwise
756 pub fn resize<W>(&mut self, target_width: W)
757 where W: Into<BitWidth>
758 {
759 self.value.zero_resize(target_width)
760 }
761}
762
763/// # Bitwise Operations
764impl UInt {
765 /// Flips all bits of `self` and returns the result.
766 pub fn into_bitnot(self) -> Self {
767 forward_mut_impl(self, UInt::bitnot)
768 }
769
770 /// Flip all bits of this `UInt` inplace.
771 pub fn bitnot(&mut self) {
772 self.value.bitnot()
773 }
774
775 /// Tries to bit-and assign this `UInt` inplace to `rhs`
776 /// and returns the result.
777 ///
778 /// **Note:** This forwards to
779 /// [`checked_bitand`](struct.UInt.html#method.checked_bitand).
780 ///
781 /// # Errors
782 ///
783 /// If `self` and `rhs` have unmatching bit widths.
784 pub fn into_checked_bitand(self, rhs: &UInt) -> Result<UInt> {
785 try_forward_bin_mut_impl(self, rhs, UInt::checked_bitand_assign)
786 }
787
788 /// Bit-and assigns all bits of this `UInt` with the bits of `rhs`.
789 ///
790 /// **Note:** This operation is inplace of `self` and won't allocate memory.
791 ///
792 /// # Errors
793 ///
794 /// If `self` and `rhs` have unmatching bit widths.
795 pub fn checked_bitand_assign(&mut self, rhs: &UInt) -> Result<()> {
796 self.value.checked_bitand_assign(&rhs.value)
797 }
798
799 /// Tries to bit-and assign this `UInt` inplace to `rhs`
800 /// and returns the result.
801 ///
802 /// **Note:** This forwards to
803 /// [`checked_bitor`](struct.UInt.html#method.checked_bitor).
804 ///
805 /// # Errors
806 ///
807 /// If `self` and `rhs` have unmatching bit widths.
808 pub fn into_checked_bitor(self, rhs: &UInt) -> Result<UInt> {
809 try_forward_bin_mut_impl(self, rhs, UInt::checked_bitor_assign)
810 }
811
812 /// Bit-or assigns all bits of this `UInt` with the bits of `rhs`.
813 ///
814 /// **Note:** This operation is inplace of `self` and won't allocate memory.
815 ///
816 /// # Errors
817 ///
818 /// If `self` and `rhs` have unmatching bit widths.
819 pub fn checked_bitor_assign(&mut self, rhs: &UInt) -> Result<()> {
820 self.value.checked_bitor_assign(&rhs.value)
821 }
822
823 /// Tries to bit-xor assign this `UInt` inplace to `rhs`
824 /// and returns the result.
825 ///
826 /// **Note:** This forwards to
827 /// [`checked_bitxor`](struct.UInt.html#method.checked_bitxor).
828 ///
829 /// # Errors
830 ///
831 /// If `self` and `rhs` have unmatching bit widths.
832 pub fn into_checked_bitxor(self, rhs: &UInt) -> Result<UInt> {
833 try_forward_bin_mut_impl(self, rhs, UInt::checked_bitxor_assign)
834 }
835
836 /// Bit-xor assigns all bits of this `UInt` with the bits of `rhs`.
837 ///
838 /// **Note:** This operation is inplace of `self` and won't allocate memory.
839 ///
840 /// # Errors
841 ///
842 /// If `self` and `rhs` have unmatching bit widths.
843 pub fn checked_bitxor_assign(&mut self, rhs: &UInt) -> Result<()> {
844 self.value.checked_bitxor_assign(&rhs.value)
845 }
846}
847
848/// # Bitwise Access
849impl UInt {
850 /// Returns the bit at the given bit position `pos`.
851 ///
852 /// This returns
853 ///
854 /// - `Bit::Set` if the bit at `pos` is `1`
855 /// - `Bit::Unset` otherwise
856 ///
857 /// # Errors
858 ///
859 /// - If `pos` is not a valid bit position for the width of this `UInt`.
860 pub fn get_bit_at<P>(&self, pos: P) -> Result<Bit>
861 where P: Into<BitPos>
862 {
863 self.value.get_bit_at(pos)
864 }
865
866 /// Sets the bit at the given bit position `pos` to one (`1`).
867 ///
868 /// # Errors
869 ///
870 /// - If `pos` is not a valid bit position for the width of this `UInt`.
871 pub fn set_bit_at<P>(&mut self, pos: P) -> Result<()>
872 where P: Into<BitPos>
873 {
874 self.value.set_bit_at(pos)
875 }
876
877 /// Sets the bit at the given bit position `pos` to zero (`0`).
878 ///
879 /// # Errors
880 ///
881 /// - If `pos` is not a valid bit position for the width of this `UInt`.
882 pub fn unset_bit_at<P>(&mut self, pos: P) -> Result<()>
883 where P: Into<BitPos>
884 {
885 self.value.unset_bit_at(pos)
886 }
887
888 /// Flips the bit at the given bit position `pos`.
889 ///
890 /// # Note
891 ///
892 /// - If the bit at the given position was `0` it will be `1`
893 /// after this operation and vice versa.
894 ///
895 /// # Errors
896 ///
897 /// - If `pos` is not a valid bit position for the width of this `UInt`.
898 pub fn flip_bit_at<P>(&mut self, pos: P) -> Result<()>
899 where P: Into<BitPos>
900 {
901 self.value.flip_bit_at(pos)
902 }
903
904 /// Sets all bits of this `UInt` to one (`1`).
905 pub fn set_all(&mut self) {
906 self.value.set_all()
907 }
908
909 /// Returns `true` if all bits in this `UInt` are set.
910 pub fn is_all_set(&self) -> bool {
911 self.value.is_all_set()
912 }
913
914 /// Sets all bits of this `UInt` to zero (`0`).
915 pub fn unset_all(&mut self) {
916 self.value.unset_all()
917 }
918
919 /// Returns `true` if all bits in this `UInt` are unset.
920 pub fn is_all_unset(&self) -> bool {
921 self.value.is_all_unset()
922 }
923
924 /// Flips all bits of this `UInt`.
925 pub fn flip_all(&mut self) {
926 self.value.flip_all()
927 }
928}
929
930/// # Bitwise utility methods.
931impl UInt {
932 /// Returns the number of ones in the binary representation of this `UInt`.
933 pub fn count_ones(&self) -> usize {
934 self.value.count_ones()
935 }
936
937 /// Returns the number of zeros in the binary representation of this `UInt`.
938 pub fn count_zeros(&self) -> usize {
939 self.value.count_zeros()
940 }
941
942 /// Returns the number of leading zeros in the binary representation of this `UInt`.
943 pub fn leading_zeros(&self) -> usize {
944 self.value.leading_zeros()
945 }
946
947 /// Returns the number of trailing zeros in the binary representation of this `UInt`.
948 pub fn trailing_zeros(&self) -> usize {
949 self.value.trailing_zeros()
950 }
951}
952
953// ===========================================================================
954// `Not` (bitwise) impls
955// ===========================================================================
956
957impl Not for UInt {
958 type Output = UInt;
959
960 fn not(self) -> Self::Output {
961 forward_mut_impl(self, UInt::bitnot)
962 }
963}
964
965// ===========================================================================
966// `BitAnd` impls
967// ===========================================================================
968
969impl<'a> BitAnd<&'a UInt> for UInt {
970 type Output = UInt;
971
972 fn bitand(self, rhs: &'a UInt) -> Self::Output {
973 self.into_checked_bitand(rhs).unwrap()
974 }
975}
976
977impl<'a, 'b> BitAnd<&'a UInt> for &'b UInt {
978 type Output = UInt;
979
980 fn bitand(self, rhs: &'a UInt) -> Self::Output {
981 self.clone().into_checked_bitand(rhs).unwrap()
982 }
983}
984
985impl<'a, 'b> BitAnd<&'a UInt> for &'b mut UInt {
986 type Output = UInt;
987
988 fn bitand(self, rhs: &'a UInt) -> Self::Output {
989 self.clone().into_checked_bitand(rhs).unwrap()
990 }
991}
992
993// ===========================================================================
994// `BitOr` impls
995// ===========================================================================
996
997impl<'a> BitOr<&'a UInt> for UInt {
998 type Output = UInt;
999
1000 fn bitor(self, rhs: &'a UInt) -> Self::Output {
1001 self.into_checked_bitor(rhs).unwrap()
1002 }
1003}
1004
1005impl<'a, 'b> BitOr<&'a UInt> for &'b UInt {
1006 type Output = UInt;
1007
1008 fn bitor(self, rhs: &'a UInt) -> Self::Output {
1009 self.clone().into_checked_bitor(rhs).unwrap()
1010 }
1011}
1012
1013impl<'a, 'b> BitOr<&'a UInt> for &'b mut UInt {
1014 type Output = UInt;
1015
1016 fn bitor(self, rhs: &'a UInt) -> Self::Output {
1017 self.clone().into_checked_bitor(rhs).unwrap()
1018 }
1019}
1020
1021// ===========================================================================
1022// `BitXor` impls
1023// ===========================================================================
1024
1025impl<'a> BitXor<&'a UInt> for UInt {
1026 type Output = UInt;
1027
1028 fn bitxor(self, rhs: &'a UInt) -> Self::Output {
1029 self.into_checked_bitxor(rhs).unwrap()
1030 }
1031}
1032
1033impl<'a, 'b> BitXor<&'a UInt> for &'b UInt {
1034 type Output = UInt;
1035
1036 fn bitxor(self, rhs: &'a UInt) -> Self::Output {
1037 self.clone().into_checked_bitxor(rhs).unwrap()
1038 }
1039}
1040
1041impl<'a, 'b> BitXor<&'a UInt> for &'b mut UInt {
1042 type Output = UInt;
1043
1044 fn bitxor(self, rhs: &'a UInt) -> Self::Output {
1045 self.clone().into_checked_bitxor(rhs).unwrap()
1046 }
1047}
1048
1049// ===========================================================================
1050// `BitAndAssign`, `BitOrAssign` and `BitXorAssign` impls
1051// ===========================================================================
1052
1053impl<'a> BitAndAssign<&'a UInt> for UInt {
1054 fn bitand_assign(&mut self, rhs: &'a UInt) {
1055 self.checked_bitand_assign(rhs).unwrap();
1056 }
1057}
1058
1059impl<'a> BitOrAssign<&'a UInt> for UInt {
1060 fn bitor_assign(&mut self, rhs: &'a UInt) {
1061 self.checked_bitor_assign(rhs).unwrap();
1062 }
1063}
1064
1065impl<'a> BitXorAssign<&'a UInt> for UInt {
1066 fn bitxor_assign(&mut self, rhs: &'a UInt) {
1067 self.checked_bitxor_assign(rhs).unwrap();
1068 }
1069}
1070
1071/// # Arithmetic Operations
1072impl UInt {
1073 /// Adds `rhs` to `self` and returns the result.
1074 ///
1075 /// **Note:** This will **not** allocate memory.
1076 ///
1077 /// # Errors
1078 ///
1079 /// - If `self` and `rhs` have unmatching bit widths.
1080 pub fn into_checked_add(self, rhs: &UInt) -> Result<UInt> {
1081 try_forward_bin_mut_impl(self, rhs, UInt::checked_add_assign)
1082 }
1083
1084 /// Add-assigns `rhs` to `self` inplace.
1085 ///
1086 /// **Note:** This will **not** allocate memory.
1087 ///
1088 /// # Errors
1089 ///
1090 /// - If `self` and `rhs` have unmatching bit widths.
1091 pub fn checked_add_assign(&mut self, rhs: &UInt) -> Result<()> {
1092 self.value.checked_add_assign(&rhs.value)
1093 }
1094
1095 /// Subtracts `rhs` from `self` and returns the result.
1096 ///
1097 /// # Note
1098 ///
1099 /// In the low-level bit-wise representation there is no difference between signed
1100 /// and unsigned subtraction of fixed bit-width integers. (Cite: LLVM)
1101 ///
1102 /// # Errors
1103 ///
1104 /// - If `self` and `rhs` have unmatching bit widths.
1105 pub fn into_checked_sub(self, rhs: &UInt) -> Result<UInt> {
1106 try_forward_bin_mut_impl(self, rhs, UInt::checked_sub_assign)
1107 }
1108
1109 /// Subtract-assigns `rhs` from `self` inplace.
1110 ///
1111 /// # Note
1112 ///
1113 /// In the low-level bit-wise representation there is no difference between signed
1114 /// and unsigned subtraction of fixed bit-width integers. (Cite: LLVM)
1115 ///
1116 /// # Errors
1117 ///
1118 /// - If `self` and `rhs` have unmatching bit widths.
1119 pub fn checked_sub_assign(&mut self, rhs: &UInt) -> Result<()> {
1120 self.value.checked_sub_assign(&rhs.value)
1121 }
1122
1123 /// Subtracts `rhs` from `self` and returns the result.
1124 ///
1125 /// # Note
1126 ///
1127 /// In the low-level bit-wise representation there is no difference between signed
1128 /// and unsigned multiplication of fixed bit-width integers. (Cite: LLVM)
1129 ///
1130 /// # Errors
1131 ///
1132 /// - If `self` and `rhs` have unmatching bit widths.
1133 pub fn into_checked_mul(self, rhs: &UInt) -> Result<UInt> {
1134 try_forward_bin_mut_impl(self, rhs, UInt::checked_mul_assign)
1135 }
1136
1137 /// Multiply-assigns `rhs` to `self` inplace.
1138 ///
1139 /// # Note
1140 ///
1141 /// In the low-level bit-wise representation there is no difference between signed
1142 /// and unsigned multiplication of fixed bit-width integers. (Cite: LLVM)
1143 ///
1144 /// # Errors
1145 ///
1146 /// - If `self` and `rhs` have unmatching bit widths.
1147 pub fn checked_mul_assign(&mut self, rhs: &UInt) -> Result<()> {
1148 self.value.checked_mul_assign(&rhs.value)
1149 }
1150
1151 /// Divides `self` by `rhs` and returns the result.
1152 ///
1153 /// # Note
1154 ///
1155 /// - This operation will **not** allocate memory and computes inplace of `self`.
1156 /// - In the low-level machine abstraction signed division and unsigned division
1157 /// are two different operations.
1158 ///
1159 /// # Errors
1160 ///
1161 /// - If `self` and `rhs` have unmatching bit widths.
1162 pub fn into_checked_div(self, rhs: &UInt) -> Result<UInt> {
1163 try_forward_bin_mut_impl(self, rhs, UInt::checked_div_assign)
1164 }
1165
1166 /// Assignes `self` to the division of `self` by `rhs`.
1167 ///
1168 /// # Note
1169 ///
1170 /// - This operation will **not** allocate memory and computes inplace of `self`.
1171 /// - In the low-level machine abstraction signed division and unsigned division
1172 /// are two different operations.
1173 ///
1174 /// # Errors
1175 ///
1176 /// - If `self` and `rhs` have unmatching bit widths.
1177 pub fn checked_div_assign(&mut self, rhs: &UInt) -> Result<()> {
1178 self.value.checked_udiv_assign(&rhs.value)
1179 }
1180
1181 /// Calculates the **unsigned** remainder of `self` by `rhs` and returns the result.
1182 ///
1183 /// # Note
1184 ///
1185 /// - This operation will **not** allocate memory and computes inplace of `self`.
1186 /// - In the low-level machine abstraction signed division and unsigned division
1187 /// are two different operations.
1188 ///
1189 /// # Errors
1190 ///
1191 /// - If `self` and `rhs` have unmatching bit widths.
1192 pub fn into_checked_rem(self, rhs: &UInt) -> Result<UInt> {
1193 try_forward_bin_mut_impl(self, rhs, UInt::checked_rem_assign)
1194 }
1195
1196 /// Assignes `self` to the **unsigned** remainder of `self` by `rhs`.
1197 ///
1198 /// # Note
1199 ///
1200 /// - This operation will **not** allocate memory and computes inplace of `self`.
1201 /// - In the low-level machine abstraction signed division and unsigned division
1202 /// are two different operations.
1203 ///
1204 /// # Errors
1205 ///
1206 /// - If `self` and `rhs` have unmatching bit widths.
1207 pub fn checked_rem_assign(&mut self, rhs: &UInt) -> Result<()> {
1208 self.value.checked_urem_assign(&rhs.value)
1209 }
1210}
1211
1212// ============================================================================
1213// Add and Add-Assign: `std::ops::Add` and `std::ops::AddAssign`
1214// ============================================================================
1215
1216impl<'a> Add<&'a UInt> for UInt {
1217 type Output = UInt;
1218
1219 fn add(self, rhs: &'a UInt) -> Self::Output {
1220 self.into_checked_add(rhs).unwrap()
1221 }
1222}
1223
1224impl<'a, 'b> Add<&'a UInt> for &'b UInt {
1225 type Output = UInt;
1226
1227 fn add(self, rhs: &'a UInt) -> Self::Output {
1228 self.clone().into_checked_add(rhs).unwrap()
1229 }
1230}
1231
1232impl<'a> AddAssign<&'a UInt> for UInt {
1233 fn add_assign(&mut self, rhs: &'a UInt) {
1234 self.checked_add_assign(rhs).unwrap()
1235 }
1236}
1237
1238// ============================================================================
1239// Sub and Sub-Assign: `std::ops::Sub` and `std::ops::SubAssign`
1240// ============================================================================
1241
1242impl<'a> Sub<&'a UInt> for UInt {
1243 type Output = UInt;
1244
1245 fn sub(self, rhs: &'a UInt) -> Self::Output {
1246 self.into_checked_sub(rhs).unwrap()
1247 }
1248}
1249
1250impl<'a, 'b> Sub<&'a UInt> for &'b UInt {
1251 type Output = UInt;
1252
1253 fn sub(self, rhs: &'a UInt) -> Self::Output {
1254 self.clone().into_checked_sub(rhs).unwrap()
1255 }
1256}
1257
1258impl<'a> SubAssign<&'a UInt> for UInt {
1259 fn sub_assign(&mut self, rhs: &'a UInt) {
1260 self.checked_sub_assign(rhs).unwrap()
1261 }
1262}
1263
1264// ============================================================================
1265// Mul and Mul-Assign: `std::ops::Mul` and `std::ops::MulAssign`
1266// ============================================================================
1267
1268impl<'a> Mul<&'a UInt> for UInt {
1269 type Output = UInt;
1270
1271 fn mul(self, rhs: &'a UInt) -> Self::Output {
1272 self.into_checked_mul(rhs).unwrap()
1273 }
1274}
1275
1276impl<'a, 'b> Mul<&'a UInt> for &'b UInt {
1277 type Output = UInt;
1278
1279 fn mul(self, rhs: &'a UInt) -> Self::Output {
1280 self.clone().into_checked_mul(rhs).unwrap()
1281 }
1282}
1283
1284impl<'a> MulAssign<&'a UInt> for UInt {
1285 fn mul_assign(&mut self, rhs: &'a UInt) {
1286 self.checked_mul_assign(rhs).unwrap();
1287 }
1288}
1289
1290// ============================================================================
1291// Div and Div-Assign: `std::ops::Div` and `std::ops::DivAssign`
1292// ============================================================================
1293
1294impl<'a> Div<&'a UInt> for UInt {
1295 type Output = UInt;
1296
1297 fn div(self, rhs: &'a UInt) -> Self::Output {
1298 self.into_checked_div(rhs).unwrap()
1299 }
1300}
1301
1302impl<'a, 'b> Div<&'a UInt> for &'b UInt {
1303 type Output = UInt;
1304
1305 fn div(self, rhs: &'a UInt) -> Self::Output {
1306 self.clone().into_checked_div(rhs).unwrap()
1307 }
1308}
1309
1310impl<'a> DivAssign<&'a UInt> for UInt {
1311 fn div_assign(&mut self, rhs: &'a UInt) {
1312 self.checked_div_assign(rhs).unwrap();
1313 }
1314}
1315
1316// ============================================================================
1317// Rem and Rem-Assign: `std::ops::Rem` and `std::ops::RemAssign`
1318// ============================================================================
1319
1320impl<'a> Rem<&'a UInt> for UInt {
1321 type Output = UInt;
1322
1323 fn rem(self, rhs: &'a UInt) -> Self::Output {
1324 self.into_checked_rem(rhs).unwrap()
1325 }
1326}
1327
1328impl<'a, 'b> Rem<&'a UInt> for &'b UInt {
1329 type Output = UInt;
1330
1331 fn rem(self, rhs: &'a UInt) -> Self::Output {
1332 self.clone().into_checked_rem(rhs).unwrap()
1333 }
1334}
1335
1336impl<'a> RemAssign<&'a UInt> for UInt {
1337 fn rem_assign(&mut self, rhs: &'a UInt) {
1338 self.checked_rem_assign(rhs).unwrap();
1339 }
1340}
1341
1342// ============================================================================
1343// Binary, Oct, LowerHex and UpperHex implementations
1344// ============================================================================
1345
1346use std::fmt;
1347
1348impl fmt::Binary for UInt {
1349 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1350 self.value.fmt(f)
1351 }
1352}
1353
1354impl fmt::Octal for UInt {
1355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1356 self.value.fmt(f)
1357 }
1358}
1359
1360impl fmt::LowerHex for UInt {
1361 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1362 self.value.fmt(f)
1363 }
1364}
1365
1366impl fmt::UpperHex for UInt {
1367 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1368 self.value.fmt(f)
1369 }
1370}