54 bool eqndx(
const corner& y)
const {
55 return (p2 == y.p2 && p1 == y.p1 && p0 == y.p0);
57 bool operator==(
const corner& y)
const {
return eqndx(y) && v == y.v; }
58 bool operator!=(
const corner& y)
const {
return !operator==(y); }
60 static bool compare(
const corner& x,
const corner& y,
const Field& F) {
61 if (x.p2 < y.p2)
return true;
62 if (x.p2 > y.p2)
return false;
63 if (x.p1 < y.p1)
return true;
64 if (x.p1 > y.p1)
return false;
65 if (x.p0 < y.p0)
return true;
66 if (x.p0 > y.p0)
return false;
67 return elt_less_than(x.v, y.v, F);
72 using index_t = size_t;
75 std::vector<corner> c_;
77 explicit Sparse(index_t n) : n_(n), c_(n) {}
86 std::unique_ptr<Sparse> clone_testing_only()
const {
87 auto s = std::make_unique<Sparse>(n_);
88 for (
index_t i = 0; i < n_; ++i) {
94 T2 t2_at_corners(index_t* newi, index_t i,
const Field& F)
const {
98 c_[i].p2 == c_[i + 1].p2 &&
99 c_[i].p1 == c_[i + 1].p1 &&
100 (c_[i].p0 >> 1) == (c_[i + 1].p0 >> 1) &&
101 c_[i + 1].p0 == c_[i].p0 + 1) {
104 return T2{c_[i].v, c_[i + 1].v};
108 if ((c_[i].p0 & 1) == 0) {
109 return T2{c_[i].v, F.zero()};
111 return T2{F.zero(), c_[i].v};
120 void bind(
const Elt& r,
const Field& F) {
121 index_t rd = 0, wr = 0;
124 T2 f = t2_at_corners(&newrd, rd, F);
125 c_[wr] =
corner{.p0 = c_[rd].p0 >> 1,
128 .v = affine_interpolation(r, f.t_[0], f.t_[1], F)};
137 void bind_all(
size_t logv,
const Elt r[],
const Field& F) {
138 for (
size_t v = 0; v < logv; ++v) {
147 size_t lost_bits = 0;
148 for (index_t i = 0; i < n_; ++i) {
149 lost_bits |= c_[i].p0;
150 c_[i] =
corner{.p0 = c_[i].p1, .p1 = c_[i].p2, .p2 = 0, .v = c_[i].v};
152 check(lost_bits == 0,
"lost_bits == 0");
158 check(n_ == 1,
"n_ == 1");
159 check(c_[0].p0 == 0,
"c_[0].p0_ == 0");
160 check(c_[0].p1 == 0,
"c_[0].p1_ == 0");
161 check(c_[0].p2 == 0,
"c_[0].p2_ == 0");
165 void canonicalize(
const Field& F) {
166 std::sort(c_.begin(), c_.end(), [&F](
const corner& x,
const corner& y) {
167 return corner::compare(x, y, F);
173 void coalesce(
const Field& F) {
179 for (index_t rd = 1; rd < n_; ++rd) {
180 if (c_[rd].eqndx(c_[wr - 1])) {
181 F.add(c_[wr - 1].v, c_[rd].v);