apint/
digit.rs

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
23/// The type for the internal `Digit` representation.
24/// 
25/// Must be exactly half the size of `DoubleDigitRepr`.
26pub(crate) type DigitRepr = u64;
27
28/// The type for the internal `DoubleDigit` representation.
29/// 
30/// Must be exactly double the size of `DigitRepr`.
31pub(crate) type DoubleDigitRepr = u128;
32
33/// The amount of bits within a single `Digit`.
34pub(crate) const BITS: usize = 64;
35
36/// The `DoubleDigit` base offset.
37const 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/// Represents the set or unset state of a bit within an `ApInt`.
50#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
51pub enum Bit {
52	/// Unset, or `false` or `off` state.
53	Unset = 0,
54	/// Set, or `true` or `on` state.
55	Set = 1
56}
57
58impl Bit {
59	/// Converts this `Bit` into a `bool`.
60	/// 
61	/// - `Unset` to `false`
62	/// - `Set` to `true`
63	#[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/// A (big) digit within an `ApInt` or similar representations.
87/// 
88/// It uses the `DoubleDigit` as computation unit.
89#[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/// A doubled digit.
119/// 
120/// This is used as a compute unit for `Digit`'s since many `Digit` arithmetic operations
121/// may overflow or have carries this is required in order to not lose those overflow- and underflow values.
122/// 
123/// Has wrapping arithmetics for better machine emulation and improved performance.
124#[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	/// Returns the value as its internal representation.
169	#[inline]
170	pub(crate) fn repr(self) -> DoubleDigitRepr {
171		self.0
172	}
173
174	/// Returns the hi part of this `DoubleDigit` as `Digit`.
175	#[inline]
176	pub(crate) fn hi(self) -> Digit {
177		Digit((self.0 >> BITS) as DigitRepr)
178	}
179
180	/// Returns the hi part of this `DoubleDigit` as `Digit`.
181	#[inline]
182	pub(crate) fn lo(self) -> Digit {
183		Digit(self.0 as DigitRepr)
184	}
185
186	/// Returns the hi and lo parts of this `DoubleDigit` as `Digit` each.
187	#[inline]
188	pub(crate) fn hi_lo(self) -> (Digit, Digit) {
189		(self.hi(), self.lo())
190	}
191
192	/// Returns a `DoubleDigit` from the given hi and lo raw `Digit` parts.
193	#[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
199/// # Constructors
200impl Digit {
201	/// Creates a digit that represents the value `0`.
202	/// 
203	/// **Note:** In twos-complement this means that all bits are `0`.
204	#[inline]
205	pub fn zero() -> Digit { ZERO }
206
207	/// Creates a digit that represents the value `1`.
208	#[inline]
209	pub fn one() -> Digit { ONE	}
210
211	/// Returns `true` if this `Digit` is zero (`0`).
212	#[inline]
213	pub fn is_zero(self) -> bool { self == ZERO }
214
215	/// Returns `true` if this `Digit` is one (`1`).
216	#[inline]
217	pub fn is_one(self) -> bool { self == ONE }
218
219	/// Returns `true` if this `Digit` has all bits set.
220	#[inline]
221	pub fn is_all_set(self) -> bool { self == ONES }
222
223	/// Creates a digit where all bits are initialized to `1`.
224	#[inline]
225	pub fn all_set() -> Digit { ONES }
226}
227
228/// # Utility & helper methods.
229impl Digit {
230	/// Returns the `Digit`'s value as internal representation.
231	#[inline]
232	pub fn repr(self) -> DigitRepr {
233		self.0
234	}
235
236	/// Returns a mutable reference to the underlying representation
237	/// of this `Digit`.
238	#[inline]
239	pub fn repr_mut(&mut self) -> &mut DigitRepr {
240		&mut self.0
241	}
242
243	/// Returns the `DoubleDigit` representation of this `Digit`.
244	#[inline]
245	pub(crate) fn dd(self) -> DoubleDigit {
246		DoubleDigit(DoubleDigitRepr::from(self.repr()))
247	}
248}
249
250impl Digit {
251	/// Validates the given `BitWidth` for `Digit` instances and returns
252	/// an appropriate error if the given `BitWidth` is invalid.
253	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	/// Truncates this `Digit` to the given `BitWidth`.
266	/// 
267	/// This operation just zeros out any bits on this `Digit` 
268	/// with bit positions above the given `BitWidth`.
269	/// 
270	/// # Note
271	/// 
272	/// This is equal to calling `Digit::retain_last_n`.
273	/// 
274	/// # Errors
275	/// 
276	/// - If the given `BitWidth` is invalid for `Digit` instances.
277	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	/// Sign extends this `Digit` from a given `BitWidth` to `64` bits.
287	/// 
288	/// # Note
289	/// 
290	/// - This can be truncated again to a real target `BitWidth` afterwards if
291	///   the users wishes to.
292	/// 
293	/// - Implementation inspired by
294	///   [Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend).
295	/// 
296	/// # Errors
297	/// 
298	/// - If the given `BitWidth` is invalid for `Digit` instances.
299	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();    // number of bits representing the number in x
306		let x = self.repr() as i64; // sign extend this b-bit number to r
307		let m: i64 = 1 << (b - 1);       // mask can be pre-computed if b is fixed
308		// x = x & ((1 << b) - 1);  // (Skip this if bits in x above position b are already zero.)
309		                            // We don't need this step since this condition is an invariant of `Digit`.
310		let r: i64 = (x ^ m).wrapping_sub(m);   // resulting sign-extended number
311		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
330/// # Bitwise access
331impl Digit {
332	/// Returns the least significant `Bit` of this `Digit`.
333	/// 
334	/// Note: This may be useful to determine if a `Digit`
335	///       represents an even or an uneven number for example.
336	#[inline]
337	pub fn least_significant_bit(self) -> Bit {
338		Bit::from((self.repr() & 0x1) != 0)
339	}
340
341	/// Returns `true` if the `n`th bit is set to `1`, else returns `false`.
342	/// 
343	/// # Errors
344	/// 
345	/// If the given `n` is greater than the digit size.
346	#[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	/// Sets the bit at position `pos` to `1`.
356	/// 
357	/// # Errors
358	/// 
359	/// If the given `n` is greater than the digit size.
360	#[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	/// Sets the bit at position `pos` to `0`.
370	/// 
371	/// # Errors
372	/// 
373	/// If the given `n` is greater than the digit size.
374	#[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	/// Flips the bit at position `pos`.
384	/// 
385	/// # Errors
386	/// 
387	/// If the given `n` is greater than the digit size.
388	#[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	/// Sets all bits in this digit to `1`.
398	#[inline]
399	pub fn set_all(&mut self) {
400		self.0 |= REPR_ONES
401	}
402
403	/// Sets all bits in this digit to `0`.
404	#[inline]
405	pub fn unset_all(&mut self) {
406		self.0 &= REPR_ZERO
407	}
408
409	/// Flips all bits in this digit.
410	#[inline]
411	pub fn flip_all(&mut self) {
412		self.0 ^= REPR_ONES
413	}
414
415	/// Unsets all bits but the last `n` ones.
416	/// 
417	/// # Note
418	/// 
419	/// This is equal to calling `Digit::truncate_to`.
420	/// 
421	/// # Errors
422	/// 
423	/// If the given `n` is greater than the digit size.
424	#[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
431/// # Bitwise operations
432impl 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
470// # Bitwise assign operations
471impl 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					// Avoid division by zero.
570					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					// Avoid division by zero.
588					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		/// Returns a digit that has every even bit set, starting at index 0.
722		/// 
723		/// E.g.: `0x....010101`
724		fn even_digit() -> Digit {
725			Digit(0x5555_5555_5555_5555)
726		}
727
728		/// Returns a digit that has every odd bit set, starting at index 0.
729		/// 
730		/// E.g.: `0x....101010`
731		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		// pub fn set(&mut self, n: usize) -> Result<()> {
801		// pub fn unset(&mut self, n: usize) -> Result<()> {
802		// pub fn flip(&mut self, n: usize) -> Result<()> {
803		// pub fn set_all(&mut self) {
804		// pub fn unset_all(&mut self) {
805		// pub fn flip_all(&mut self) {
806		// pub fn set_first_n(&mut self, n: usize) -> Result<()> {
807		// pub fn unset_first_n(&mut self, n: usize) -> Result<()> {
808		// pub fn retain_last_n(&mut self, n: usize) -> Result<()> {
809
810		#[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}