This function generates a graph for the "segment tree" to calculate carry bits. It assumes both `propagate_bits` and `generate_bits` are arrays with bits dimension pulled out to the outermost level. It also assumes the number of bits is a power of two. Each node of the segment tree labeled `ij` stores two bits `(propagate, generate)` that are used to compute carry[j+1] given carry[i], as `genera
(
propagate_bits: Node,
generate_bits: Node,
overflow_bit: bool,
)
| 282 | /// (carry[0..n-1], None) tuple if overflow_bit=false, |
| 283 | /// representing carry bits and the overflow bit. |
| 284 | fn calculate_carry_bits( |
| 285 | propagate_bits: Node, |
| 286 | generate_bits: Node, |
| 287 | overflow_bit: bool, |
| 288 | ) -> Result<(Node, Option<Node>)> { |
| 289 | let graph = propagate_bits.get_graph(); |
| 290 | |
| 291 | let mut nodes = vec![CarryNode { |
| 292 | propagate: propagate_bits, |
| 293 | generate: generate_bits, |
| 294 | }]; |
| 295 | let bit_len = nodes[0].bit_len()?; |
| 296 | if !bit_len.is_power_of_two() { |
| 297 | return Err(runtime_error!("BinaryAdd only supports numbers with number of bits, which is a power of 2. {} bits provided.", bit_len)); |
| 298 | } |
| 299 | let mut shape = nodes[0].propagate.get_type()?.get_shape(); |
| 300 | shape[0] = 1; |
| 301 | let mut carries = graph.zeros(array_type(shape, BIT))?; |
| 302 | // Two special cases for the overflow_bit=false optimization: |
| 303 | // If the input is 1 bit long: ignore input and just return zero: |
| 304 | if !overflow_bit && bit_len == 1 { |
| 305 | return Ok((carries, None)); |
| 306 | } |
| 307 | // If the input is 2 bits long: we must not join the two nodes on the initial layer. |
| 308 | if overflow_bit || bit_len > 2 { |
| 309 | while nodes.last().unwrap().bit_len()? > 1 { |
| 310 | let last = nodes.last().unwrap(); |
| 311 | nodes.push(last.shrink(overflow_bit)?); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | let mut node_rev_iter = nodes.iter().rev(); |
| 316 | let overflow_bit = if overflow_bit { |
| 317 | let root_node = node_rev_iter.next().unwrap(); |
| 318 | Some(root_node.apply(carries.clone())?) |
| 319 | } else { |
| 320 | None |
| 321 | }; |
| 322 | for node in node_rev_iter { |
| 323 | let lower = node.sub_slice(0, node.bit_len()? as i64)?; |
| 324 | let new_carries = lower.apply(carries.clone())?; |
| 325 | carries = interleave(carries, new_carries)?; |
| 326 | } |
| 327 | |
| 328 | Ok((carries, overflow_bit)) |
| 329 | } |
| 330 | |
| 331 | #[cfg(test)] |
| 332 | mod tests { |
no test coverage detected