Longfellow ZK 0290cb32
Loading...
Searching...
No Matches
eqs.h
1// Copyright 2025 Google LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef PRIVACY_PROOFS_ZK_LIB_ARRAYS_EQS_H_
16#define PRIVACY_PROOFS_ZK_LIB_ARRAYS_EQS_H_
17
18#include <stddef.h>
19
20#include <vector>
21
22#include "algebra/blas.h"
23#include "arrays/affine.h"
24#include "arrays/dense.h"
25#include "util/panic.h"
26
27namespace proofs {
28
29// Stateful implementation of EQ[I, j] which, for fixed
30// I, holds an array indexed by j.
31template <class Field>
32class Eqs : public Dense<Field> {
33 using Elt = typename Field::Elt;
34 using Dense<Field>::v_;
35 using Dense<Field>::n0_;
36
37 public:
38 Eqs(size_t logn, corner_t n, const Elt I[/*logn*/], const Field& F)
39 : Dense<Field>(n, 1) {
40 filleq(&v_[0], logn, n, I, F);
41 }
42
43 corner_t n() const { return n0_; }
44
45 // Optimization for a special case: return a raw vector EQ[G0|.] + alpha *
46 // EQ[G1|.] Return std::vector<> because we don't need the full
47 // dense<> machinery.
48 static std::vector<Elt> raw_eq2(size_t logn, corner_t n, const Elt* G0,
49 const Elt* G1, const Elt& alpha,
50 const Field& F) {
51 std::vector<Elt> eq0(n);
52 std::vector<Elt> eq1(n);
53 filleq(&eq0[0], logn, n, G0, F);
54 filleq(&eq1[0], logn, n, G1, F);
55 Blas<Field>::axpy(n, &eq0[0], 1, alpha, &eq1[0], 1, F);
56 return eq0;
57 }
58
59 private:
60 // Return ceil(a / 2^{n}) for a != 0.
61 //
62 // Several ways exist to compute ceil(a/b) given a primitive that
63 // computes floor(a/b), such as the C++ unsigned division operator.
64 // The simplest one is floor((a+(b-1))/b), which potentally overflows.
65 // Another way is 1+floor((a-1)/b), which underflows for a==0 but
66 // otherwise does not overflow. More complicated ways exist that neither
67 // overflow nor underflow. Since the rest of the code assumes
68 // a!=0 anyway, we use the 1+floor((a-1)/b) version.
69 static corner_t ceilshr(corner_t a, size_t n) { return 1u + ((a - 1u) >> n); }
70
71 // Compute the array EQ[Q, i] for all 0<=i<n, for n <= 2^{logn}.
72 // (logn can otherwise be arbitrarily large.)
73 //
74 // Let Q be the array of field elements Q[0,logn), and let
75 // i[l] be the l-th bit of the binary representation of i, for
76 // 0 <= l < logn.
77 //
78 // We have
79 // EQ[Q, i] = (1 - Q[0]) * EQ[Q[1:], i[1:]] if i[0] = 0;
80 // EQ[Q, i] = Q[0] * EQ[Q[1:], i[1:]] if i[0] = 1.
81 //
82 // Thus, EQ{n, logn} can be expressed in terms of EQ{ceil(n/2), logn-1}
83 // of half the size.
84 static void filleq(Elt* eq, size_t logn, corner_t n, const Elt* Q,
85 const Field& F) {
86 check(n > 0, "n > 0");
87 eq[0] = F.one();
88 for (size_t l = logn; l-- > 0;) {
89 corner_t nl = ceilshr(n, l);
90 corner_t i = ceilshr(nl, 1);
91
92 // Special case for the first iteration of the i-loop
93 // below: don't compute eq[2*i+1] (post decrement) if it
94 // would overflow the array.
95 if (/*2*(i-1)+1 = */ 2 * i - 1 >= nl) {
96 i--;
97 Elt v = eq[i], qv = Q[l];
98 F.mul(qv, v);
99 eq[2 * i] = v;
100 F.sub(eq[2 * i], qv);
101 }
102 while (i-- > 0) {
103 // Assign
104 // eq[2*i] = (1-Q[l])*eq[i]
105 // eq[2*i+1] = Q[l]*eq[i]
106 // with one multiplication.
107 Elt v = eq[i], qv = Q[l];
108 F.mul(qv, v);
109 eq[2 * i] = v;
110 F.sub(eq[2 * i], qv);
111 eq[2 * i + 1] = qv;
112 }
113 }
114 }
115};
116} // namespace proofs
117
118#endif // PRIVACY_PROOFS_ZK_LIB_ARRAYS_EQS_H_
Definition gf2_128.h:63