1use bitpos::BitPos;
2use bitwidth::BitWidth;
3use errors::{Error, Result};
4use traits::{Width};
5use checks;
6
7use std::ops::{
8 Not,
9 BitAnd,
10 BitOr,
11 BitXor,
12 BitAndAssign,
13 BitOrAssign,
14 BitXorAssign,
15
16 Add,
17 Sub,
18 Mul,
19 Div,
20 Rem
21};
22
23pub(crate) type DigitRepr = u64;
27
28pub(crate) type DoubleDigitRepr = u128;
32
33pub(crate) const BITS: usize = 64;
35
36const BASE_REPR: DoubleDigitRepr = 1 << BITS;
38
39pub(crate) const BASE: DoubleDigit = DoubleDigit(BASE_REPR);
40
41const REPR_ONE : DigitRepr = 0x1;
42const REPR_ZERO: DigitRepr = 0x0;
43const REPR_ONES: DigitRepr = !REPR_ZERO;
44
45pub(crate) const ONE : Digit = Digit(REPR_ONE);
46pub(crate) const ZERO: Digit = Digit(REPR_ZERO);
47pub(crate) const ONES: Digit = Digit(REPR_ONES);
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
51pub enum Bit {
52 Unset = 0,
54 Set = 1
56}
57
58impl Bit {
59 #[inline]
64 pub fn to_bool(self) -> bool {
65 match self {
66 Bit::Unset => false,
67 Bit::Set => true
68 }
69 }
70}
71
72impl From<bool> for Bit {
73 #[inline]
74 fn from(flag: bool) -> Bit {
75 if flag { Bit::Set } else { Bit::Unset }
76 }
77}
78
79impl From<Bit> for bool {
80 #[inline]
81 fn from(bit: Bit) -> bool {
82 bit.to_bool()
83 }
84}
85
86#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
90pub(crate) struct Digit(pub DigitRepr);
91
92use std::fmt;
93
94impl fmt::Binary for Digit {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 self.repr().fmt(f)
97 }
98}
99
100impl fmt::Octal for Digit {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 self.repr().fmt(f)
103 }
104}
105
106impl fmt::LowerHex for Digit {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 self.repr().fmt(f)
109 }
110}
111
112impl fmt::UpperHex for Digit {
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 self.repr().fmt(f)
115 }
116}
117
118#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
125pub(crate) struct DoubleDigit(pub DoubleDigitRepr);
126
127impl Add for DoubleDigit {
128 type Output = DoubleDigit;
129
130 fn add(self, rhs: DoubleDigit) -> Self::Output {
131 DoubleDigit(self.repr().wrapping_add(rhs.repr()))
132 }
133}
134
135impl Sub for DoubleDigit {
136 type Output = DoubleDigit;
137
138 fn sub(self, rhs: DoubleDigit) -> Self::Output {
139 DoubleDigit(self.repr().wrapping_sub(rhs.repr()))
140 }
141}
142
143impl Mul for DoubleDigit {
144 type Output = DoubleDigit;
145
146 fn mul(self, rhs: DoubleDigit) -> Self::Output {
147 DoubleDigit(self.repr().wrapping_mul(rhs.repr()))
148 }
149}
150
151impl Div for DoubleDigit {
152 type Output = DoubleDigit;
153
154 fn div(self, rhs: DoubleDigit) -> Self::Output {
155 DoubleDigit(self.repr().wrapping_div(rhs.repr()))
156 }
157}
158
159impl Rem for DoubleDigit {
160 type Output = DoubleDigit;
161
162 fn rem(self, rhs: DoubleDigit) -> Self::Output {
163 DoubleDigit(self.repr().wrapping_rem(rhs.repr()))
164 }
165}
166
167impl DoubleDigit {
168 #[inline]
170 pub(crate) fn repr(self) -> DoubleDigitRepr {
171 self.0
172 }
173
174 #[inline]
176 pub(crate) fn hi(self) -> Digit {
177 Digit((self.0 >> BITS) as DigitRepr)
178 }
179
180 #[inline]
182 pub(crate) fn lo(self) -> Digit {
183 Digit(self.0 as DigitRepr)
184 }
185
186 #[inline]
188 pub(crate) fn hi_lo(self) -> (Digit, Digit) {
189 (self.hi(), self.lo())
190 }
191
192 #[inline]
194 pub(crate) fn from_hi_lo(hi: Digit, lo: Digit) -> DoubleDigit {
195 DoubleDigit((DoubleDigitRepr::from(hi.repr()) << BITS) | DoubleDigitRepr::from(lo.repr()))
196 }
197}
198
199impl Digit {
201 #[inline]
205 pub fn zero() -> Digit { ZERO }
206
207 #[inline]
209 pub fn one() -> Digit { ONE }
210
211 #[inline]
213 pub fn is_zero(self) -> bool { self == ZERO }
214
215 #[inline]
217 pub fn is_one(self) -> bool { self == ONE }
218
219 #[inline]
221 pub fn is_all_set(self) -> bool { self == ONES }
222
223 #[inline]
225 pub fn all_set() -> Digit { ONES }
226}
227
228impl Digit {
230 #[inline]
232 pub fn repr(self) -> DigitRepr {
233 self.0
234 }
235
236 #[inline]
239 pub fn repr_mut(&mut self) -> &mut DigitRepr {
240 &mut self.0
241 }
242
243 #[inline]
245 pub(crate) fn dd(self) -> DoubleDigit {
246 DoubleDigit(DoubleDigitRepr::from(self.repr()))
247 }
248}
249
250impl Digit {
251 fn verify_valid_bitwidth<W>(self, width: W) -> Result<()>
254 where W: Into<BitWidth>
255 {
256 let width = width.into();
257 if width.to_usize() > BITS {
258 return Err(Error::invalid_bitwidth(width.to_usize())
259 .with_annotation(format!("Encountered invalid `BitWidth` for operating \
260 on a `Digit`.")))
261 }
262 Ok(())
263 }
264
265 pub(crate) fn truncate_to<W>(&mut self, to: W) -> Result<()>
278 where W: Into<BitWidth>
279 {
280 let to = to.into();
281 self.verify_valid_bitwidth(to)?;
282 self.0 &= !(REPR_ONES << to.to_usize());
283 Ok(())
284 }
285
286 pub(crate) fn sign_extend_from<W>(&mut self, from: W) -> Result<()>
300 where W: Into<BitWidth>,
301 {
302 let from = from.into();
303 self.verify_valid_bitwidth(from)?;
304
305 let b = from.to_usize(); let x = self.repr() as i64; let m: i64 = 1 << (b - 1); let r: i64 = (x ^ m).wrapping_sub(m); self.0 = r as u64;
312 Ok(())
313 }
314}
315
316impl Width for Digit {
317 #[inline]
318 fn width(&self) -> BitWidth {
319 BitWidth::w64()
320 }
321}
322
323impl Width for DoubleDigit {
324 #[inline]
325 fn width(&self) -> BitWidth {
326 BitWidth::w128()
327 }
328}
329
330impl Digit {
332 #[inline]
337 pub fn least_significant_bit(self) -> Bit {
338 Bit::from((self.repr() & 0x1) != 0)
339 }
340
341 #[inline]
347 pub fn get<P>(self, pos: P) -> Result<Bit>
348 where P: Into<BitPos>
349 {
350 let pos = pos.into();
351 checks::verify_bit_access(&self, pos)?;
352 Ok(Bit::from(((self.repr() >> pos.to_usize()) & 0x01) == 1))
353 }
354
355 #[inline]
361 pub fn set<P>(&mut self, pos: P) -> Result<()>
362 where P: Into<BitPos>
363 {
364 let pos = pos.into();
365 checks::verify_bit_access(self, pos)?;
366 Ok(self.0 |= 0x01 << pos.to_usize())
367 }
368
369 #[inline]
375 pub fn unset<P>(&mut self, pos: P) -> Result<()>
376 where P: Into<BitPos>
377 {
378 let pos = pos.into();
379 checks::verify_bit_access(self, pos)?;
380 Ok(self.0 &= !(0x01 << pos.to_usize()))
381 }
382
383 #[inline]
389 pub fn flip<P>(&mut self, pos: P) -> Result<()>
390 where P: Into<BitPos>
391 {
392 let pos = pos.into();
393 checks::verify_bit_access(self, pos)?;
394 Ok(self.0 ^= 0x01 << pos.to_usize())
395 }
396
397 #[inline]
399 pub fn set_all(&mut self) {
400 self.0 |= REPR_ONES
401 }
402
403 #[inline]
405 pub fn unset_all(&mut self) {
406 self.0 &= REPR_ZERO
407 }
408
409 #[inline]
411 pub fn flip_all(&mut self) {
412 self.0 ^= REPR_ONES
413 }
414
415 #[inline]
425 pub fn retain_last_n(&mut self, n: usize) -> Result<()> {
426 checks::verify_bit_access(self, n)?;
427 Ok(self.0 &= !(REPR_ONES << n))
428 }
429}
430
431impl Not for Digit {
433 type Output = Self;
434
435 fn not(self) -> Self::Output {
436 Digit(!self.repr())
437 }
438}
439
440impl Digit {
441 pub fn not_inplace(&mut self) {
442 self.0 = !self.repr()
443 }
444}
445
446impl BitAnd for Digit {
447 type Output = Self;
448
449 fn bitand(self, rhs: Self) -> Self::Output {
450 Digit(self.repr() & rhs.repr())
451 }
452}
453
454impl BitOr for Digit {
455 type Output = Self;
456
457 fn bitor(self, rhs: Self) -> Self::Output {
458 Digit(self.repr() | rhs.repr())
459 }
460}
461
462impl BitXor for Digit {
463 type Output = Self;
464
465 fn bitxor(self, rhs: Self) -> Self::Output {
466 Digit(self.repr() ^ rhs.repr())
467 }
468}
469
470impl BitAndAssign for Digit {
472 fn bitand_assign(&mut self, rhs: Self) {
473 self.0 &= rhs.repr()
474 }
475}
476
477impl BitOrAssign for Digit {
478 fn bitor_assign(&mut self, rhs: Self) {
479 self.0 |= rhs.repr()
480 }
481}
482
483impl BitXorAssign for Digit {
484 fn bitxor_assign(&mut self, rhs: Self) {
485 self.0 ^= rhs.repr()
486 }
487}
488
489#[cfg(test)]
490mod tests {
491 use super::*;
492
493 mod bit {
494 use super::*;
495
496 #[test]
497 fn from_bool() {
498 assert_eq!(Bit::from(true) , Bit::Set);
499 assert_eq!(Bit::from(false), Bit::Unset);
500 }
501
502 #[test]
503 fn from_bit() {
504 assert_eq!(bool::from(Bit::Set) , true);
505 assert_eq!(bool::from(Bit::Unset), false);
506 }
507 }
508
509 mod double_digit {
510 use super::*;
511
512 static TEST_VALUES: &[DoubleDigitRepr] = &[0, 1, 2, 10, 42, 1337];
513
514 #[test]
515 fn ops_add() {
516 fn assert_for(lhs: DoubleDigitRepr, rhs: DoubleDigitRepr) {
517 assert_eq!(
518 DoubleDigit(lhs) + DoubleDigit(rhs),
519 DoubleDigit(lhs.wrapping_add(rhs))
520 )
521 }
522 for &lhs in TEST_VALUES {
523 for &rhs in TEST_VALUES {
524 assert_for(lhs, rhs)
525 }
526 }
527 }
528
529 #[test]
530 fn ops_sub() {
531 fn assert_for(lhs: DoubleDigitRepr, rhs: DoubleDigitRepr) {
532 assert_eq!(
533 DoubleDigit(lhs) - DoubleDigit(rhs),
534 DoubleDigit(lhs.wrapping_sub(rhs))
535 )
536 }
537 for &lhs in TEST_VALUES {
538 for &rhs in TEST_VALUES {
539 assert_for(lhs, rhs)
540 }
541 }
542 }
543
544 #[test]
545 fn ops_mul() {
546 fn assert_for(lhs: DoubleDigitRepr, rhs: DoubleDigitRepr) {
547 assert_eq!(
548 DoubleDigit(lhs) * DoubleDigit(rhs),
549 DoubleDigit(lhs.wrapping_mul(rhs))
550 )
551 }
552 for &lhs in TEST_VALUES {
553 for &rhs in TEST_VALUES {
554 assert_for(lhs, rhs)
555 }
556 }
557 }
558
559 #[test]
560 fn ops_div() {
561 fn assert_for(lhs: DoubleDigitRepr, rhs: DoubleDigitRepr) {
562 assert_eq!(
563 DoubleDigit(lhs) / DoubleDigit(rhs),
564 DoubleDigit(lhs.wrapping_div(rhs))
565 )
566 }
567 for &lhs in TEST_VALUES {
568 for &rhs in TEST_VALUES {
569 if rhs != 0 {
571 assert_for(lhs, rhs)
572 }
573 }
574 }
575 }
576
577 #[test]
578 fn ops_rem() {
579 fn assert_for(lhs: DoubleDigitRepr, rhs: DoubleDigitRepr) {
580 assert_eq!(
581 DoubleDigit(lhs) % DoubleDigit(rhs),
582 DoubleDigit(lhs.wrapping_rem(rhs))
583 )
584 }
585 for &lhs in TEST_VALUES {
586 for &rhs in TEST_VALUES {
587 if rhs != 0 {
589 assert_for(lhs, rhs)
590 }
591 }
592 }
593 }
594
595 #[test]
596 fn width() {
597 for &val in TEST_VALUES {
598 assert_eq!(DoubleDigit(val).width(), BitWidth::w128());
599 }
600 }
601
602 #[test]
603 fn repr() {
604 fn assert_for(val: DoubleDigitRepr) {
605 assert_eq!(DoubleDigit(val).repr(), val)
606 }
607 for &val in TEST_VALUES {
608 assert_for(val)
609 }
610 }
611
612 #[test]
613 fn hi() {
614 fn assert_for(input: DoubleDigitRepr, expected: DigitRepr) {
615 assert_eq!(DoubleDigit(input).hi(), Digit(expected))
616 }
617 let test_values = &[
618 (0,0),
619 (1,0),
620 (0x0000_0000_0000_0001_0000_0000_0000_0000, 1),
621 (0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF),
622 (0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF, 0),
623 (0x0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000, 0xFFFF_FFFF),
624 (0xFFFF_FFFF_FFFF_FFFF_0000_0000_0000_0000, 0xFFFF_FFFF_FFFF_FFFF),
625 (0x0123_4567_8910_ABCD_EF00_0000_0000_0000, 0x0123_4567_8910_ABCD),
626 (0x0000_0000_0000_00FE_DCBA_0198_7654_3210, 0xFE)
627 ];
628 for &(input, expected) in test_values {
629 assert_for(input, expected)
630 }
631 }
632
633 #[test]
634 fn lo() {
635 fn assert_for(input: DoubleDigitRepr, expected: DigitRepr) {
636 assert_eq!(DoubleDigit(input).lo(), Digit(expected))
637 }
638 let test_values = &[
639 (0,0),
640 (1,1),
641 (0x0000_0000_0000_0001_0000_0000_0000_0000, 0),
642 (0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF),
643 (0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF),
644 (0x0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000, 0xFFFF_FFFF_0000_0000),
645 (0xFFFF_FFFF_FFFF_FFFF_0000_0000_0000_0000, 0),
646 (0x0123_4567_8910_ABCD_EF00_0000_0000_0000, 0xEF00_0000_0000_0000),
647 (0x0000_0000_0000_00FE_DCBA_0198_7654_3210, 0xDCBA_0198_7654_3210)
648 ];
649 for &(input, expected) in test_values {
650 assert_for(input, expected)
651 }
652 }
653
654 #[test]
655 fn hi_lo() {
656 fn assert_for(input: DoubleDigitRepr, expected_hi: DigitRepr, expected_lo: DigitRepr) {
657 assert_eq!(DoubleDigit(input).hi_lo(), (Digit(expected_hi), Digit(expected_lo)))
658 }
659 let test_values = &[
660 (0, (0, 0)),
661 (1, (0, 1)),
662 (0x0000_0000_0000_0001_0000_0000_0000_0000, (1, 0)),
663 (0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, (0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF)),
664 (0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF, (0, 0xFFFF_FFFF_FFFF_FFFF)),
665 (0x0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000, (0xFFFF_FFFF, 0xFFFF_FFFF_0000_0000)),
666 (0xFFFF_FFFF_FFFF_FFFF_0000_0000_0000_0000, (0xFFFF_FFFF_FFFF_FFFF, 0)),
667 (0x0123_4567_8910_ABCD_EF00_0000_0000_0000, (0x0123_4567_8910_ABCD, 0xEF00_0000_0000_0000)),
668 (0x0000_0000_0000_00FE_DCBA_0198_7654_3210, (0x0000_0000_0000_00FE, 0xDCBA_0198_7654_3210))
669 ];
670 for &(input, (expected_hi, expected_lo)) in test_values {
671 assert_for(input, expected_hi, expected_lo)
672 }
673 }
674
675 #[test]
676 fn from_hi_lo() {
677 fn assert_for(hi: DigitRepr, lo: DigitRepr, expected: DoubleDigitRepr) {
678 assert_eq!(DoubleDigit::from_hi_lo(Digit(hi), Digit(lo)), DoubleDigit(expected))
679 }
680 let test_values = &[
681 (0, (0, 0)),
682 (1, (0, 1)),
683 (0x0000_0000_0000_0001_0000_0000_0000_0000, (1, 0)),
684 (0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, (0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF)),
685 (0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF, (0, 0xFFFF_FFFF_FFFF_FFFF)),
686 (0x0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000, (0xFFFF_FFFF, 0xFFFF_FFFF_0000_0000)),
687 (0xFFFF_FFFF_FFFF_FFFF_0000_0000_0000_0000, (0xFFFF_FFFF_FFFF_FFFF, 0)),
688 (0x0123_4567_8910_ABCD_EF00_0000_0000_0000, (0x0123_4567_8910_ABCD, 0xEF00_0000_0000_0000)),
689 (0x0000_0000_0000_00FE_DCBA_0198_7654_3210, (0x0000_0000_0000_00FE, 0xDCBA_0198_7654_3210))
690 ];
691 for &(expected, (hi, lo)) in test_values {
692 assert_for(hi, lo, expected)
693 }
694 }
695 }
696
697 mod digit {
698 use super::*;
699
700 use std::usize;
701
702 static VALID_TEST_POS_VALUES: &[usize] = &[
703 0, 1, 2, 3, 10, 32, 42, 48, 63
704 ];
705
706 static INVALID_TEST_POS_VALUES: &[usize] = &[
707 64, 65, 100, 1337, usize::MAX
708 ];
709
710 static TEST_DIGIT_REPRS: &[DigitRepr] = &[
711 digit::REPR_ZERO,
712 digit::REPR_ONE,
713 digit::REPR_ONES,
714 0x5555_5555_5555_5555,
715 0xAAAA_AAAA_AAAA_AAAA,
716 0xFFFF_FFFF_0000_0000,
717 0x0000_FFFF_FFFF_0000,
718 0x0000_0000_FFFF_FFFF
719 ];
720
721 fn even_digit() -> Digit {
725 Digit(0x5555_5555_5555_5555)
726 }
727
728 fn odd_digit() -> Digit {
732 Digit(0xAAAA_AAAA_AAAA_AAAA)
733 }
734
735 #[test]
736 fn repr() {
737 for &val in TEST_DIGIT_REPRS {
738 assert_eq!(Digit(val).repr(), val);
739 }
740 }
741
742 #[test]
743 fn dd() {
744 for &val in TEST_DIGIT_REPRS {
745 assert_eq!(Digit(val).dd(), DoubleDigit(val as DoubleDigitRepr));
746 }
747 }
748
749 #[test]
750 fn width() {
751 assert_eq!(digit::ONES.width(), BitWidth::w64());
752 assert_eq!(digit::ZERO.width(), BitWidth::w64());
753 assert_eq!(even_digit().width(), BitWidth::w64());
754 assert_eq!(odd_digit().width(), BitWidth::w64());
755 }
756
757 #[test]
758 fn get_ok() {
759 for &pos in VALID_TEST_POS_VALUES {
760 assert_eq!(digit::ONES.get(pos), Ok(Bit::Set));
761 assert_eq!(digit::ZERO.get(pos), Ok(Bit::Unset));
762 assert_eq!(even_digit().get(pos), Ok(if pos % 2 == 0 { Bit::Set } else { Bit::Unset }));
763 assert_eq!(odd_digit().get(pos), Ok(if pos % 2 == 1 { Bit::Set } else { Bit::Unset }));
764 }
765 }
766
767 #[test]
768 fn get_fail() {
769 for &pos in INVALID_TEST_POS_VALUES {
770 let expected_err = Err(Error::invalid_bit_access(pos, BitWidth::w64()));
771 assert_eq!(digit::ONES.get(pos), expected_err);
772 assert_eq!(digit::ZERO.get(pos), expected_err);
773 assert_eq!(digit::even_digit().get(pos), expected_err);
774 assert_eq!(digit::odd_digit().get(pos), expected_err);
775 }
776 }
777
778 #[test]
779 fn set_ok() {
780 for &val in TEST_DIGIT_REPRS {
781 let mut digit = Digit(val);
782 for &pos in VALID_TEST_POS_VALUES {
783 digit.set(pos).unwrap();
784 assert_eq!(digit.get(pos), Ok(Bit::Set));
785 }
786 }
787 }
788
789 #[test]
790 fn set_fail() {
791 for &pos in INVALID_TEST_POS_VALUES {
792 let expected_err = Err(Error::invalid_bit_access(pos, BitWidth::w64()));
793 assert_eq!(digit::ONES.set(pos), expected_err);
794 assert_eq!(digit::ZERO.set(pos), expected_err);
795 assert_eq!(digit::even_digit().set(pos), expected_err);
796 assert_eq!(digit::odd_digit().set(pos), expected_err);
797 }
798 }
799
800 #[test]
811 fn retain_last_n() {
812 let mut d = ONES;
813 d.retain_last_n(32).unwrap();
814 assert_eq!(d, Digit(0x0000_0000_FFFF_FFFF));
815 }
816 }
817}