1use crate::bv::arithmetic::mask_double_word;
9use crate::bv::io::strings::ParseIntError;
10use crate::bv::owned::{double_word_from_words, double_word_to_words};
11use crate::{BitVecValue, BitVecValueRef, DoubleWord, WidthInt, Word, mask};
12#[cfg(feature = "rand1")]
13use rand::RngExt;
14
15macro_rules! declare_arith_bin_fn {
18 ($name:ident) => {
19 fn $name<R: BitVecOps>(&self, rhs: &R) -> BitVecValue {
20 debug_assert_eq!(self.width(), rhs.width());
21 debug_assert_eq!(self.words().len(), rhs.words().len());
22 let mut out = BitVecValue::zero(self.width());
23 if self.words().len() == 1 {
24 crate::bv::arithmetic::$name(
26 &mut out.words_mut()[0..1],
27 &self.words()[0..1],
28 &rhs.words()[0..1],
29 self.width(),
30 );
31 } else {
32 crate::bv::arithmetic::$name(
33 out.words_mut(),
34 self.words(),
35 rhs.words(),
36 self.width(),
37 );
38 }
39 out
40 }
41 };
42}
43
44macro_rules! declare_bit_arith_bin_fn {
47 ($name:ident) => {
48 fn $name<R: BitVecOps>(&self, rhs: &R) -> BitVecValue {
49 debug_assert_eq!(self.width(), rhs.width());
50 debug_assert_eq!(self.words().len(), rhs.words().len());
51 let mut out = BitVecValue::zero(self.width());
52 if self.words().len() == 1 {
53 crate::bv::arithmetic::$name(
55 &mut out.words_mut()[0..1],
56 &self.words()[0..1],
57 &rhs.words()[0..1],
58 );
59 } else {
60 crate::bv::arithmetic::$name(out.words_mut(), self.words(), rhs.words());
61 }
62 out
63 }
64 };
65}
66
67pub trait BitVecOps {
69 fn width(&self) -> WidthInt;
70 fn words(&self) -> &[Word];
71
72 fn to_bit_str(&self) -> String {
74 crate::bv::io::strings::to_bit_str(self.words(), self.width())
75 }
76
77 fn to_bit_str_signed(&self) -> String {
79 crate::bv::io::strings::to_bit_str_signed(self.words(), self.width())
80 }
81
82 fn to_hex_str(&self) -> String {
84 crate::bv::io::strings::to_hex_str(self.words(), self.width())
85 }
86
87 fn to_dec_str(&self) -> String {
89 crate::bv::io::strings::to_dec_str(self.words(), self.width())
90 }
91
92 fn to_hex_str_signed(&self) -> String {
94 crate::bv::io::strings::to_hex_str_signed(self.words(), self.width())
95 }
96
97 fn to_bytes_le(&self) -> Vec<u8> {
98 crate::bv::io::bytes::to_bytes_le(self.words(), self.width())
99 }
100
101 #[cfg(feature = "bigint")]
102 fn to_big_int(&self) -> num_bigint::BigInt {
103 crate::bv::io::bigint::to_big_int(self.words(), self.width())
104 }
105
106 #[cfg(feature = "bigint")]
107 fn to_big_uint(&self) -> num_bigint::BigUint {
108 crate::bv::io::bigint::to_big_uint(self.words())
109 }
110
111 #[cfg(feature = "fraction1")]
112 fn to_signed_fixed_point(&self, fraction_width: WidthInt) -> Option<fraction::Fraction> {
113 debug_assert!(fraction_width <= self.width());
114 if self.is_negative() {
115 if self.width() > u64::BITS {
117 None
118 } else {
119 let negated = self.negate();
120 let frac = negated.to_unsigned_fixed_point(fraction_width);
121 frac.map(|f| -f)
122 }
123 } else {
124 self.to_unsigned_fixed_point(fraction_width)
125 }
126 }
127
128 #[cfg(feature = "fraction1")]
129 fn to_unsigned_fixed_point(&self, fraction_width: WidthInt) -> Option<fraction::Fraction> {
130 debug_assert!(fraction_width <= self.width());
131 let denom = 1u64 << fraction_width;
132 self.to_u64().map(|v| fraction::Fraction::new(v, denom))
133 }
134
135 fn to_bool(&self) -> Option<bool> {
137 if self.width() == 1 {
138 Some(crate::bv::arithmetic::word_to_bool(self.words()[0]))
139 } else {
140 None
141 }
142 }
143
144 fn to_u64(&self) -> Option<u64> {
146 debug_assert_eq!(Word::BITS, u64::BITS);
147 let non_zero_msb = self.words().iter().skip(1).any(|w| *w != 0);
149 if non_zero_msb {
150 None
151 } else {
152 Some(self.words().iter().next().cloned().unwrap_or(0))
153 }
154 }
155
156 fn to_i64(&self) -> Option<i64> {
158 debug_assert_eq!(Word::BITS, i64::BITS);
159 if self.width() <= i64::BITS {
160 if self.width() == 0 {
161 Some(0)
162 } else if self.width() == i64::BITS {
163 Some(self.words()[0] as i64)
164 } else {
165 debug_assert_eq!(self.words().len(), 1);
166 if crate::bv::arithmetic::is_neg(self.words(), self.width()) {
167 let extra_sign_bits =
168 crate::bv::arithmetic::mask(Word::BITS - self.width()) << self.width();
169 Some((self.words()[0] | extra_sign_bits) as i64)
170 } else {
171 Some(self.words()[0] as i64)
172 }
173 }
174 } else {
175 let all_zero_msbs = self.words().iter().skip(1).all(|w| *w == 0);
176 let word_0 = self.words()[0];
177 let all_max_msbs = self.words().iter().skip(1).all(|w| *w == Word::MAX);
178 match (
179 all_zero_msbs,
180 all_max_msbs,
181 crate::bv::arithmetic::is_neg(&[word_0], Word::BITS),
182 ) {
183 (true, false, false) => Some(word_0 as i64),
184 (false, true, true) => Some(word_0 as i64),
185 _ => None,
186 }
187 }
188 }
189
190 fn is_true(&self) -> bool {
191 self.width() == 1 && self.words()[0] == 1
192 }
193
194 fn is_false(&self) -> bool {
195 self.width() == 1 && self.words()[0] == 0
196 }
197
198 fn is_zero(&self) -> bool {
199 self.words().iter().all(|w| *w == 0)
200 }
201
202 fn is_one(&self) -> bool {
203 let msbs_are_zero = self.words().iter().skip(1).all(|w| *w == 0);
204 msbs_are_zero && self.words()[0] == 1
205 }
206
207 fn is_all_ones(&self) -> bool {
208 let lsbs_are_max = self
209 .words()
210 .iter()
211 .take(self.words().len() - 1)
212 .all(|w| *w == Word::MAX);
213 lsbs_are_max && (*self.words().last().unwrap() == mask(self.width() % Word::BITS))
214 }
215
216 fn is_negative(&self) -> bool {
217 crate::bv::arithmetic::is_neg(self.words(), self.width())
218 }
219
220 fn is_pow_2(&self) -> Option<WidthInt> {
221 crate::bv::arithmetic::is_pow2(self.words())
222 }
223
224 fn min_width(&self) -> WidthInt {
227 crate::bv::arithmetic::min_width(self.words())
228 }
229
230 fn bit_set_intervals(&self) -> Vec<std::ops::Range<WidthInt>> {
232 match self.width() {
233 0 => vec![],
234 1 if self.is_zero() => vec![],
235 1 => {
236 let range = 0..1;
237 vec![range]
238 }
239 _ => crate::bv::arithmetic::find_ranges_of_ones(self.words()),
240 }
241 }
242
243 declare_arith_bin_fn!(add);
244 declare_arith_bin_fn!(sub);
245 declare_arith_bin_fn!(shift_left);
246 declare_arith_bin_fn!(shift_right);
247 declare_arith_bin_fn!(arithmetic_shift_right);
248
249 fn mul<R: BitVecOps>(&self, rhs: &R) -> BitVecValue {
250 debug_assert_eq!(self.width(), rhs.width());
251 debug_assert_eq!(self.words().len(), rhs.words().len());
252 match (self.words(), rhs.words()) {
253 ([a], [b]) => {
254 BitVecValue::from_u64(a.overflowing_mul(*b).0 & mask(self.width()), self.width())
255 }
256 ([a_lsb, a_msb], [b_lsb, b_msb]) => BitVecValue::from_u128(
257 double_word_from_words(*a_lsb, *a_msb)
258 .overflowing_mul(double_word_from_words(*b_lsb, *b_msb))
259 .0
260 & mask_double_word(self.width()),
261 self.width(),
262 ),
263 (a_words, b_words) => {
264 let mut out = BitVecValue::zero(self.width());
265 crate::bv::arithmetic::mul(out.words_mut(), a_words, b_words, self.width());
266 out
267 }
268 }
269 }
270
271 declare_bit_arith_bin_fn!(and);
272 declare_bit_arith_bin_fn!(or);
273 declare_bit_arith_bin_fn!(xor);
274
275 fn is_equal<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
276 debug_assert_eq!(
277 self.width(),
278 rhs.width(),
279 "cannot compare bv<{}> with bv<{}>",
280 self.width(),
281 rhs.width()
282 );
283 debug_assert_eq!(self.words().len(), rhs.words().len());
284 if self.words().len() == 1 {
285 crate::bv::arithmetic::cmp_equal(self.words(), rhs.words())
287 } else {
288 crate::bv::arithmetic::cmp_equal(self.words(), rhs.words())
289 }
290 }
291
292 fn is_not_equal<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
293 !self.is_equal(rhs)
294 }
295
296 fn is_greater<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
297 debug_assert_eq!(self.width(), rhs.width());
298 debug_assert_eq!(self.words().len(), rhs.words().len());
299 if self.words().len() == 1 {
300 crate::bv::arithmetic::cmp_greater(&self.words()[0..1], &rhs.words()[0..1])
302 } else {
303 crate::bv::arithmetic::cmp_greater(self.words(), rhs.words())
304 }
305 }
306
307 fn is_greater_or_equal<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
308 debug_assert_eq!(self.width(), rhs.width());
309 debug_assert_eq!(self.words().len(), rhs.words().len());
310 if self.words().len() == 1 {
311 crate::bv::arithmetic::cmp_greater_equal(&self.words()[0..1], &rhs.words()[0..1])
313 } else {
314 crate::bv::arithmetic::cmp_greater(self.words(), rhs.words())
315 }
316 }
317
318 fn is_less<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
319 rhs.is_greater(self)
321 }
322
323 fn is_less_or_equal<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
324 rhs.is_greater_or_equal(self)
326 }
327
328 fn is_greater_signed<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
329 debug_assert_eq!(self.width(), rhs.width());
330 debug_assert_eq!(self.words().len(), rhs.words().len());
331 if self.words().len() == 1 {
332 crate::bv::arithmetic::cmp_greater_signed(
334 &self.words()[0..1],
335 &rhs.words()[0..1],
336 self.width(),
337 )
338 } else {
339 crate::bv::arithmetic::cmp_greater_signed(self.words(), rhs.words(), self.width())
340 }
341 }
342
343 fn is_greater_or_equal_signed<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
344 debug_assert_eq!(self.width(), rhs.width());
345 debug_assert_eq!(self.words().len(), rhs.words().len());
346 if self.words().len() == 1 {
347 crate::bv::arithmetic::cmp_greater_equal_signed(
349 &self.words()[0..1],
350 &rhs.words()[0..1],
351 self.width(),
352 )
353 } else {
354 crate::bv::arithmetic::cmp_greater_equal_signed(self.words(), rhs.words(), self.width())
355 }
356 }
357
358 fn is_less_signed<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
359 rhs.is_greater_signed(self)
361 }
362
363 fn is_less_or_equal_signed<R: BitVecOps + ?Sized>(&self, rhs: &R) -> bool {
364 rhs.is_greater_or_equal_signed(self)
366 }
367
368 fn slice(&self, msb: WidthInt, lsb: WidthInt) -> BitVecValue {
369 debug_assert!(msb <= self.width());
370 debug_assert!(msb >= lsb);
371 let out_width = msb - lsb + 1;
372 let mut out = BitVecValue::zero(out_width);
373 if out_width <= Word::BITS {
374 crate::bv::arithmetic::slice(&mut out.words_mut()[0..1], self.words(), msb, lsb);
376 } else {
377 crate::bv::arithmetic::slice(out.words_mut(), self.words(), msb, lsb);
378 }
379 out
380 }
381
382 fn is_bit_set(&self, pos: WidthInt) -> bool {
383 crate::bv::arithmetic::is_bit_set(self.words(), pos)
384 }
385
386 fn sign_extend(&self, by: WidthInt) -> BitVecValue {
387 let out_width = self.width() + by;
388 let mut out = BitVecValue::zero(out_width);
389 if out_width <= Word::BITS {
390 crate::bv::arithmetic::sign_extend(
392 &mut out.words_mut()[0..1],
393 &self.words()[0..1],
394 self.width(),
395 out_width,
396 );
397 } else {
398 crate::bv::arithmetic::sign_extend(
399 out.words_mut(),
400 self.words(),
401 self.width(),
402 out_width,
403 );
404 }
405 out
406 }
407
408 fn zero_extend(&self, by: WidthInt) -> BitVecValue {
409 let out_width = self.width() + by;
410 let mut out = BitVecValue::zero(out_width);
411 if out_width <= Word::BITS {
412 crate::bv::arithmetic::zero_extend(&mut out.words_mut()[0..1], &self.words()[0..1]);
414 } else {
415 crate::bv::arithmetic::zero_extend(out.words_mut(), self.words());
416 }
417 out
418 }
419
420 fn not(&self) -> BitVecValue {
421 let mut out = BitVecValue::zero(self.width());
422 if self.words().len() <= 1 {
423 crate::bv::arithmetic::not(
425 &mut out.words_mut()[0..1],
426 &self.words()[0..1],
427 self.width(),
428 );
429 } else {
430 crate::bv::arithmetic::not(out.words_mut(), self.words(), self.width());
431 }
432 out
433 }
434
435 fn negate(&self) -> BitVecValue {
436 let mut out = BitVecValue::zero(self.width());
437 if self.words().len() <= 1 {
438 crate::bv::arithmetic::negate(
440 &mut out.words_mut()[0..1],
441 &self.words()[0..1],
442 self.width(),
443 );
444 } else {
445 crate::bv::arithmetic::negate(out.words_mut(), self.words(), self.width());
446 }
447 out
448 }
449
450 fn concat<R: BitVecOps + ?Sized>(&self, rhs: &R) -> BitVecValue {
451 let out_width = self.width() + rhs.width();
452 let mut out = BitVecValue::zero(out_width);
453 if out_width <= Word::BITS {
454 crate::bv::arithmetic::concat(
456 &mut out.words_mut()[0..1],
457 &self.words()[0..1],
458 &rhs.words()[0..1],
459 rhs.width(),
460 );
461 } else {
462 crate::bv::arithmetic::concat(out.words_mut(), self.words(), rhs.words(), rhs.width());
463 }
464 out
465 }
466}
467
468macro_rules! declare_in_place_arith_bin_fn {
471 ($name:ident) => {
472 paste::paste! {
473 fn [<$name _in_place>](&mut self, lhs: &impl BitVecOps, rhs: &impl BitVecOps) {
474 let width = self.width();
475 debug_assert_eq!(width, lhs.width());
476 debug_assert_eq!(lhs.width(), rhs.width());
477 crate::bv::arithmetic::$name(self.words_mut(), lhs.words(), rhs.words(), width);
478 }
479 }
480 };
481}
482
483macro_rules! declare_in_place_bit_bin_fn {
486 ($name:ident) => {
487 paste::paste! {
488 fn [<$name _in_place>](&mut self, lhs: &impl BitVecOps, rhs: &impl BitVecOps) {
489 debug_assert_eq!(self.width(), lhs.width());
490 debug_assert_eq!(lhs.width(), rhs.width());
491 crate::bv::arithmetic::$name(self.words_mut(), lhs.words(), rhs.words());
492 }
493 }
494 };
495}
496
497pub trait BitVecMutOps: BitVecOps {
499 fn words_mut(&mut self) -> &mut [Word];
500
501 declare_in_place_arith_bin_fn!(add);
502 declare_in_place_arith_bin_fn!(sub);
503 declare_in_place_arith_bin_fn!(shift_left);
504 declare_in_place_arith_bin_fn!(shift_right);
505 declare_in_place_arith_bin_fn!(arithmetic_shift_right);
506
507 fn mul_in_place(&mut self, lhs: &impl BitVecOps, rhs: &impl BitVecOps) {
508 let width = self.width();
509 match (self.words_mut(), lhs.words(), rhs.words()) {
510 ([dst], [a], [b]) => {
511 *dst = a.overflowing_mul(*b).0 & mask(width);
512 }
513 ([dst_lsb, dst_msb], [a_lsb, a_msb], [b_lsb, b_msb]) => {
514 [*dst_lsb, *dst_msb] = double_word_to_words(
515 double_word_from_words(*a_lsb, *a_msb)
516 .overflowing_mul(double_word_from_words(*b_lsb, *b_msb))
517 .0
518 & mask_double_word(width),
519 );
520 }
521 (dst_words_mut, a_words, b_words) => {
522 crate::bv::arithmetic::mul(dst_words_mut, a_words, b_words, width);
523 }
524 }
525 }
526
527 declare_in_place_bit_bin_fn!(and);
528 declare_in_place_bit_bin_fn!(or);
529 declare_in_place_bit_bin_fn!(xor);
530
531 fn concat_in_place(&mut self, lhs: &impl BitVecOps, rhs: &impl BitVecOps) {
532 let width = self.width();
533 debug_assert_eq!(width, lhs.width() + rhs.width());
534 crate::bv::arithmetic::concat(self.words_mut(), lhs.words(), rhs.words(), rhs.width());
535 }
536
537 fn slice_in_place(&mut self, src: &impl BitVecOps, msb: WidthInt, lsb: WidthInt) {
538 let width = self.width();
539 debug_assert_eq!(width, msb - lsb + 1);
540 crate::bv::arithmetic::slice(self.words_mut(), src.words(), msb, lsb);
541 }
542
543 fn not_in_place(&mut self) {
544 self.words_mut().iter_mut().for_each(|word| *word = !*word);
545 }
546
547 fn negate_in_place(&mut self) {
548 let width = self.width();
549 crate::bv::arithmetic::negate_in_place(self.words_mut(), width);
550 }
551
552 fn sign_extend_in_place(&mut self, src: &impl BitVecOps, by: WidthInt) {
553 let width = self.width();
554 debug_assert_eq!(width, src.width() + by);
555 crate::bv::arithmetic::sign_extend(self.words_mut(), src.words(), src.width(), width);
556 }
557
558 fn zero_extend_in_place(&mut self, src: &impl BitVecOps, by: WidthInt) {
559 let width = self.width();
560 debug_assert_eq!(width, src.width() + by);
561 crate::bv::arithmetic::zero_extend(self.words_mut(), src.words());
562 }
563
564 fn assign<'a>(&mut self, value: impl Into<BitVecValueRef<'a>>) {
565 let value = value.into();
566 debug_assert_eq!(self.width(), value.width());
567 debug_assert_eq!(self.words_mut().len(), value.words().len());
568 self.words_mut().copy_from_slice(value.words());
569 }
570
571 fn mask_msb(&mut self) {
573 let width = self.width();
574 crate::bv::arithmetic::mask_msb(self.words_mut(), width);
575 }
576
577 fn clear(&mut self) {
579 self.words_mut().iter_mut().for_each(|w| {
580 *w = 0;
581 });
582 }
583
584 fn assign_ones(&mut self) {
586 self.words_mut().iter_mut().for_each(|w| {
588 *w = Word::MAX;
589 });
590 self.mask_msb();
591 }
592
593 fn assign_from_u64(&mut self, value: u64) {
594 debug_assert_eq!(Word::BITS, u64::BITS, "basic assumption of this function");
595 self.clear();
597 self.words_mut()[0] = value;
599 self.mask_msb();
601 debug_assert_eq!(
602 self.words()[0],
603 value,
604 "value {value} does not fit into {} bits",
605 self.width()
606 );
607 }
608
609 fn assign_from_u128(&mut self, value: u128) {
610 debug_assert_eq!(
611 DoubleWord::BITS,
612 u128::BITS,
613 "basic assumption of this function"
614 );
615 self.clear();
617 let words = double_word_to_words(value);
619 self.words_mut()[0] = words[0];
620 self.words_mut()[1] = words[1];
621 self.mask_msb();
623 debug_assert_eq!(
624 self.words()[0],
625 words[0],
626 "value {value} does not fit into {} bits",
627 self.width()
628 );
629 debug_assert_eq!(
630 self.words()[1],
631 words[1],
632 "value {value} does not fit into {} bits",
633 self.width()
634 );
635 }
636
637 fn assign_from_i64(&mut self, value: i64) {
638 debug_assert_eq!(Word::BITS, i64::BITS, "basic assumption of this function");
639 let width = self.width();
640 self.clear();
642 if self.words().len() == 1 {
644 let masked = value as u64 & crate::bv::arithmetic::mask(width);
645 self.words_mut()[0] = masked;
646 } else {
647 crate::bv::arithmetic::sign_extend(self.words_mut(), &[value as u64], u64::BITS, width);
648 };
649
650 #[cfg(debug_assertions)]
651 if self.is_negative() {
652 if self.width() < Word::BITS {
653 let extra_sign_bits =
654 crate::bv::arithmetic::mask(Word::BITS - self.width()) << self.width();
655 let word_0 = self.words()[0];
656 let word_0_with_bits = word_0 | extra_sign_bits;
657 debug_assert_eq!(
658 word_0_with_bits,
659 value as u64,
660 "value {value} does not fit into {} bits",
661 self.width()
662 );
663 } else {
664 debug_assert_eq!(
665 self.words()[0],
666 value as u64,
667 "value {value} does not fit into {} bits",
668 self.width()
669 );
670 }
671 } else {
672 debug_assert_eq!(
673 self.words()[0],
674 value as u64,
675 "value {value} does not fit into {} bits",
676 self.width()
677 );
678 }
679 }
680
681 fn assign_from_str_radix(&mut self, value: &str, radix: u32) -> Result<(), ParseIntError> {
682 let width = self.width();
683 crate::bv::io::strings::from_str_radix(value, radix, self.words_mut(), width)
684 }
685
686 fn set_bit(&mut self, pos: WidthInt) {
687 crate::bv::arithmetic::set_bit(self.words_mut(), pos);
688 }
689
690 fn clear_bit(&mut self, pos: WidthInt) {
691 crate::bv::arithmetic::clear_bit(self.words_mut(), pos);
692 }
693
694 #[cfg(feature = "rand1")]
695 fn randomize(&mut self, rng: &mut impl RngExt) {
696 rng.fill(self.words_mut());
697 self.mask_msb();
698 }
699}
700
701#[cfg(test)]
702mod tests {
703 use super::*;
704
705 #[test]
706 fn assign_bit_vector() {
707 let mut dst = BitVecValue::zero(123);
708
709 let src = BitVecValue::from_u64(1111111111, 123);
711 dst.assign(&src);
712
713 let src = BitVecValue::from_u64(1111111111 * 2, 123);
715 let src_ref = BitVecValueRef::from(&src);
716 dst.assign(src_ref);
717
718 let value = src_ref.to_u64().unwrap();
720 assert_eq!(value, 1111111111 * 2);
721 }
722
723 #[test]
724 fn test_is_all_ones() {
725 let mut a = BitVecValue::ones(23);
726 assert!(a.is_all_ones());
727 a.clear_bit(20);
728 assert!(!a.is_all_ones());
729
730 let mut a = BitVecValue::ones(1345);
731 assert!(a.is_all_ones());
732 a.clear_bit(1000);
733 assert!(!a.is_all_ones());
734 a.set_bit(1000);
735 assert!(a.is_all_ones());
736 }
737
738 #[test]
739 fn test_is_one() {
740 let mut a = BitVecValue::zero(23);
741 assert!(!a.is_one());
742 a.set_bit(0);
743 assert!(a.is_one());
744 a.set_bit(20);
745 assert!(!a.is_one());
746 }
747
748 #[test]
749 fn test_is_pow_2() {
750 let mut a = BitVecValue::zero(1456);
751 assert_eq!(a.is_pow_2(), None);
752 a.set_bit(0);
753 assert_eq!(a.is_pow_2(), Some(0));
754 a.set_bit(20);
755 assert_eq!(a.is_pow_2(), None);
756
757 for bit in 0..a.width() {
758 a.clear();
759 a.set_bit(bit);
760 assert_eq!(a.is_pow_2(), Some(bit));
761 }
762 }
763
764 #[test]
765 fn test_bit_set_intervals() {
766 let a = BitVecValue::zero(1456);
767 assert_eq!(a.bit_set_intervals(), []);
768 let a = BitVecValue::from_u64(Word::MAX, Word::BITS);
769 assert_eq!(a.bit_set_intervals(), [0..Word::BITS]);
770 let mut a = BitVecValue::from_u64((1 as Word) << (Word::BITS - 1), 127);
771 assert_eq!(a.bit_set_intervals(), [(Word::BITS - 1)..Word::BITS]);
772 a.set_bit(Word::BITS);
773 assert_eq!(a.bit_set_intervals(), [(Word::BITS - 1)..(Word::BITS + 1)]);
774 a.clear_bit(Word::BITS - 1);
775 assert_eq!(a.bit_set_intervals(), [Word::BITS..(Word::BITS + 1)]);
776 a.set_bit(13);
777 assert_eq!(
778 a.bit_set_intervals(),
779 [13..14, Word::BITS..(Word::BITS + 1)]
780 );
781 a.set_bit(14);
782 assert_eq!(
783 a.bit_set_intervals(),
784 [13..15, Word::BITS..(Word::BITS + 1)]
785 );
786 }
787}