MCPcopy Create free account
hub / github.com/ciphermodelabs/ciphercore / calculate_carry_bits

Function calculate_carry_bits

ciphercore-base/src/ops/adder.rs:284–329  ·  view source on GitHub ↗

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,
)

Source from the content-addressed store, hash-verified

282/// (carry[0..n-1], None) tuple if overflow_bit=false,
283/// representing carry bits and the overflow bit.
284fn 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)]
332mod tests {

Callers 1

instantiateMethod · 0.85

Calls 12

interleaveFunction · 0.85
bit_lenMethod · 0.80
get_shapeMethod · 0.80
zerosMethod · 0.80
applyMethod · 0.80
cloneMethod · 0.80
array_typeFunction · 0.50
get_graphMethod · 0.45
get_typeMethod · 0.45
pushMethod · 0.45
shrinkMethod · 0.45
sub_sliceMethod · 0.45

Tested by

no test coverage detected