(&self, context: Context, arguments_types: Vec<Type>)
| 60 | #[typetag::serde] |
| 61 | impl CustomOperationBody for LongDivision { |
| 62 | fn instantiate(&self, context: Context, arguments_types: Vec<Type>) -> Result<Graph> { |
| 63 | if arguments_types.len() != 2 { |
| 64 | return Err(runtime_error!( |
| 65 | "Invalid number of arguments for LongDivision, given {}, expected 2", |
| 66 | arguments_types.len() |
| 67 | )); |
| 68 | } |
| 69 | |
| 70 | let dividend_type = arguments_types[0].clone(); |
| 71 | let divisor_type = arguments_types[1].clone(); |
| 72 | if dividend_type.get_scalar_type() != BIT { |
| 73 | return Err(runtime_error!( |
| 74 | "Invalid scalar types for LongDivision: dividend scalar type {}, expected BIT", |
| 75 | dividend_type.get_scalar_type() |
| 76 | )); |
| 77 | } |
| 78 | if divisor_type.get_scalar_type() != BIT { |
| 79 | return Err(runtime_error!( |
| 80 | "Invalid scalar types for LongDivision: divisor scalar type {}, expected BIT", |
| 81 | dividend_type.get_scalar_type() |
| 82 | )); |
| 83 | } |
| 84 | if !divisor_type.is_array() { |
| 85 | return Err(runtime_error!("Divisor in LongDivision must be an array")); |
| 86 | } |
| 87 | if !dividend_type.is_array() { |
| 88 | return Err(runtime_error!("Dividend in LongDivision must be an array")); |
| 89 | } |
| 90 | let types = Types::new(dividend_type, divisor_type)?; |
| 91 | let g_iterate = single_iteration_graph(&context, types.clone())?; |
| 92 | let g = context.create_graph()?; |
| 93 | let dividend = g.input(types.divident_type.clone())?; |
| 94 | let divisor = g.input(types.divisor_type.clone())?; |
| 95 | |
| 96 | // We compute abs(dividend) / abs(divisor) first, and adjust the results at the end. |
| 97 | let (dividend_is_negative, abs_dividend) = abs(dividend, self.signed)?; |
| 98 | let (divisor_is_negative, abs_divisor) = abs(divisor, self.signed)?; |
| 99 | let negative_abs_divisor = negative(abs_divisor.clone())?; |
| 100 | // Pull out dividend bits as first dimesion, and reverse them as we want to process bits |
| 101 | // starting with the most significant bit. We also pull out divisor bits as it's more |
| 102 | // efficient to work with them in this form. |
| 103 | let (dividend_pulled_bits, negative_abs_divisor_pulled_bits) = |
| 104 | pull_out_bits_pair(abs_dividend, negative_abs_divisor)?; |
| 105 | |
| 106 | let dividend_pulled_bits = |
| 107 | dividend_pulled_bits.get_slice(vec![SliceElement::SubArray(None, None, Some(-1))])?; |
| 108 | |
| 109 | // Iterate single bit computation over all dividend bits. |
| 110 | let state = g.create_tuple(vec![ |
| 111 | g.zeros(types.remainder_pulled_bits_type.clone())?, |
| 112 | broadcast( |
| 113 | negative_abs_divisor_pulled_bits, |
| 114 | types.remainder_pulled_bits_type, |
| 115 | )?, |
| 116 | ])?; |
| 117 | let result = g.iterate(g_iterate, state, dividend_pulled_bits.array_to_vector()?)?; |
| 118 | let remainder = put_in_bits(result.tuple_get(0)?.tuple_get(0)?)?; |
| 119 | let quotient_pulled_bits = result.tuple_get(1)?.vector_to_array()?; |
nothing calls this directly
no test coverage detected