101 __host__ __device__
int Gen(
102 Cw cws[], cuda::std::array<int4, 4> &cs, int4 &ocw, cuda::std::span<const int4, 2> s0s, In a, int4 b_buf) {
104 s0 = util::SetLsb(s0,
false);
106 s1 = util::SetLsb(s1,
false);
109 b_buf = util::SetLsb(b_buf,
false);
111 for (
int i = 0; i < in_bits; ++i) {
112 auto [s0l, s0r] = prg.Gen(s0);
113 auto [s1l, s1r] = prg.Gen(s1);
115 bool t0l = util::GetLsb(s0l);
116 s0l = util::SetLsb(s0l,
false);
117 bool t0r = util::GetLsb(s0r);
118 s0r = util::SetLsb(s0r,
false);
119 bool t1l = util::GetLsb(s1l);
120 s1l = util::SetLsb(s1l,
false);
121 bool t1r = util::GetLsb(s1r);
122 s1r = util::SetLsb(s1r,
false);
124 bool a_bit = (a >> (in_bits - 1 - i)) & 1;
127 if (!a_bit) s_cw = util::Xor(s0r, s1r);
128 else s_cw = util::Xor(s0l, s1l);
130 bool tl_cw = t0l ^ t1l ^ a_bit ^ 1;
131 bool tr_cw = t0r ^ t1r ^ a_bit;
135 if (t0) s0 = util::Xor(s0, s_cw);
137 if (t1) s1 = util::Xor(s1, s_cw);
139 if (t0) t0 = t0l ^ tl_cw;
141 if (t1) t1 = t1l ^ tl_cw;
145 if (t0) s0 = util::Xor(s0, s_cw);
147 if (t1) s1 = util::Xor(s1, s_cw);
149 if (t0) t0 = t0r ^ tr_cw;
151 if (t1) t1 = t1r ^ tr_cw;
155 s_cw = util::SetLsb(s_cw, tl_cw);
160 int4 *cw_slot =
reinterpret_cast<int4 *
>(&cws[i]);
162 cw_slot[1] = make_int4(tr_cw, 0, 0, 0);
166 int4 a_buf = util::Pack(a);
168 auto pi_tilde_0 = xor_hash.Hash(cuda::std::tuple<int4, const int4>{a_buf, s0});
169 auto pi_tilde_1 = xor_hash.Hash(cuda::std::tuple<int4, const int4>{a_buf, s1});
170 cs = util::Xor(cuda::std::span<const int4, 4>(pi_tilde_0), cuda::std::span<const int4, 4>(pi_tilde_1));
173 if (t0 == t1)
return 1;
176 auto v_cw = Group::From(b_buf) + (-Group::From(s0)) + Group::From(s1);
177 if (t1) v_cw = -v_cw;
195 __host__ __device__ cuda::std::array<int4, 4>
Eval(
196 bool b, int4 s0, cuda::std::span<const Cw> cws, cuda::std::span<const int4, 4> cs, int4 ocw, In x, int4 &y) {
198 s = util::SetLsb(s,
false);
201 for (
int i = 0; i < in_bits; ++i) {
204 bool tl_cw = util::GetLsb(s_cw);
205 s_cw = util::SetLsb(s_cw,
false);
208 auto [sl, sr] = prg.Gen(s);
210 bool tl = util::GetLsb(sl);
211 sl = util::SetLsb(sl,
false);
212 bool tr = util::GetLsb(sr);
213 sr = util::SetLsb(sr,
false);
216 sl = util::Xor(sl, s_cw);
217 sr = util::Xor(sr, s_cw);
222 bool x_bit = (x >> (in_bits - 1 - i)) & 1;
234 auto g = Group::From(s);
235 assert((ocw.w & 1) == 0);
236 if (t) g = g + Group::From(ocw);
241 int4 x_buf = util::Pack(x);
243 auto pi_tilde = xor_hash.Hash(cuda::std::tuple<int4, const int4>{x_buf, s});
245 return util::Xor(cuda::std::span<const int4, 4>(pi_tilde), cuda::std::span<const int4, 4>(cs));
259 void Prove(cuda::std::span<
const cuda::std::array<int4, 4>> pi_tildes, cuda::std::span<const int4, 4> cs,
260 cuda::std::array<int4, 4> &pi) {
261 pi = {cs[0], cs[1], cs[2], cs[3]};
262 for (
size_t i = 0; i < pi_tildes.size(); ++i) {
263 cuda::std::array<int4, 4> h_input =
264 util::Xor(cuda::std::span<const int4, 4>(pi), cuda::std::span<const int4, 4>(pi_tildes[i]));
265 auto h_out = hash.Hash(cuda::std::span<const int4, 4>(h_input));
266 pi[0] = util::Xor(pi[0], h_out[0]);
267 pi[1] = util::Xor(pi[1], h_out[1]);
302 void EvalAll(
bool b, int4 s0, cuda::std::span<const Cw> cws, cuda::std::span<const int4, 4> cs, int4 ocw,
303 cuda::std::span<int4> ys, cuda::std::array<int4, 4> &pi) {
306 st = util::SetLsb(st, t);
308 assert(in_bits <
sizeof(
size_t) * 8);
310 size_t r = 1ULL << in_bits;
313 int par_depth_ = util::ResolveParDepth(par_depth);
318 EvalTree(st, cws, ys, l, r, i, par_depth_);
321 pi = {cs[0], cs[1], cs[2], cs[3]};
322 size_t n = 1ULL << in_bits;
323 assert((ocw.w & 1) == 0);
324 auto ocw_group = Group::From(ocw);
325 for (
size_t j = 0; j < n; ++j) {
327 bool tj = util::GetLsb(sj);
328 sj = util::SetLsb(sj,
false);
331 auto g = Group::From(sj);
332 if (tj) g = g + ocw_group;
337 int4 x_buf = util::Pack(
static_cast<In
>(j));
339 auto pi_tilde = xor_hash.Hash(cuda::std::tuple<int4, const int4>{x_buf, sj});
341 pi_tilde = util::Xor(cuda::std::span<const int4, 4>(pi_tilde), cuda::std::span<const int4, 4>(cs));
344 cuda::std::array<int4, 4> h_input =
345 util::Xor(cuda::std::span<const int4, 4>(pi), cuda::std::span<const int4, 4>(pi_tilde));
346 auto h_out = hash.Hash(cuda::std::span<const int4, 4>(h_input));
347 pi[0] = util::Xor(pi[0], h_out[0]);
348 pi[1] = util::Xor(pi[1], h_out[1]);
354 int4 st, cuda::std::span<const Cw> cws, cuda::std::span<int4> ys,
size_t l,
size_t r,
int i,
int par_depth_) {
394 EvalTree(stl, cws, ys, l, mid, i + 1, par_depth_);
396 EvalTree(str, cws, ys, mid, r, i + 1, par_depth_);
399 EvalTree(stl, cws, ys, l, mid, i + 1, par_depth_);
400 EvalTree(str, cws, ys, mid, r, i + 1, par_depth_);