49 DEFINE_STRONG_INT_TYPE(quad_corner_t, uint32_t);
56 bool operator==(
const corner& y)
const {
58 morton::eq(
size_t(h[0]),
size_t(h[1]),
size_t(y.h[0]),
63 bool eqndx(
const corner& y)
const {
64 return (g == y.g && h[0] == y.h[0] && h[1] == y.h[1]);
68 quad_corner_t h0 = h[0], h1 = h[1];
69 h[0] = std::min<quad_corner_t>(h0, h1);
70 h[1] = std::max<quad_corner_t>(h0, h1);
73 static bool compare(
const corner& x,
const corner& y,
const Field& F) {
74 if (morton::lt(
size_t(x.h[0]),
size_t(x.h[1]),
size_t(y.h[0]),
77 }
else if (morton::eq(
size_t(x.h[0]),
size_t(x.h[1]),
size_t(y.h[0]),
79 if (x.g < y.g)
return true;
80 if (x.g > y.g)
return false;
81 return elt_less_than(x.v, y.v, F);
88 using index_t = size_t;
90 std::vector<corner> c_;
92 bool operator==(
const Quad& y)
const {
94 std::equal(c_.begin(), c_.end(), y.c_.begin(), y.c_.end());
100 Quad(
const Quad& y) =
delete;
101 Quad(
const Quad&& y) =
delete;
102 Quad operator=(
const Quad& y) =
delete;
104 std::unique_ptr<Quad> clone()
const {
105 auto s = std::make_unique<Quad>(n_);
106 for (index_t i = 0; i < n_; ++i) {
112 void bind_h(
const Elt& r,
size_t hand,
const Field& F) {
113 index_t rd = 0, wr = 0;
116 cc.g = quad_corner_t(0);
117 cc.h[hand] = c_[rd].h[hand] >> 1;
118 cc.h[1 - hand] = c_[rd].h[1 - hand];
122 c_[rd].h[1 - hand] == c_[rd1].h[1 - hand] &&
123 (c_[rd].h[hand] >> 1) == (c_[rd1].h[hand] >> 1) &&
124 c_[rd1].h[hand] == c_[rd].h[hand] + quad_corner_t(1)) {
126 cc.v = affine_interpolation(r, c_[rd].v, c_[rd1].v, F);
130 if ((c_[rd].h[hand] & quad_corner_t(1)) == quad_corner_t(0)) {
131 cc.v = affine_interpolation_nz_z(r, c_[rd].v, F);
133 cc.v = affine_interpolation_z_nz(r, c_[rd].v, F);
147 void bind_g(
size_t logv,
const Elt* G0,
const Elt* G1,
const Elt& alpha,
148 const Elt& beta,
const Field& F) {
149 size_t nv = size_t(1) << logv;
150 auto dot = Eqs<Field>::raw_eq2(logv, nv, G0, G1, alpha, F);
151 for (index_t i = 0; i < n_; ++i) {
152 if (c_[i].v == F.zero()) {
155 F.mul(c_[i].v, dot[corner_t(c_[i].g)]);
156 c_[i].g = quad_corner_t(0);
166 size_t logv,
const Elt G0[],
const Elt G1[],
167 const Elt& alpha,
const Elt& beta,
169 size_t logw,
const Elt H0[],
const Elt H1[],
171 const Field& F)
const {
172 size_t nv = size_t(1) << logv;
173 auto eqg = Eqs<Field>::raw_eq2(logv, nv, G0, G1, alpha, F);
175 size_t nw = size_t(1) << logw;
176 Eqs<Field> eqh0(logw, nw, H0, F);
177 Eqs<Field> eqh1(logw, nw, H1, F);
181 for (index_t i = 0; i < n_; ++i) {
186 F.mul(q, eqg[corner_t(c_[i].g)]);
187 F.mul(q, eqh0.at(corner_t(c_[i].h[0])));
188 F.mul(q, eqh1.at(corner_t(c_[i].h[1])));
195 check(n_ == 1,
"n_ == 1");
196 check(c_[0].g == quad_corner_t(0),
"c_[0].g == 0");
197 check(c_[0].h[0] == quad_corner_t(0),
"c_[0].h[0] == 0");
198 check(c_[0].h[1] == quad_corner_t(0),
"c_[0].h[1] == 0");
202 void canonicalize(
const Field& F) {
203 for (index_t i = 0; i < n_; ++i) {
204 c_[i].canonicalize();
206 std::sort(c_.begin(), c_.end(), [&F](
const corner& x,
const corner& y) {
207 return corner::compare(x, y, F);
213 void coalesce(
const Field& F) {
219 for (index_t rd = 1; rd < n_; ++rd) {
220 if (c_[rd].eqndx(c_[wr - 1])) {
221 F.add(c_[wr - 1].v, c_[rd].v);