43 using EltW =
typename Backend::V;
47 explicit Logic(
const Backend* bk,
const Field& F) : f_(F), bk_(bk) {}
54 Elt addf(
const Elt& a,
const Elt& b)
const {
return f_.addf(a, b); }
55 Elt mulf(
const Elt& a,
const Elt& b)
const {
return f_.mulf(a, b); }
56 Elt invertf(
const Elt& a)
const {
return f_.invertf(a); }
57 Elt negf(
const Elt& a)
const {
return f_.negf(a); }
58 Elt zero()
const {
return f_.zero(); }
59 Elt one()
const {
return f_.one(); }
60 Elt mone()
const {
return f_.mone(); }
61 Elt elt(uint64_t a)
const {
return f_.of_scalar(a); }
64 Elt elt(
const char (&s)[N])
const {
65 return f_.of_string(s);
79 EltW assert0(
const EltW& a)
const {
return bk_->assert0(a); }
80 EltW add(
const EltW* a,
const EltW& b)
const {
return bk_->add(*a, b); }
82 EltW sub(
const EltW* a,
const EltW& b)
const {
return bk_->sub(*a, b); }
84 EltW mul(
const EltW* a,
const EltW& b)
const {
return bk_->mul(*a, b); }
85 EltW mul(
const Elt& k,
const EltW& b)
const {
return bk_->mul(k, b); }
86 EltW mul(
const Elt& k,
const EltW* a,
const EltW& b)
const {
87 return bk_->mul(k, a, b);
90 EltW ax(
const Elt& a,
const EltW& x)
const {
return bk_->ax(a, x); }
91 EltW axy(
const Elt& a,
const EltW* x,
const EltW& y)
const {
92 return bk_->axy(a, *x, y);
94 EltW axpy(
const EltW* y,
const Elt& a,
const EltW& x)
const {
95 return bk_->axpy(*y, a, x);
97 EltW apy(
const EltW& y,
const Elt& a)
const {
return bk_->apy(y, a); }
99 EltW konst(
const Elt& a)
const {
return bk_->konst(a); }
100 EltW konst(uint64_t a)
const {
return konst(elt(a)); }
103 std::array<EltW, N> konst(
const std::array<Elt, N>& a)
const {
104 std::array<EltW, N> r;
105 for (
size_t i = 0; i < N; ++i) {
136 explicit BitW(
const EltW& bv,
const Field& F)
137 : BitW(F.zero(), F.one(), bv) {}
139 BitW(Elt c0_, Elt c1_,
const EltW& x_) : c0(c0_), c1(c1_), x(x_) {}
144 class bitvec :
public std::array<BitW, N> {};
161 BitW rebase(
const Elt& d0,
const Elt& d1,
const BitW& v)
const {
162 return BitW(addf(d0, mulf(d1, v.c0)), mulf(d1, v.c1), v.x);
165 EltW eval(
const BitW& v)
const {
166 EltW r = ax(v.c1, v.x);
167 if (v.c0 != zero()) {
168 auto c0 = konst(v.c0);
175 EltW assert0(
const BitW& v)
const {
180 EltW assert1(
const BitW& v)
const {
186 EltW assert_eq(
const EltW* a,
const EltW& b)
const {
187 return assert0(sub(a, b));
189 EltW assert_eq(
const BitW* a,
const BitW& b)
const {
190 return assert0(lxor(a, b));
192 EltW assert_implies(
const BitW* a,
const BitW& b)
const {
193 return assert1(limplies(a, b));
198 EltW assert_is_bit(
const BitW& b)
const {
204 return assert_is_bit(eb);
206 EltW assert_is_bit(
const EltW& v)
const {
207 auto vvmv = sub(&v, mul(&v, v));
208 return assert0(vvmv);
213 BitW bit(
size_t b)
const {
214 return BitW((b == 0) ? zero() : one(), zero(), konst(one()));
217 void bits(
size_t n,
BitW a[], uint64_t x)
const {
218 for (
size_t i = 0; i < n; ++i) {
219 a[i] = bit((x >> i) & 1u);
229 return rebase(one(), mone(), x);
239 EltW lmul(
const BitW* a,
const EltW& b)
const {
241 auto ab = mulv(a,
BitW(b, f_));
244 EltW lmul(
const EltW* b,
const BitW& a)
const {
return lmul(&a, *b); }
247 return lxor_aux(*a, b,
typename Field::TypeTag());
250 return lxor_aux(*a, *b,
typename Field::TypeTag());
255 auto nab = land(&na, lnot(b));
266 BitW lor_exclusive(
const BitW* a,
const BitW& b)
const {
return addv(*a, b); }
275 auto xy = land(x, *y);
277 return lor_exclusive(&xy, land(&nx, z));
284 BitW p = lxor(x, *y);
285 BitW g = land(x, *y);
286 return lor_exclusive(&g, land(&p, z));
290 BitW mux(
const BitW* control,
const BitW* iftrue,
const BitW& iffalse)
const {
291 auto cif = land(control, *iftrue);
292 auto nc = lnot(*control);
293 auto ciff = land(&nc, *iffalse);
294 return lor_exclusive(&cif, ciff);
298 EltW mux(
const BitW* control,
const EltW* iftrue,
const EltW& iffalse)
const {
299 auto cif = lmul(control, *iftrue);
300 auto nc = lnot(*control);
301 auto ciff = lmul(&nc, iffalse);
302 return add(&cif, ciff);
306 EltW add(
size_t i0,
size_t i1,
const std::function<EltW(
size_t)>& f)
const {
309 }
else if (i1 == i0 + 1) {
312 size_t im = i0 + (i1 - i0) / 2;
313 auto lh = add(i0, im, f);
314 auto rh = add(im, i1, f);
320 BitW lor_exclusive(
size_t i0,
size_t i1,
321 const std::function<
BitW(
size_t)>& f)
const {
324 }
else if (i1 == i0 + 1) {
327 size_t im = i0 + (i1 - i0) / 2;
328 auto lh = lor_exclusive(i0, im, f);
329 auto rh = lor_exclusive(im, i1, f);
330 return lor_exclusive(&lh, rh);
335 BitW land(
size_t i0,
size_t i1,
const std::function<
BitW(
size_t)>& f)
const {
338 }
else if (i1 == i0 + 1) {
341 size_t im = i0 + (i1 - i0) / 2;
342 auto lh = land(i0, im, f);
343 auto rh = land(im, i1, f);
344 return land(&lh, rh);
349 BitW lor(
size_t i0,
size_t i1,
const std::function<
BitW(
size_t)>& f)
const {
352 }
else if (i1 == i0 + 1) {
355 size_t im = i0 + (i1 - i0) / 2;
356 auto lh = lor(i0, im, f);
357 auto rh = lor(im, i1, f);
362 BitW or_of_and(std::vector<std::vector<BitW>> clauses_of_ands)
const {
363 std::vector<BitW> ands(clauses_of_ands.size());
364 for (
size_t i = 0; i < clauses_of_ands.size(); ++i) {
365 auto ai = clauses_of_ands[i];
366 BitW res = land(0, ai.size(), [&](
size_t i) { return ai[i]; });
369 return lor(0, ands.size(), [&](
size_t i) { return ands[i]; });
373 EltW mul(
size_t i0,
size_t i1,
const std::function<EltW(
size_t)>& f)
const {
376 }
else if (i1 == i0 + 1) {
379 size_t im = i0 + (i1 - i0) / 2;
380 auto lh = mul(i0, im, f);
381 auto rh = mul(im, i1, f);
387 void assert_sum(
size_t w,
const BitW c[],
const BitW a[],
388 const BitW b[])
const {
391 std::vector<BitW> g(w), p(w), cy(w);
392 for (
size_t i = 0; i < w; ++i) {
393 g[i] = land(&a[i], b[i]);
394 p[i] = lxor(&a[i], &b[i]);
400 assert_eq(&c[0], p[0]);
401 for (
size_t i = 1; i < w; ++i) {
402 cy[i - 1] = lxor(&c[i], p[i]);
408 assert_eq(&cy[0], g[0]);
409 for (
size_t i = 1; i + 1 < w; ++i) {
410 auto cyp = land(&cy[i - 1], p[i]);
411 auto g_cyp = lor_exclusive(&g[i], cyp);
412 assert_eq(&cy[i], g_cyp);
417 BitW ripple_carry_add(
size_t w,
BitW c[],
const BitW a[],
418 const BitW b[])
const {
419 return generic_gp_add(w, c, a, b, &Logic::ripple_scan);
423 BitW ripple_carry_sub(
size_t w,
BitW c[],
const BitW a[],
424 const BitW b[])
const {
425 return generic_gp_sub(w, c, a, b, &Logic::ripple_scan);
428 BitW parallel_prefix_add(
size_t w,
BitW c[],
const BitW a[],
429 const BitW b[])
const {
430 return generic_gp_add(w, c, a, b, &Logic::sklansky_scan);
433 BitW parallel_prefix_sub(
size_t w,
BitW c[],
const BitW a[],
434 const BitW b[])
const {
435 return generic_gp_sub(w, c, a, b, &Logic::sklansky_scan);
439 void multiplier(
size_t w,
BitW c[],
const BitW a[],
440 const BitW b[])
const {
441 std::vector<BitW> t(w);
442 for (
size_t i = 0; i < w; ++i) {
444 for (
size_t j = 0; j < w; ++j) {
445 c[j] = land(&a[0], b[j]);
449 for (
size_t j = 0; j < w; ++j) {
450 t[j] = land(&a[i], b[j]);
452 BitW carry = ripple_carry_add(w, c + i, t.data(), c + i);
459 void gf2_polynomial_multiplier(
size_t w,
BitW c[],
const BitW a[],
460 const BitW b[])
const {
461 std::vector<BitW> t(w);
462 for (
size_t k = 0; k < 2 * w; ++k) {
464 for (
size_t i = 0; i < w; ++i) {
465 if (k >= i && k - i < w) {
466 t[n++] = land(&a[i], b[k - i]);
469 c[k] = parity(0, n, t.data());
475 void gf2_polynomial_multiplier_karat(
size_t w,
BitW c[],
477 const BitW b[])
const {
478 check(w == 128 || w == 64 || w < 64,
"input length is not a power of 2");
480 gf2_polynomial_multiplier(w, c, a, b);
484 std::vector<BitW> a01(w / 2);
485 std::vector<BitW> b01(w / 2);
486 std::vector<BitW> ab01(w);
487 std::vector<BitW> a0b0(w);
488 std::vector<BitW> a1b1(w);
490 for (
size_t i = 0; i < w / 2; ++i) {
491 a01[i] = lxor(&a[i], a[i + w / 2]);
492 b01[i] = lxor(&b[i], b[i + w / 2]);
495 gf2_polynomial_multiplier_karat(w / 2, &ab01[0], &a01[0], &b01[0]);
496 gf2_polynomial_multiplier_karat(w / 2, &a0b0[0], a, b);
497 gf2_polynomial_multiplier_karat(w / 2, &a1b1[0], a + w / 2, b + w / 2);
499 for (
size_t i = 0; i < w; ++i) {
500 ab01[i] = lxor3(&ab01[i], &a0b0[i], a1b1[i]);
503 for (
size_t i = 0; i < w/2; ++i) {
505 c[i + w/2] = lxor(&a0b0[i + w/2], ab01[i]);
506 c[i + w] = lxor(&ab01[i + w/2], a1b1[i]);
507 c[i + 3*w/2] = a1b1[i + w/2];
527 void gf2_128_mul(v128& c,
const v128 a,
const v128 b)
const {
528 const std::vector<uint16_t> taps[128] = {
530 {1, 128, 129, 249, 250, 254},
531 {2, 128, 129, 130, 249, 250, 251, 254},
532 {3, 129, 130, 131, 250, 251, 252},
533 {4, 130, 131, 132, 251, 252, 253},
534 {5, 131, 132, 133, 252, 253, 254},
535 {6, 132, 133, 134, 253, 254},
536 {7, 128, 133, 134, 135, 249},
537 {8, 129, 134, 135, 136, 250},
538 {9, 130, 135, 136, 137, 251},
539 {10, 131, 136, 137, 138, 252},
540 {11, 132, 137, 138, 139, 253},
541 {12, 133, 138, 139, 140, 254},
542 {13, 134, 139, 140, 141},
543 {14, 135, 140, 141, 142},
544 {15, 136, 141, 142, 143},
545 {16, 137, 142, 143, 144},
546 {17, 138, 143, 144, 145},
547 {18, 139, 144, 145, 146},
548 {19, 140, 145, 146, 147},
549 {20, 141, 146, 147, 148},
550 {21, 142, 147, 148, 149},
551 {22, 143, 148, 149, 150},
552 {23, 144, 149, 150, 151},
553 {24, 145, 150, 151, 152},
554 {25, 146, 151, 152, 153},
555 {26, 147, 152, 153, 154},
556 {27, 148, 153, 154, 155},
557 {28, 149, 154, 155, 156},
558 {29, 150, 155, 156, 157},
559 {30, 151, 156, 157, 158},
560 {31, 152, 157, 158, 159},
561 {32, 153, 158, 159, 160},
562 {33, 154, 159, 160, 161},
563 {34, 155, 160, 161, 162},
564 {35, 156, 161, 162, 163},
565 {36, 157, 162, 163, 164},
566 {37, 158, 163, 164, 165},
567 {38, 159, 164, 165, 166},
568 {39, 160, 165, 166, 167},
569 {40, 161, 166, 167, 168},
570 {41, 162, 167, 168, 169},
571 {42, 163, 168, 169, 170},
572 {43, 164, 169, 170, 171},
573 {44, 165, 170, 171, 172},
574 {45, 166, 171, 172, 173},
575 {46, 167, 172, 173, 174},
576 {47, 168, 173, 174, 175},
577 {48, 169, 174, 175, 176},
578 {49, 170, 175, 176, 177},
579 {50, 171, 176, 177, 178},
580 {51, 172, 177, 178, 179},
581 {52, 173, 178, 179, 180},
582 {53, 174, 179, 180, 181},
583 {54, 175, 180, 181, 182},
584 {55, 176, 181, 182, 183},
585 {56, 177, 182, 183, 184},
586 {57, 178, 183, 184, 185},
587 {58, 179, 184, 185, 186},
588 {59, 180, 185, 186, 187},
589 {60, 181, 186, 187, 188},
590 {61, 182, 187, 188, 189},
591 {62, 183, 188, 189, 190},
592 {63, 184, 189, 190, 191},
593 {64, 185, 190, 191, 192},
594 {65, 186, 191, 192, 193},
595 {66, 187, 192, 193, 194},
596 {67, 188, 193, 194, 195},
597 {68, 189, 194, 195, 196},
598 {69, 190, 195, 196, 197},
599 {70, 191, 196, 197, 198},
600 {71, 192, 197, 198, 199},
601 {72, 193, 198, 199, 200},
602 {73, 194, 199, 200, 201},
603 {74, 195, 200, 201, 202},
604 {75, 196, 201, 202, 203},
605 {76, 197, 202, 203, 204},
606 {77, 198, 203, 204, 205},
607 {78, 199, 204, 205, 206},
608 {79, 200, 205, 206, 207},
609 {80, 201, 206, 207, 208},
610 {81, 202, 207, 208, 209},
611 {82, 203, 208, 209, 210},
612 {83, 204, 209, 210, 211},
613 {84, 205, 210, 211, 212},
614 {85, 206, 211, 212, 213},
615 {86, 207, 212, 213, 214},
616 {87, 208, 213, 214, 215},
617 {88, 209, 214, 215, 216},
618 {89, 210, 215, 216, 217},
619 {90, 211, 216, 217, 218},
620 {91, 212, 217, 218, 219},
621 {92, 213, 218, 219, 220},
622 {93, 214, 219, 220, 221},
623 {94, 215, 220, 221, 222},
624 {95, 216, 221, 222, 223},
625 {96, 217, 222, 223, 224},
626 {97, 218, 223, 224, 225},
627 {98, 219, 224, 225, 226},
628 {99, 220, 225, 226, 227},
629 {100, 221, 226, 227, 228},
630 {101, 222, 227, 228, 229},
631 {102, 223, 228, 229, 230},
632 {103, 224, 229, 230, 231},
633 {104, 225, 230, 231, 232},
634 {105, 226, 231, 232, 233},
635 {106, 227, 232, 233, 234},
636 {107, 228, 233, 234, 235},
637 {108, 229, 234, 235, 236},
638 {109, 230, 235, 236, 237},
639 {110, 231, 236, 237, 238},
640 {111, 232, 237, 238, 239},
641 {112, 233, 238, 239, 240},
642 {113, 234, 239, 240, 241},
643 {114, 235, 240, 241, 242},
644 {115, 236, 241, 242, 243},
645 {116, 237, 242, 243, 244},
646 {117, 238, 243, 244, 245},
647 {118, 239, 244, 245, 246},
648 {119, 240, 245, 246, 247},
649 {120, 241, 246, 247, 248},
650 {121, 242, 247, 248, 249},
651 {122, 243, 248, 249, 250},
652 {123, 244, 249, 250, 251},
653 {124, 245, 250, 251, 252},
654 {125, 246, 251, 252, 253},
655 {126, 247, 252, 253, 254},
656 {127, 248, 253, 254},
658 gf2k_mul(c.data(), a.data(), b.data(), taps, 128);
663 const std::vector<uint16_t> M[],
size_t w)
const {
664 std::vector<BitW> t(w * 2);
665 gf2_polynomial_multiplier_karat(w, t.data(), a, b);
667 std::vector<BitW> tmp(w);
668 for (
size_t i = 0; i < w; ++i) {
670 for (
auto ti : M[i]) {
673 c[i] = parity(0, n, tmp.data());
678 BitW eq0(
size_t w,
const BitW a[])
const {
return eq0(0, w, a); }
681 BitW eq(
size_t w,
const BitW a[],
const BitW b[])
const {
682 return eq_reduce(0, w, a, b);
687 BitW lt(
size_t w,
const BitW a[],
const BitW b[])
const {
692 lt_reduce(0, w, &xeq, &xlt, a, b);
698 BitW leq(
size_t w,
const BitW a[],
const BitW b[])
const {
699 auto blt = lt(w, b, a);
705 void scan(
const std::function<
void(T*,
const T&,
const T&)>& op, T x[],
706 size_t i0,
size_t i1,
bool backward =
false)
const {
709 size_t im = i0 + (i1 - i0) / 2;
710 scan(op, x, i0, im, backward);
711 scan(op, x, im, i1, backward);
713 for (
size_t i = i0; i < im; ++i) {
714 op(&x[i], x[i], x[im]);
717 for (
size_t i = im; i < i1; ++i) {
718 op(&x[i], x[im - 1], x[i]);
724 void scan_and(
BitW x[],
size_t i0,
size_t i1,
bool backward =
false)
const {
726 [&](
BitW* out,
const BitW& l,
const BitW& r) { *out = land(&l, r); }, x,
730 void scan_or(
BitW x[],
size_t i0,
size_t i1,
bool backward =
false)
const {
732 [&](
BitW* out,
const BitW& l,
const BitW& r) { *out = lor(&l, r); }, x,
736 void scan_xor(
BitW x[],
size_t i0,
size_t i1,
bool backward =
false)
const {
738 [&](
BitW* out,
const BitW& l,
const BitW& r) { *out = lxor(&l, r); }, x,
742 template <
size_t I0,
size_t I1,
size_t N>
745 for (
size_t i = I0; i < I1; ++i) {
753 template <
size_t NA,
size_t NB>
756 for (
size_t i = 0; i < NA; ++i) {
759 for (
size_t i = 0; i < NB; ++i) {
767 for (
size_t i = 0; i < N; ++i) {
768 auto eai = eval((*a)[i]);
769 auto ebi = eval(b[i]);
770 if (eai != ebi)
return false;
778 bits(N, r.data(), x);
783 v8 vbit8(uint64_t x)
const {
return vbit<8>(x); }
784 v32 vbit32(uint64_t x)
const {
return vbit<32>(x); }
789 for (
size_t i = 0; i < N; ++i) {
798 for (
size_t i = 0; i < N; ++i) {
799 r[i] = land(&(*a)[i], b[i]);
807 for (
size_t i = 0; i < N; ++i) {
808 r[i] = land(a, b[i]);
816 for (
size_t i = 0; i < N; ++i) {
817 r[i] = lor(&(*a)[i], b[i]);
824 for (
size_t i = 0; i < N; ++i) {
825 r[i] = lor_exclusive(&(*a)[i], b[i]);
832 for (
size_t i = 0; i < N; ++i) {
833 r[i] = lxor(&(*a)[i], b[i]);
842 for (
size_t i = 0; i < N; ++i) {
843 r[i] = lCh(&(*x)[i], &(*y)[i], z[i]);
851 for (
size_t i = 0; i < N; ++i) {
852 r[i] = lMaj(&(*x)[i], &(*y)[i], z[i]);
861 for (
size_t i = 0; i < N; ++i) {
862 r[i] = lxor3(&(*x)[i], &(*y)[i], z[i]);
870 for (
size_t i = 0; i < N; ++i) {
883 for (
size_t i = 0; i < N; ++i) {
896 for (
size_t i = 0; i < N; ++i) {
897 r[i] = a[(i + b) % N];
905 for (
size_t i = 0; i < N; ++i) {
906 r[(i + b) % N] = a[i];
914 (void)parallel_prefix_add(N, &r[0], &a[0], &b[0]);
919 return vadd(a, vbit<N>(val));
924 return eq(N, a.data(), b.data());
928 auto v = vbit<N>(val);
933 return lt(N, (*a).data(), b.data());
937 auto v = vbit<N>(val);
942 auto va = vbit<N>(a);
947 return leq(N, (*a).data(), b.data());
951 auto v = vbit<N>(val);
958 auto r = vxor(a, val);
959 size_t n = pack(mask, N, &r[0]);
960 return eq0(0, n, &r[0]);
964 BitW veqmask(
const bitvec<N>& a, uint64_t mask, uint64_t val)
const {
965 auto v = vbit<N>(val);
966 return veqmask(&a, mask, v);
973 BitW input()
const {
return BitW(bk_->input(), f_); }
974 void output(
const BitW& x,
size_t i)
const { bk_->output(eval(x), i); }
975 size_t wire_id(
const BitW& v)
const {
return bk_->wire_id(v.x); }
976 size_t wire_id(
const EltW& x)
const {
return bk_->wire_id(x); }
981 for (
size_t i = 0; i < N; ++i) {
988 void voutput(
const bitvec<N>& x,
size_t i0)
const {
989 for (
size_t i = 0; i < N; ++i) {
990 output(x[i], i + i0);
995 void vassert0(
const bitvec<N>& x)
const {
996 for (
size_t i = 0; i < N; ++i) {
1003 for (
size_t i = 0; i < N; ++i) {
1004 (void)assert_eq(&(*x)[i], y[i]);
1009 void vassert_eq(
const bitvec<N>& x, uint64_t y)
const {
1010 auto v = vbit<N>(y);
1015 void vassert_is_bit(
const bitvec<N>& a)
const {
1016 for (
size_t i = 0; i < N; ++i) {
1017 (void)assert_is_bit(a[i]);
1025 if (a->c1 == zero()) {
1026 return rebase(zero(), a->c0, b);
1027 }
else if (b.c1 == zero()) {
1028 return mulv(&b, *a);
1035 EltW x = axy(mulf(a->c1, b.c1), &a->x, b.x);
1036 x = axpy(&x, mulf(a->c0, b.c1), b.x);
1037 x = axpy(&x, mulf(a->c1, b.c0), a->x);
1038 x = apy(x, mulf(a->c0, b.c0));
1044 if (a.c1 == zero()) {
1045 return BitW(addf(a.c0, b.c0), b.c1, b.x);
1046 }
else if (b.c1 == zero()) {
1049 EltW x = ax(a.c1, a.x);
1050 auto axb = ax(b.c1, b.x);
1052 x = apy(x, addf(a.c0, b.c0));
1057 BitW lxor_aux(
const BitW& a,
const BitW& b, PrimeFieldTypeTag tt)
const {
1060 Elt mtwo = f_.negf(f_.two());
1061 Elt half = f_.half();
1062 Elt mhalf = f_.negf(half);
1064 BitW a1 = rebase(one(), mtwo, a);
1065 BitW b1 = rebase(one(), mtwo, b);
1066 BitW p = mulv(&a1, b1);
1067 return rebase(half, mhalf, p);
1069 BitW lxor_aux(
const BitW& a,
const BitW& b, BinaryFieldTypeTag tt)
const {
1074 size_t pack(uint64_t mask,
size_t n,
BitW a[])
const {
1076 for (
size_t i = 0; i < n; ++i) {
1093 auto g0p1 = land(&g0, *p1);
1094 *g1 = lor_exclusive(g1, g0p1);
1095 *p1 = land(&p0, *p1);
1099 void ripple_scan(std::vector<BitW>& g, std::vector<BitW>& p,
size_t i0,
1101 for (
size_t i = i0 + 1; i < i1; ++i) {
1102 gp_reduce(g[i - 1], p[i - 1], &g[i], &p[i]);
1107 void sklansky_scan(std::vector<BitW>& g, std::vector<BitW>& p,
size_t i0,
1110 size_t im = i0 + (i1 - i0) / 2;
1111 sklansky_scan(g, p, i0, im);
1112 sklansky_scan(g, p, im, i1);
1113 for (
size_t i = im; i < i1; ++i) {
1114 gp_reduce(g[im - 1], p[im - 1], &g[i], &p[i]);
1123 BitW generic_gp_add(
size_t w,
BitW c[],
const BitW a[],
1125 void (Logic::*scan)(std::vector<BitW>& ,
1126 std::vector<BitW>& ,
1132 std::vector<BitW> g(w), p(w);
1133 for (
size_t i = 0; i < w; ++i) {
1134 g[i] = land(&a[i], b[i]);
1135 p[i] = lxor(&a[i], b[i]);
1138 (this->*scan)(g, p, 0, w);
1139 for (
size_t i = 1; i < w; ++i) {
1140 c[i] = lxor(&c[i], g[i - 1]);
1146 BitW generic_gp_sub(
size_t w,
BitW c[],
const BitW a[],
1148 void (Logic::*scan)(std::vector<BitW>& ,
1149 std::vector<BitW>& ,
1153 std::vector<BitW> t(w);
1154 for (
size_t j = 0; j < w; ++j) {
1157 BitW carry = generic_gp_add(w, c, t.data(), b, scan);
1158 for (
size_t j = 0; j < w; ++j) {
1169 void lt_reduce(
size_t i0,
size_t i1,
BitW* xeq,
BitW* xlt,
1170 const BitW a[],
const BitW b[])
const {
1172 BitW eq0, eq1, lt0, lt1;
1173 size_t im = i0 + (i1 - i0) / 2;
1174 lt_reduce(i0, im, &eq0, <0, a, b);
1175 lt_reduce(im, i1, &eq1, <1, a, b);
1176 *xeq = land(&eq1, eq0);
1177 auto lt0_and_eq1 = land(&eq1, lt0);
1178 *xlt = lor_exclusive(<1, lt0_and_eq1);
1180 auto axb = lxor(&a[i0], b[i0]);
1182 auto na = lnot(a[i0]);
1183 *xlt = land(&na, b[i0]);
1187 BitW parity(
size_t i0,
size_t i1,
const BitW a[])
const {
1190 }
else if (i1 == i0 + 1) {
1193 size_t im = i0 + (i1 - i0) / 2;
1194 auto lp = parity(i0, im, a);
1195 auto rp = parity(im, i1, a);
1196 return lxor(&lp, rp);
1200 BitW eq0(
size_t i0,
size_t i1,
const BitW a[])
const {
1203 }
else if (i1 == i0 + 1) {
1206 size_t im = i0 + (i1 - i0) / 2;
1207 auto le = eq0(i0, im, a);
1208 auto re = eq0(im, i1, a);
1209 return land(&le, re);
1213 BitW eq_reduce(
size_t i0,
size_t i1,
const BitW a[],
const BitW b[])
const {
1216 }
else if (i1 == i0 + 1) {
1217 return lnot(lxor(&a[i0], b[i0]));
1219 size_t im = i0 + (i1 - i0) / 2;
1220 auto le = eq_reduce(i0, im, a, b);
1221 auto re = eq_reduce(im, i1, a, b);
1222 return land(&le, re);