1#![cfg_attr(docsrs, feature(doc_cfg))]
4use std::cell::RefCell;
7use std::fmt::Debug;
8use std::ops::Neg;
9use std::rc::Rc;
10
11use crate::boolexpr::{bool_ite, half_adder, opt_full_adder, BoolExprNode};
12use crate::boolexpr_creator::ExprCreator;
13use crate::intexpr::BitVal;
14use crate::writer::VarLit;
15
16pub(super) fn gen_dadda_mult<T>(
17 creator: Rc<RefCell<ExprCreator<T>>>,
18 matrix: &mut [Vec<usize>],
19) -> Vec<usize>
20where
21 T: VarLit + Neg<Output = T> + Debug,
22 isize: TryFrom<T>,
23 <T as TryInto<usize>>::Error: Debug,
24 <T as TryFrom<usize>>::Error: Debug,
25 <isize as TryFrom<T>>::Error: Debug,
26{
27 let max_col_size = matrix.iter().map(|col| col.len()).max().unwrap();
28 let mut step_sizes = vec![];
29 {
30 let mut max_step_size = 2usize;
31 while max_step_size < max_col_size {
32 step_sizes.push(max_step_size);
33 max_step_size += max_step_size >> 1;
34 }
35 }
36 let mut extracol: Vec<usize> = vec![];
37 let mut next_extracol: Vec<usize> = vec![];
38 let matrixlen = matrix.len();
40 for new_column_size in step_sizes.iter().rev() {
41 for (coli, col) in matrix.iter_mut().enumerate() {
42 next_extracol.clear();
43 if col.len() + extracol.len() > *new_column_size {
44 let cells_to_reduce = extracol.len() + col.len() - *new_column_size;
45 let mut src = col.len() - cells_to_reduce - ((cells_to_reduce + 1) >> 1);
46 let mut dest = src;
47 while src < col.len() {
48 let a = BoolExprNode::new(creator.clone(), col[src]);
49 let b = BoolExprNode::new(creator.clone(), col[src + 1]);
50 if coli + 1 < matrixlen {
63 let (s, c) = if src + 2 < col.len() {
64 opt_full_adder(a, b, BoolExprNode::new(creator.clone(), col[src + 2]))
66 } else {
67 half_adder(a, b)
69 };
70 col[dest] = s.index;
71 next_extracol.push(c.index);
72 } else {
73 col[dest] = if src + 2 < col.len() {
75 a ^ b ^ BoolExprNode::new(creator.clone(), col[src + 2])
77 } else {
78 a ^ b
80 }
81 .index;
82 }
83 src += 3;
84 dest += 1;
85 }
86 col.resize(dest, 0);
87 }
88 col.extend(extracol.iter());
89 std::mem::swap(&mut extracol, &mut next_extracol);
90 }
91 }
92
93 let mut output = vec![0; matrix.len()];
95 let mut c = BoolExprNode::new(creator.clone(), 0); for (i, col) in matrix.iter().enumerate().take(matrix.len() - 1) {
97 (output[i], c) = if col.len() == 2 {
98 let (s0, c0) = opt_full_adder(
99 BoolExprNode::new(creator.clone(), col[0]),
100 BoolExprNode::new(creator.clone(), col[1]),
101 c,
102 );
103 (s0.index, c0)
104 } else {
105 let (s0, c0) = half_adder(BoolExprNode::new(creator.clone(), col[0]), c);
106 (s0.index, c0)
107 };
108 }
109 let col = matrix.last().unwrap();
110 output[matrix.len() - 1] = if col.len() == 2 {
111 BoolExprNode::new(creator.clone(), col[0]) ^ BoolExprNode::new(creator, col[1]) ^ c
112 } else if col.len() == 1 {
113 BoolExprNode::new(creator, col[0]) ^ c
114 } else {
115 c
116 }
117 .index;
118
119 output
120}
121
122pub(super) fn gen_dadda_matrix<'a, T>(
123 creator: Rc<RefCell<ExprCreator<T>>>,
124 avector: &'a [usize],
125 bvector: &'a [usize],
126 col_num: usize,
127) -> Vec<Vec<usize>>
128where
129 T: VarLit + Neg<Output = T> + Debug,
130 isize: TryFrom<T>,
131 <T as TryInto<usize>>::Error: Debug,
132 <T as TryFrom<usize>>::Error: Debug,
133 <isize as TryFrom<T>>::Error: Debug,
134{
135 let mut matrix = (0..col_num).into_iter().map(|_| vec![]).collect::<Vec<_>>();
136 for (i, a) in avector.iter().enumerate() {
137 for (j, b) in bvector.iter().enumerate() {
138 if i + j < col_num {
139 matrix[i + j].push(
140 (BoolExprNode::new(creator.clone(), *a)
141 & BoolExprNode::new(creator.clone(), *b))
142 .index,
143 )
144 }
145 }
146 }
147 matrix
148}
149
150pub(super) const fn calc_log_bits(n: usize) -> usize {
151 if n == 0 {
152 return 0;
153 }
154 let nbits = usize::BITS - n.leading_zeros();
155 if (1 << (nbits - 1)) == n {
156 (nbits - 1) as usize
157 } else {
158 nbits as usize
159 }
160}
161
162pub(super) fn iter_shift_left<T, BV>(
163 output: &mut [usize],
164 input: BV,
165 rhs_bit: BoolExprNode<T>,
166 i: usize,
167) where
168 T: VarLit + Neg<Output = T> + Debug,
169 isize: TryFrom<T>,
170 <T as TryInto<usize>>::Error: Debug,
171 <T as TryFrom<usize>>::Error: Debug,
172 <isize as TryFrom<T>>::Error: Debug,
173 BV: BitVal<Output = BoolExprNode<T>> + Copy,
174{
175 output.iter_mut().enumerate().for_each(|(x, out)| {
176 *out = bool_ite(
177 rhs_bit.clone(),
178 if x >= (1usize << i) {
180 input.bit(x - (1 << i))
181 } else {
182 BoolExprNode::new(rhs_bit.creator.clone(), 0)
183 },
184 input.bit(x),
185 )
186 .index
187 });
188}
189
190pub(super) fn iter_shift_right<T, BV>(
191 output: &mut [usize],
192 input: BV,
193 rhs_bit: BoolExprNode<T>,
194 i: usize,
195 sign: bool,
196) where
197 T: VarLit + Neg<Output = T> + Debug,
198 isize: TryFrom<T>,
199 <T as TryInto<usize>>::Error: Debug,
200 <T as TryFrom<usize>>::Error: Debug,
201 <isize as TryFrom<T>>::Error: Debug,
202 BV: BitVal<Output = BoolExprNode<T>> + Copy,
203{
204 output.iter_mut().enumerate().for_each(|(x, out)| {
205 *out = bool_ite(
206 rhs_bit.clone(),
207 if x + (1usize << i) < input.bitnum() {
209 input.bit(x + (1 << i))
210 } else if sign {
211 input.bit(input.bitnum() - 1)
212 } else {
213 BoolExprNode::new(rhs_bit.creator.clone(), 0)
214 },
215 input.bit(x),
216 )
217 .index
218 });
219}
220
221pub(super) fn iter_rotate_left<T, BV>(
222 output: &mut [usize],
223 input: BV,
224 rhs_bit: BoolExprNode<T>,
225 i: usize,
226) where
227 T: VarLit + Neg<Output = T> + Debug,
228 isize: TryFrom<T>,
229 <T as TryInto<usize>>::Error: Debug,
230 <T as TryFrom<usize>>::Error: Debug,
231 <isize as TryFrom<T>>::Error: Debug,
232 BV: BitVal<Output = BoolExprNode<T>> + Copy,
233{
234 output.iter_mut().enumerate().for_each(|(x, out)| {
235 *out = bool_ite(
236 rhs_bit.clone(),
237 if x >= (1usize << i) {
239 input.bit(x - (1 << i))
240 } else {
241 input.bit(input.bitnum() + x - (1 << i))
242 },
243 input.bit(x),
244 )
245 .index
246 });
247}
248
249pub(super) fn iter_rotate_right<T, BV>(
250 output: &mut [usize],
251 input: BV,
252 rhs_bit: BoolExprNode<T>,
253 i: usize,
254) where
255 T: VarLit + Neg<Output = T> + Debug,
256 isize: TryFrom<T>,
257 <T as TryInto<usize>>::Error: Debug,
258 <T as TryFrom<usize>>::Error: Debug,
259 <isize as TryFrom<T>>::Error: Debug,
260 BV: BitVal<Output = BoolExprNode<T>> + Copy,
261{
262 output.iter_mut().enumerate().for_each(|(x, out)| {
263 *out = bool_ite(
264 rhs_bit.clone(),
265 if x + (1usize << i) < input.bitnum() {
267 input.bit(x + (1 << i))
268 } else {
269 input.bit(x + (1 << i) - input.bitnum())
270 },
271 input.bit(x),
272 )
273 .index
274 });
275}
276
277pub(super) fn helper_addc_cout<T, BV>(
279 output: &mut [usize],
280 lhs: BV,
281 rhs: BV,
282 in_carry: BoolExprNode<T>,
283) -> (BoolExprNode<T>, BoolExprNode<T>)
284where
285 T: VarLit + Neg<Output = T> + Debug,
286 isize: TryFrom<T>,
287 <T as TryInto<usize>>::Error: Debug,
288 <T as TryFrom<usize>>::Error: Debug,
289 <isize as TryFrom<T>>::Error: Debug,
290 BV: BitVal<Output = BoolExprNode<T>> + Copy,
291{
292 let n = lhs.bitnum();
293 let mut c = in_carry;
294 for (i, out) in output.iter_mut().enumerate().take(n - 1) {
295 (*out, c) = {
296 let (s0, c0) = opt_full_adder(lhs.bit(i), rhs.bit(i), c);
297 (s0.index, c0)
298 };
299 }
300 let lastbit_c = c.clone();
301 (output[n - 1], c) = {
302 let (s0, c0) = opt_full_adder(lhs.bit(n - 1), rhs.bit(n - 1), c);
303 (s0.index, c0)
304 };
305 (c, lastbit_c)
306}
307
308pub(super) fn helper_subc_cout<T, BV>(
310 output: &mut [usize],
311 lhs: BV,
312 rhs: BV,
313 in_carry: BoolExprNode<T>,
314) -> (BoolExprNode<T>, BoolExprNode<T>)
315where
316 T: VarLit + Neg<Output = T> + Debug,
317 isize: TryFrom<T>,
318 <T as TryInto<usize>>::Error: Debug,
319 <T as TryFrom<usize>>::Error: Debug,
320 <isize as TryFrom<T>>::Error: Debug,
321 BV: BitVal<Output = BoolExprNode<T>> + Copy,
322{
323 let n = lhs.bitnum();
324 let mut c = in_carry;
325 for (i, out) in output.iter_mut().enumerate().take(n - 1) {
326 (*out, c) = {
327 let (s0, c0) = opt_full_adder(lhs.bit(i), !rhs.bit(i), c);
328 (s0.index, c0)
329 };
330 }
331 let lastbit_c = c.clone();
332 (output[n - 1], c) = {
333 let (s0, c0) = opt_full_adder(lhs.bit(n - 1), !rhs.bit(n - 1), c);
334 (s0.index, c0)
335 };
336 (c, lastbit_c)
337}
338
339pub(super) fn helper_addc<T, BV>(output: &mut [usize], lhs: BV, rhs: BV, in_carry: BoolExprNode<T>)
340where
341 T: VarLit + Neg<Output = T> + Debug,
342 isize: TryFrom<T>,
343 <T as TryInto<usize>>::Error: Debug,
344 <T as TryFrom<usize>>::Error: Debug,
345 <isize as TryFrom<T>>::Error: Debug,
346 BV: BitVal<Output = BoolExprNode<T>> + Copy,
347{
348 let mut c = in_carry;
349 let n = lhs.bitnum();
350 for (i, out) in output.iter_mut().enumerate().take(n - 1) {
351 (*out, c) = {
352 let (s0, c0) = opt_full_adder(lhs.bit(i), rhs.bit(i), c);
353 (s0.index, c0)
354 };
355 }
356 output[n - 1] = (lhs.bit(n - 1) ^ rhs.bit(n - 1) ^ c).index;
357}
358
359pub(super) fn helper_subc<T, BV>(output: &mut [usize], lhs: BV, rhs: BV, in_carry: BoolExprNode<T>)
360where
361 T: VarLit + Neg<Output = T> + Debug,
362 isize: TryFrom<T>,
363 <T as TryInto<usize>>::Error: Debug,
364 <T as TryFrom<usize>>::Error: Debug,
365 <isize as TryFrom<T>>::Error: Debug,
366 BV: BitVal<Output = BoolExprNode<T>> + Copy,
367{
368 let mut c = in_carry;
369 let n = lhs.bitnum();
370 for (i, out) in output.iter_mut().enumerate().take(n - 1) {
371 (*out, c) = {
372 let (s0, c0) = opt_full_adder(lhs.bit(i), !rhs.bit(i), c);
373 (s0.index, c0)
374 };
375 }
376 output[n - 1] = (lhs.bit(n - 1) ^ !rhs.bit(n - 1) ^ c).index;
377}
378
379#[cfg(test)]
380mod tests {
381 use super::*;
382 use crate::boolexpr::test_utils::*;
383
384 use crate::intexpr::{IntExprNode, IntModAdd};
385 use generic_array::typenum::*;
386 use generic_array::GenericArray;
387
388 #[test]
389 fn test_gen_dadda_matrix() {
390 {
391 let ec = ExprCreator::new();
392 let a = IntExprNode::<isize, U3, false>::variable(ec.clone());
393 let b = IntExprNode::<isize, U4, false>::variable(ec.clone());
394 let res = gen_dadda_matrix(ec.clone(), &a.indexes, &b.indexes, 6);
395
396 let exp_ec = ExprCreator::new();
397 let a = alloc_boolvars(exp_ec.clone(), 3);
398 let b = alloc_boolvars(exp_ec.clone(), 4);
399 let a0b0 = a[0].clone() & b[0].clone();
400 let a0b1 = a[0].clone() & b[1].clone();
401 let a0b2 = a[0].clone() & b[2].clone();
402 let a0b3 = a[0].clone() & b[3].clone();
403 let a1b0 = a[1].clone() & b[0].clone();
404 let a1b1 = a[1].clone() & b[1].clone();
405 let a1b2 = a[1].clone() & b[2].clone();
406 let a1b3 = a[1].clone() & b[3].clone();
407 let a2b0 = a[2].clone() & b[0].clone();
408 let a2b1 = a[2].clone() & b[1].clone();
409 let a2b2 = a[2].clone() & b[2].clone();
410 let a2b3 = a[2].clone() & b[3].clone();
411 let exp = [
412 vec![a0b0],
413 vec![a0b1, a1b0],
414 vec![a0b2, a1b1, a2b0],
415 vec![a0b3, a1b2, a2b1],
416 vec![a1b3, a2b2],
417 vec![a2b3],
418 ]
419 .into_iter()
420 .map(|c| {
421 Vec::from(c)
422 .into_iter()
423 .map(|x| x.index)
424 .collect::<Vec<_>>()
425 })
426 .collect::<Vec<_>>();
427
428 assert_eq!(exp, res);
429 assert_eq!(*exp_ec.borrow(), *ec.borrow());
430 }
431 {
432 let ec = ExprCreator::new();
433 let a = IntExprNode::<isize, U3, false>::variable(ec.clone());
434 let b = IntExprNode::<isize, U4, false>::variable(ec.clone());
435 let res = gen_dadda_matrix(ec.clone(), &a.indexes, &b.indexes, 4);
436
437 let exp_ec = ExprCreator::new();
438 let a = alloc_boolvars(exp_ec.clone(), 3);
439 let b = alloc_boolvars(exp_ec.clone(), 4);
440 let a0b0 = a[0].clone() & b[0].clone();
441 let a0b1 = a[0].clone() & b[1].clone();
442 let a0b2 = a[0].clone() & b[2].clone();
443 let a0b3 = a[0].clone() & b[3].clone();
444 let a1b0 = a[1].clone() & b[0].clone();
445 let a1b1 = a[1].clone() & b[1].clone();
446 let a1b2 = a[1].clone() & b[2].clone();
447 let a2b0 = a[2].clone() & b[0].clone();
448 let a2b1 = a[2].clone() & b[1].clone();
449 let exp = [
450 vec![a0b0],
451 vec![a0b1, a1b0],
452 vec![a0b2, a1b1, a2b0],
453 vec![a0b3, a1b2, a2b1],
454 ]
455 .into_iter()
456 .map(|c| {
457 Vec::from(c)
458 .into_iter()
459 .map(|x| x.index)
460 .collect::<Vec<_>>()
461 })
462 .collect::<Vec<_>>();
463
464 assert_eq!(exp, res);
465 assert_eq!(*exp_ec.borrow(), *ec.borrow());
466 }
467 }
468
469 #[test]
470 fn test_gen_dadda_mult() {
471 {
472 let ec = ExprCreator::new();
473 let bvs = alloc_boolvars(ec.clone(), 4 * 3);
474 let mut matrix = vec![
475 vec![bvs[0].index],
476 vec![bvs[1].index, bvs[2].index],
477 vec![bvs[3].index, bvs[4].index, bvs[5].index],
478 vec![bvs[6].index, bvs[7].index, bvs[8].index],
479 vec![bvs[9].index, bvs[10].index],
480 vec![bvs[11].index],
481 ];
482 let res = gen_dadda_mult(ec.clone(), &mut matrix);
483
484 let exp_ec = ExprCreator::new();
485 let bvs = alloc_boolvars(exp_ec.clone(), 4 * 3);
486 let (s0, c0) = half_adder(bvs[4].clone(), bvs[5].clone());
490 let (s1, c1) = opt_full_adder(bvs[6].clone(), bvs[7].clone(), bvs[8].clone());
491 let (s2, c2) = half_adder(bvs[9].clone(), bvs[10].clone());
492 let a = IntExprNode::<isize, U6, false> {
493 creator: exp_ec.clone(),
494 indexes: GenericArray::clone_from_slice(&[
495 bvs[0].index,
496 bvs[1].index,
497 bvs[3].index,
498 s1.index,
499 s2.index,
500 bvs[11].index,
501 ]),
502 };
503 let b = IntExprNode::<isize, U6, false> {
504 creator: exp_ec.clone(),
505 indexes: GenericArray::clone_from_slice(&[
506 0,
507 bvs[2].index,
508 s0.index,
509 c0.index,
510 c1.index,
511 c2.index,
512 ]),
513 };
514 let exp = a.mod_add(b);
515
516 assert_eq!(exp.indexes.as_slice(), res.as_slice());
517 assert_eq!(*exp_ec.borrow(), *ec.borrow());
518 }
519 {
520 let ec = ExprCreator::new();
521 let bvs = alloc_boolvars(ec.clone(), 4 * 3);
522 let mut matrix = vec![
523 vec![bvs[0].index],
524 vec![bvs[1].index, bvs[2].index],
525 vec![bvs[3].index, bvs[4].index, bvs[5].index],
526 vec![bvs[6].index, bvs[7].index, bvs[8].index],
527 vec![bvs[9].index, bvs[10].index],
528 vec![bvs[11].index],
529 vec![],
530 ];
531 let res = gen_dadda_mult(ec.clone(), &mut matrix);
532
533 let exp_ec = ExprCreator::new();
534 let bvs = alloc_boolvars(exp_ec.clone(), 4 * 3);
535 let (s0, c0) = half_adder(bvs[4].clone(), bvs[5].clone());
539 let (s1, c1) = opt_full_adder(bvs[6].clone(), bvs[7].clone(), bvs[8].clone());
540 let (s2, c2) = half_adder(bvs[9].clone(), bvs[10].clone());
541 let a = IntExprNode::<isize, U7, false> {
542 creator: exp_ec.clone(),
543 indexes: GenericArray::clone_from_slice(&[
544 bvs[0].index,
545 bvs[1].index,
546 bvs[3].index,
547 s1.index,
548 s2.index,
549 bvs[11].index,
550 0,
551 ]),
552 };
553 let b = IntExprNode::<isize, U7, false> {
554 creator: exp_ec.clone(),
555 indexes: GenericArray::clone_from_slice(&[
556 0,
557 bvs[2].index,
558 s0.index,
559 c0.index,
560 c1.index,
561 c2.index,
562 0,
563 ]),
564 };
565 let exp = a.mod_add(b);
566
567 assert_eq!(exp.indexes.as_slice(), res.as_slice());
568 assert_eq!(*exp_ec.borrow(), *ec.borrow());
569 }
570 {
571 let ec = ExprCreator::new();
572 let bvs = alloc_boolvars(ec.clone(), 4 * 5);
573 let mut matrix = vec![
574 vec![bvs[0].index],
575 vec![bvs[1].index, bvs[2].index],
576 vec![bvs[3].index, bvs[4].index, bvs[5].index],
577 vec![bvs[6].index, bvs[7].index, bvs[8].index, bvs[9].index],
578 vec![bvs[10].index, bvs[11].index, bvs[12].index, bvs[13].index],
579 vec![bvs[14].index, bvs[15].index, bvs[16].index],
580 vec![bvs[17].index, bvs[18].index],
581 vec![bvs[19].index],
582 ];
583 let res = gen_dadda_mult(ec.clone(), &mut matrix);
584
585 let exp_ec = ExprCreator::new();
586 let bvs = alloc_boolvars(exp_ec.clone(), 4 * 5);
587 let (s0, c0) = half_adder(bvs[8].clone(), bvs[9].clone());
592 let (s1, c1) = opt_full_adder(bvs[11].clone(), bvs[12].clone(), bvs[13].clone());
593 let (s2, c2) = half_adder(bvs[15].clone(), bvs[16].clone());
594 let (s0_2, c0_2) = half_adder(bvs[4].clone(), bvs[5].clone());
598 let (s1_2, c1_2) = opt_full_adder(bvs[6].clone(), bvs[7].clone(), s0);
599 let (s2_2, c2_2) = opt_full_adder(bvs[10].clone(), s1, c0);
600 let (s3_2, c3_2) = opt_full_adder(bvs[14].clone(), s2, c1);
601 let (s4_2, c4_2) = opt_full_adder(bvs[17].clone(), bvs[18].clone(), c2);
602 let a = IntExprNode::<isize, U8, false> {
605 creator: exp_ec.clone(),
606 indexes: GenericArray::clone_from_slice(&[
607 bvs[0].index,
608 bvs[1].index,
609 bvs[3].index,
610 s1_2.index,
611 s2_2.index,
612 s3_2.index,
613 s4_2.index,
614 bvs[19].index,
615 ]),
616 };
617 let b = IntExprNode::<isize, U8, false> {
618 creator: exp_ec.clone(),
619 indexes: GenericArray::clone_from_slice(&[
620 0,
621 bvs[2].index,
622 s0_2.index,
623 c0_2.index,
624 c1_2.index,
625 c2_2.index,
626 c3_2.index,
627 c4_2.index,
628 ]),
629 };
630 let exp = a.mod_add(b);
631
632 assert_eq!(exp.indexes.as_slice(), res.as_slice());
633 assert_eq!(*exp_ec.borrow(), *ec.borrow());
634 }
635 {
636 let ec = ExprCreator::new();
637 let bvs = alloc_boolvars(ec.clone(), 4 * 5 - 3);
638 let mut matrix = vec![
639 vec![bvs[0].index],
640 vec![bvs[1].index, bvs[2].index],
641 vec![bvs[3].index, bvs[4].index, bvs[5].index],
642 vec![bvs[6].index, bvs[7].index, bvs[8].index, bvs[9].index],
643 vec![bvs[10].index, bvs[11].index, bvs[12].index, bvs[13].index],
644 vec![bvs[14].index, bvs[15].index, bvs[16].index],
645 ];
646 let res = gen_dadda_mult(ec.clone(), &mut matrix);
647
648 let exp_ec = ExprCreator::new();
649 let bvs = alloc_boolvars(exp_ec.clone(), 4 * 5 - 3);
650 let (s0, c0) = half_adder(bvs[8].clone(), bvs[9].clone());
655 let (s1, c1) = opt_full_adder(bvs[11].clone(), bvs[12].clone(), bvs[13].clone());
656 let s2 = bvs[15].clone() ^ bvs[16].clone();
657 let (s0_2, c0_2) = half_adder(bvs[4].clone(), bvs[5].clone());
661 let (s1_2, c1_2) = opt_full_adder(bvs[6].clone(), bvs[7].clone(), s0);
662 let (s2_2, c2_2) = opt_full_adder(bvs[10].clone(), s1, c0);
663 let s3_2 = bvs[14].clone() ^ s2 ^ c1;
664 let a = IntExprNode::<isize, U6, false> {
667 creator: exp_ec.clone(),
668 indexes: GenericArray::clone_from_slice(&[
669 bvs[0].index,
670 bvs[1].index,
671 bvs[3].index,
672 s1_2.index,
673 s2_2.index,
674 s3_2.index,
675 ]),
676 };
677 let b = IntExprNode::<isize, U6, false> {
678 creator: exp_ec.clone(),
679 indexes: GenericArray::clone_from_slice(&[
680 0,
681 bvs[2].index,
682 s0_2.index,
683 c0_2.index,
684 c1_2.index,
685 c2_2.index,
686 ]),
687 };
688 let exp = a.mod_add(b);
689
690 assert_eq!(exp.indexes.as_slice(), res.as_slice());
691 assert_eq!(*exp_ec.borrow(), *ec.borrow());
692 }
693 {
694 let ec = ExprCreator::new();
695 let bvs = alloc_boolvars(ec.clone(), 5 * 7);
696 let mut matrix = vec![
697 vec![bvs[0].index],
698 vec![bvs[1].index, bvs[2].index],
699 vec![bvs[3].index, bvs[4].index, bvs[5].index],
700 vec![bvs[6].index, bvs[7].index, bvs[8].index, bvs[9].index],
701 vec![
702 bvs[10].index,
703 bvs[11].index,
704 bvs[12].index,
705 bvs[13].index,
706 bvs[14].index,
707 ],
708 vec![
709 bvs[15].index,
710 bvs[16].index,
711 bvs[17].index,
712 bvs[18].index,
713 bvs[19].index,
714 ],
715 vec![
716 bvs[20].index,
717 bvs[21].index,
718 bvs[22].index,
719 bvs[23].index,
720 bvs[24].index,
721 ],
722 vec![bvs[25].index, bvs[26].index, bvs[27].index, bvs[28].index],
723 vec![bvs[29].index, bvs[30].index, bvs[31].index],
724 vec![bvs[32].index, bvs[33].index],
725 vec![bvs[34].index],
726 ];
727 let res = gen_dadda_mult(ec.clone(), &mut matrix);
728
729 let exp_ec = ExprCreator::new();
730 let bvs = alloc_boolvars(exp_ec.clone(), 5 * 7);
731 let (s0, c0) = half_adder(bvs[13].clone(), bvs[14].clone());
737 let (s1, c1) = opt_full_adder(bvs[17].clone(), bvs[18].clone(), bvs[19].clone());
738 let (s2, c2) = opt_full_adder(bvs[22].clone(), bvs[23].clone(), bvs[24].clone());
739 let (s3, c3) = half_adder(bvs[27].clone(), bvs[28].clone());
740 let (s0_2, c0_2) = half_adder(bvs[8].clone(), bvs[9].clone());
745 let (s1_2, c1_2) = opt_full_adder(bvs[11].clone(), bvs[12].clone(), s0);
746 let (s2_2, c2_2) = opt_full_adder(bvs[16].clone(), s1, c0);
747 let (s3_2, c3_2) = opt_full_adder(bvs[21].clone(), s2, c1);
748 let (s4_2, c4_2) = opt_full_adder(bvs[26].clone(), s3, c2);
749 let (s5_2, c5_2) = opt_full_adder(bvs[30].clone(), bvs[31].clone(), c3);
750 let (s0_3, c0_3) = half_adder(bvs[4].clone(), bvs[5].clone());
754 let (s1_3, c1_3) = opt_full_adder(bvs[6].clone(), bvs[7].clone(), s0_2);
755 let (s2_3, c2_3) = opt_full_adder(bvs[10].clone(), s1_2, c0_2);
756 let (s3_3, c3_3) = opt_full_adder(bvs[15].clone(), s2_2, c1_2);
757 let (s4_3, c4_3) = opt_full_adder(bvs[20].clone(), s3_2, c2_2);
758 let (s5_3, c5_3) = opt_full_adder(bvs[25].clone(), s4_2, c3_2);
759 let (s6_3, c6_3) = opt_full_adder(bvs[29].clone(), s5_2, c4_2);
760 let (s7_3, c7_3) = opt_full_adder(bvs[32].clone(), bvs[33].clone(), c5_2);
761 let a = IntExprNode::<isize, U11, false> {
764 creator: exp_ec.clone(),
765 indexes: GenericArray::clone_from_slice(&[
766 bvs[0].index,
767 bvs[1].index,
768 bvs[3].index,
769 s1_3.index,
770 s2_3.index,
771 s3_3.index,
772 s4_3.index,
773 s5_3.index,
774 s6_3.index,
775 s7_3.index,
776 bvs[34].index,
777 ]),
778 };
779 let b = IntExprNode::<isize, U11, false> {
780 creator: exp_ec.clone(),
781 indexes: GenericArray::clone_from_slice(&[
782 0,
783 bvs[2].index,
784 s0_3.index,
785 c0_3.index,
786 c1_3.index,
787 c2_3.index,
788 c3_3.index,
789 c4_3.index,
790 c5_3.index,
791 c6_3.index,
792 c7_3.index,
793 ]),
794 };
795 let exp = a.mod_add(b);
796
797 assert_eq!(exp.indexes.as_slice(), res.as_slice());
798 assert_eq!(*exp_ec.borrow(), *ec.borrow());
799 }
800 }
801}