/// This function confirms that all of the input expressions are direct SATInts, and returns vectors for each input of their bits
/// This function also normalizes direct SATInt operands to a common value range by zero-padding.
// TODO: In the future it may be possible to optimize operations between integers with different bit sizes
// TODO: this could be optimized by just going over the sections of both vectors where the ranges intersect
let (binding, old_min, old_max) = validate_direct_int_operands(vec![value.as_ref().clone()])?;
// There are no expressions to sum, this is a degenerate case that we can handle by returning a constant 0
// Validate all operands are direct SATInts and extract their bit vectors, also calculate a common min and max for all operands to normalize them to the same size by padding with zeroes as needed to simplify the addition logic.
// Addition is implemented as a series of pairwise additions. The bits of the output are defined by iterating over all possible output values, and for each output value k, ORing together ANDs for each pair of input values i,j where i+j=k. This is effectively a big disjunction of all possible ways to sum to k.
/// Matches a `|SATInt|` with an absolute value operation and rewrites it to a direct-encoded absolute-value `SATInt` by grouping input indicator bits by `|value|` and OR-ing each group (named here as buckets) into the corresponding output bit.
// The new range is from the minimum absolute value to the maximum absolute value. The minimum absolute value is either 0 if the old range includes 0, or the smaller of the absolute values of the old min and max if the old range does not include 0. The maximum absolute value is the larger of the absolute values of the old min and max.
// Iterates over all possible input values, calculate their absolute value, and place them in the corresponding bucket. Each bucket corresponds to a possible output value, and contains the disjunction of all input bits that could produce that output.
// For each bucket, if it's empty then the output bit is false, if it contains one element then the output bit is that element, and if it contains multiple elements then the output bit is the OR of all elements in the bucket.