pub struct BV<R: Borrow<Btor> + Clone> { /* private fields */ }
Expand description

A bitvector object: that is, a single symbolic value, consisting of some number of symbolic bits.

This is generic in the Btor reference type. For instance, you could use BV<Rc<Btor>> for single-threaded applications, or BV<Arc<Btor>> for multi-threaded applications.

Implementations

Create a new unconstrained BV variable of the given width.

The symbol, if present, will be used to identify the BV when printing a model or dumping to file. It must be unique if it is present.

width must not be 0.

Example
let btor = Rc::new(Btor::new());
btor.set_opt(BtorOption::ModelGen(ModelGen::All));

// An 8-bit unconstrained `BV` with the symbol "foo"
let bv = BV::new(btor.clone(), 8, Some("foo"));

// Assert that it must be greater than `3`
bv.ugt(&BV::from_u32(btor.clone(), 3, 8)).assert();

// Now any solution must give it a value greater than `3`
assert_eq!(btor.sat(), SolverResult::Sat);
let solution = bv.get_a_solution().as_u64().unwrap();
assert!(solution > 3);

Create a new constant BV representing the given bool (either constant true or constant false).

The resulting BV will be either constant 0 or constant 1, and will have bitwidth 1.

Create a new constant BV representing the given signed integer. The new BV will have the width width, which must not be 0.

Create a new constant BV representing the given unsigned integer. The new BV will have the width width, which must not be 0.

For a code example, see BV::new().

Create a new constant BV representing the given signed integer. The new BV will have the width width, which must not be 0.

Create a new constant BV representing the given unsigned integer. The new BV will have the width width, which must not be 0.

Create the constant 0 of the given width. This is equivalent to from_i32(btor, 0, width), but may be more efficient.

Example
let btor = Rc::new(Btor::new());
let zero = BV::zero(btor.clone(), 8);
assert_eq!(zero.as_u64().unwrap(), 0);

Create the constant 1 of the given width. This is equivalent to from_i32(btor, 1, width), but may be more efficient.

Example
let btor = Rc::new(Btor::new());
let one = BV::one(btor.clone(), 8);
assert_eq!(one.as_u64().unwrap(), 1);

Create a bitvector constant of the given width, where all bits are set to one. This is equivalent to from_i32(btor, -1, width), but may be more efficient.

Example
let btor = Rc::new(Btor::new());
let ones = BV::ones(btor.clone(), 8);
assert_eq!(ones.as_binary_str().unwrap(), "11111111");

Create a new constant BV from the given string bits representing a binary number.

bits must be non-empty and consist only of ‘0’ and/or ‘1’ characters.

The resulting BV will have bitwidth equal to the length of bits.

Create a new constant BV from the given string num representing a (signed) decimal number. The new BV will have the width width, which must not be 0.

Create a new constant BV from the given string num representing a hexadecimal number. The new BV will have the width width, which must not be 0.

Get the value of the BV as a string of ’0’s and ’1’s. This method is only effective for BVs which are constant, as indicated by BV::is_const().

This method does not require the current state to be satisfiable. To get the value of nonconstant BV objects given the current constraints, see get_a_solution(), which does require that the current state be satisfiable.

Returns None if the BV is not constant.

Example
let btor = Rc::new(Btor::new());

// This `BV` is constant, so we get a `Some`
let five = BV::from_u32(btor.clone(), 5, 8);
assert_eq!(five.as_binary_str(), Some("00000101".to_owned()));

// This `BV` is not constant, so we get `None`
let unconstrained = BV::new(btor.clone(), 8, Some("foo"));
assert_eq!(unconstrained.as_binary_str(), None);

Get the value of the BV as a u64. This method is only effective for BVs which are constant, as indicated by BV::is_const().

This method does not require the current state to be satisfiable. To get the value of nonconstant BV objects given the current constraints, see get_a_solution(), which does require that the current state be satisfiable.

Returns None if the BV is not constant, or if the value does not fit in 64 bits.

Example
let btor = Rc::new(Btor::new());

// This `BV` is constant, so we get a `Some`
let five = BV::from_u32(btor.clone(), 5, 8);
assert_eq!(five.as_u64(), Some(5));

// This `BV` is not constant, so we get `None`
let unconstrained = BV::new(btor.clone(), 8, Some("foo"));
assert_eq!(unconstrained.as_u64(), None);

Get the value of the BV as a bool. This method is only effective for BVs which are constant, as indicated by BV::is_const().

Returns true if the BV has a constant nonzero value, or false if the BV has a constant zero value. Returns None if the BV is not constant.

Get a solution for the BV according to the current model.

This requires that model generation is enabled (see Btor::set_opt), and that the most recent call to Btor::sat() returned SolverResult::Sat.

Calling this multiple times on the same BV or different arbitrary BVs (for the same Btor instance) will produce a consistent set of solutions as long as the Btor’s state is not otherwise changed. That is, this queries an underlying model which won’t change unless the Btor state changes.

For a code example, see BV::new().

Get the Btor which this BV belongs to

Get the id of the BV

Get the bitwidth of the BV

Get the symbol of the BV, if one was assigned

Set the symbol of the BV. See notes on BV::new().

Does the BV have a constant value?

Examples
let btor = Rc::new(Btor::new());

// This `BV` is constant
let five = BV::from_u32(btor.clone(), 5, 8);
assert!(five.is_const());

// This `BV` is not constant
let unconstrained = BV::new(btor.clone(), 8, Some("foo"));
assert!(!unconstrained.is_const());

// 5 + [unconstrained] is also not constant
let sum = five.add(&unconstrained);
assert!(!sum.is_const());

// But 5 + 5 is constant
let sum = five.add(&five);
assert!(sum.is_const());

Does self have the same width as other?

Assert that self == 1.

self must have bitwidth 1.

Example
let btor = Rc::new(Btor::new());
btor.set_opt(BtorOption::Incremental(true));
btor.set_opt(BtorOption::ModelGen(ModelGen::All));

// Create an unconstrained `BV`
let bv = BV::new(btor.clone(), 8, Some("foo"));

// Assert that it must be greater than `3`
bv.ugt(&BV::from_u32(btor.clone(), 3, 8)).assert();

// (you may prefer this alternate style for assertions)
BV::assert(&bv.ugt(&BV::from_u32(btor.clone(), 3, 8)));

// The state is satisfiable, and any solution we get
// for `bv` must be greater than `3`
assert_eq!(btor.sat(), SolverResult::Sat);
let solution = bv.get_a_solution().as_u64().unwrap();
assert!(solution > 3);

// Now we assert that `bv` must be less than `2`
bv.ult(&BV::from_u32(btor.clone(), 2, 8)).assert();

// The state is now unsatisfiable
assert_eq!(btor.sat(), SolverResult::Unsat);

Assume that the given node == 1. Assumptions are identical to assertions except that they are discarded after each call to Btor::sat().

Requires incremental usage to be enabled via Btor::set_opt().

Example
let btor = Rc::new(Btor::new());
btor.set_opt(BtorOption::Incremental(true));

// Create an unconstrained `BV`
let bv = BV::new(btor.clone(), 8, Some("foo"));

// Assert that it must be greater than `3`
bv.ugt(&BV::from_u32(btor.clone(), 3, 8)).assert();

// The state is satisfiable
assert_eq!(btor.sat(), SolverResult::Sat);

// Temporarily assume that the `BV` is less than `2`
bv.ult(&BV::from_u32(btor.clone(), 2, 8)).assume();

// The state is now unsatisfiable
assert_eq!(btor.sat(), SolverResult::Unsat);

// The assumption only lasts until the next `sat()`
// call, so it has been discarded now
assert_eq!(btor.sat(), SolverResult::Sat);

Returns true if this node is an assumption that forced the input formula to become unsatisfiable.

Example
let btor = Rc::new(Btor::new());
btor.set_opt(BtorOption::Incremental(true));

// Create an unconstrained `BV` and assert that it is greater
// than `3`; the state is satisfiable
let bv = BV::new(btor.clone(), 8, Some("foo"));
bv.ugt(&BV::from_u32(btor.clone(), 3, 8)).assert();
assert_eq!(btor.sat(), SolverResult::Sat);

// Temporarily assume that the `BV` is less than `2`
let assumption = bv.ult(&BV::from_u32(btor.clone(), 2, 8));
assumption.assume();

// The state is now unsatisfiable, and `assumption` is a
// failed assumption
assert_eq!(btor.sat(), SolverResult::Unsat);
assert!(assumption.is_failed_assumption());

Bitvector equality. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Bitvector inequality. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Bitvector addition. self and other must have the same bitwidth.

Bitvector subtraction. self and other must have the same bitwidth.

Bitvector multiplication. self and other must have the same bitwidth.

Unsigned division. self and other must have the same bitwidth. Division by 0 produces -1.

Signed division. self and other must have the same bitwidth.

Unsigned remainder. self and other must have the same bitwidth. If other is 0, the result will be self.

Signed remainder. self and other must have the same bitwidth. Resulting BV will have positive sign.

Signed remainder. self and other must have the same bitwidth. Resulting BV will have sign matching the divisor.

Increment operation

Decrement operation

Two’s complement negation

Unsigned addition overflow detection. Resulting BV will have bitwidth one, and be true if adding self and other would overflow when interpreting both self and other as unsigned.

Signed addition overflow detection. Resulting BV will have bitwidth one, and be true if adding self and other would overflow when interpreting both self and other as signed.

Unsigned subtraction overflow detection. Resulting BV will have bitwidth one, and be true if subtracting self and other would overflow when interpreting both self and other as unsigned.

Signed subtraction overflow detection. Resulting BV will have bitwidth one, and be true if subtracting self and other would overflow when interpreting both self and other as signed.

Unsigned multiplication overflow detection. Resulting BV will have bitwidth 1, and be true if multiplying self and other would overflow when interpreting both self and other as unsigned.

Signed multiplication overflow detection. Resulting BV will have bitwidth 1, and be true if multiplying self and other would overflow when interpreting both self and other as signed.

Signed division overflow detection. Resulting BV will have bitwidth one, and be true if dividing self by other would overflow when interpreting both self and other as signed.

Signed division can overflow if self is INT_MIN and other is -1. Note that unsigned division cannot overflow.

Bitwise not operation (one’s complement)

Bitwise and operation. self and other must have the same bitwidth.

Bitwise or operation. self and other must have the same bitwidth.

Bitwise xor operation. self and other must have the same bitwidth.

Bitwise nand operation. self and other must have the same bitwidth.

Bitwise nor operation. self and other must have the same bitwidth.

Bitwise xnor operation. self and other must have the same bitwidth.

Logical shift left: shift self left by other bits. Either self and other must have the same bitwidth, or self must have a bitwidth which is a power of two and the bitwidth of other must be log2 of the bitwidth of self.

Resulting BV will have the same bitwidth as self.

Logical shift right: shift self right by other bits. Either self and other must have the same bitwidth, or self must have a bitwidth which is a power of two and the bitwidth of other must be log2 of the bitwidth of self.

Resulting BV will have the same bitwidth as self.

Arithmetic shift right: shift self right by other bits. Either self and other must have the same bitwidth, or self must have a bitwidth which is a power of two and the bitwidth of other must be log2 of the bitwidth of self.

Resulting BV will have the same bitwidth as self.

Rotate self left by other bits. self must have a bitwidth which is a power of two, and the bitwidth of other must be log2 of the bitwidth of self.

Resulting BV will have the same bitwidth as self.

Rotate self right by other bits. self must have a bitwidth which is a power of two, and the bitwidth of other must be log2 of the bitwidth of self.

Resulting BV will have the same bitwidth as self.

and reduction operation: take the Boolean and of all bits in the BV. Resulting BV will have bitwidth 1.

or reduction operation: take the Boolean or of all bits in the BV. Resulting BV will have bitwidth 1.

xor reduction operation: take the Boolean xor of all bits in the BV. Resulting BV will have bitwidth 1.

Unsigned greater than. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Unsigned greater than or equal. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Signed greater than. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Signed greater than or equal. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Unsigned less than. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Unsigned less than or equal. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Signed less than. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Signed less than or equal. self and other must have the same bitwidth. Resulting BV will have bitwidth 1.

Unsigned extension (zero-extension), extending by n bits. Resulting BV will have bitwidth equal to the bitwidth of self plus n.

Example
let btor = Rc::new(Btor::new());

// Create an 8-bit `BV` with value `3`
let bv = BV::from_u32(btor.clone(), 3, 8);

// Zero-extend by 56 bits
let extended = bv.uext(56);

// Resulting `BV` is 64 bits and has value `3`
assert_eq!(extended.get_width(), 64);
assert_eq!(extended.as_u64().unwrap(), 3);

Sign-extension operation, extending by n bits. Resulting BV will have bitwidth equal to the bitwidth of self plus n.

Example
let btor = Rc::new(Btor::new());

// Create an 8-bit `BV` with value `-3`
let bv = BV::from_i32(btor.clone(), -3, 8);

// Sign-extend by 56 bits
let extended = bv.sext(56);

// Resulting `BV` is 64 bits and has value `-3`
assert_eq!(extended.get_width(), 64);
assert_eq!(extended.as_u64().unwrap() as i64, -3);

Slicing operation: obtain bits high through low (inclusive) of self. Resulting BV will have bitwidth high - low + 1.

Requires that 0 <= low <= high < self.get_width().

Example
let btor = Rc::new(Btor::new());

// Create an 8-bit `BV` with this constant value
let bv = BV::from_binary_str(btor.clone(), "01100101");

// Slice out bits 1 through 4, inclusive
let slice = bv.slice(4, 1);

// Resulting slice has width `4` and value `"0010"`
assert_eq!(slice.get_width(), 4);
assert_eq!(slice.as_binary_str().unwrap(), "0010");

Concatenate two bitvectors. Resulting BV will have bitwidth equal to the sum of self and other’s bitwidths.

Example
let btor = Rc::new(Btor::new());

// Create an 8-bit `BV` with value `1`
let one = BV::one(btor.clone(), 8);

// Create an 8-bit `BV` consisting of all ones
let ones = BV::ones(btor.clone(), 8);

// The concatenation has length 16 and this value
let result = ones.concat(&one);
assert_eq!(result.get_width(), 16);
assert_eq!(result.as_binary_str().unwrap(), "1111111100000001");

// Concatenate in the other order
let result = one.concat(&ones);
assert_eq!(result.get_width(), 16);
assert_eq!(result.as_binary_str().unwrap(), "0000000111111111");

Concatenate the BV with itself n times

Returns the BV which is true if self <=> other, else false. self and other must have bitwidth 1.

Returns the BV which is true if self implies other, else false. self and other must have bitwidth 1.

Create an if-then-else BV node. If self is true, then truebv is returned, else falsebv is returned.

self must have bitwidth 1.

Example
let btor = Rc::new(Btor::new());
btor.set_opt(BtorOption::ModelGen(ModelGen::All));

// Create an unconstrained `BV` `x`
let x = BV::new(btor.clone(), 8, Some("x"));

// `y` will be `5` if `x > 10`, else it will be `1`
let five = BV::from_u32(btor.clone(), 5, 8);
let one = BV::one(btor.clone(), 8);
let cond = x.ugt(&BV::from_u32(btor.clone(), 10, 8));
let y = cond.cond_bv(&five, &one);
// (you may prefer this alternate style)
let _y = BV::cond_bv(&cond, &five, &one);

// Now assert that `x < 7`
x.ult(&BV::from_u32(btor.clone(), 7, 8)).assert();

// As a result, `y` must be `1`
assert_eq!(btor.sat(), SolverResult::Sat);
assert_eq!(y.get_a_solution().as_u64().unwrap(), 1);

Create an if-then-else Array node. If self is true, then true_array is returned, else false_array is returned.

self must have bitwidth 1.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Executes the destructor for this type. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.