forked from data61/MP-SPDZ
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgf2n.h
274 lines (207 loc) · 7.1 KB
/
gf2n.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#ifndef _gf2n
#define _gf2n
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
#include "Tools/random.h"
#include "Math/field_types.h"
#include "Math/bigint.h"
#include "Math/ValueInterface.h"
class gf2n_short;
class P2Data;
class Bit;
class int128;
template<class T> class Square;
typedef Square<gf2n_short> gf2n_short_square;
void expand_byte(gf2n_short& a,int b);
void collapse_byte(int& b,const gf2n_short& a);
/* This interface compatible with the gfp interface
* which then allows us to template the Share
* data type.
*/
/*
Arithmetic in Gf_{2^n} with n<64
*/
template<class U>
class gf2n_ : public ValueInterface
{
protected:
friend class gf2n_long;
U a;
static int n, nterms;
static int t[4], l[4];
static U mask;
static U uppermask, lowermask;
static bool useC;
static octet mult_table[256][256];
static void init_tables();
static void init_multiplication();
template<class T>
T invert(T a) const;
public:
typedef U internal_type;
typedef gf2n_ Scalar;
static const int N_BYTES = sizeof(a);
static const int MAX_N_BITS = 8 * N_BYTES;
static void init_field(int nn = 0);
static void init_default(int, bool = false) { init_field(); }
static void init_minimum(int lower);
static void reset() { n = 0; }
static int degree() { return n; }
static int get_nterms() { return nterms; }
static int get_t(int i) { return (i < 3) ? t[i + 1] : -1; }
static DataFieldType field_type() { return DATA_GF2N; }
static char type_char() { return '2'; }
static string type_short() { return "2"; }
static string type_string() { return "gf2n_"; }
static void specification(octetStream& os);
static int size() { return sizeof(a); }
static int size_in_bits() { return sizeof(a) * 8; }
static int length() { return n == 0 ? MAX_N_BITS : n; }
static bool allows(Dtype type) { (void) type; return true; }
static string options();
static const true_type invertible;
static const true_type characteristic_two;
static gf2n_ Mul(gf2n_ a, gf2n_ b) { return a * b; }
U get() const { return a; }
const void* get_ptr() const { return &a; }
void assign_zero() { a=0; }
void assign_one() { a=1; }
void assign_x() { a=2; }
void assign(const void* aa) { memcpy(&a, aa, sizeof(a)); }
void normalize() { a &= mask; }
/* Assign x[0..2*nwords] to a and reduce it... */
void reduce(U xh, U xl);
int get_bit(int i) const
{ return ((a>>i)&1) != 0; }
void set_bit(int i,unsigned int b)
{ if (b==1)
{ a |= (1UL<<i); }
else
{ a &= ~(1UL<<i); }
}
gf2n_() : a(0) {}
gf2n_(U a) : a(a & mask) {}
gf2n_(long a) : gf2n_(U(a)) {}
gf2n_(int a) : gf2n_(U(unsigned(a))) {}
gf2n_(long long a) : gf2n_(U(a)) {}
template<class T>
gf2n_(IntBase<T> a) : a(a.get()) {}
int is_zero() const { return (a==0); }
int is_one() const { return (a==1); }
bool operator==(const gf2n_& y) const { return a==y.a; }
bool operator!=(const gf2n_& y) const { return a!=y.a; }
// x+y
void add(const gf2n_& x,const gf2n_& y)
{ a=x.a^y.a; }
void add(octet* x)
{ a^=*(U*)(x); }
void add(octetStream& os)
{ add(os.consume(size())); }
void sub(const gf2n_& x,const gf2n_& y)
{ a=x.a^y.a; }
// = x * y
gf2n_& mul(const gf2n_& x,const gf2n_& y);
gf2n_ lazy_add(const gf2n_& x) const { return *this + x; }
gf2n_ lazy_mul(const gf2n_& x) const { return *this * x; }
gf2n_ operator+(const gf2n_& x) const { gf2n_ res; res.add(*this, x); return res; }
gf2n_ operator*(const gf2n_& x) const { gf2n_ res; res.mul(*this, x); return res; }
gf2n_& operator+=(const gf2n_& x) { add(*this, x); return *this; }
gf2n_& operator*=(const gf2n_& x) { mul(*this, x); return *this; }
gf2n_ operator-(const gf2n_& x) const { gf2n_ res; res.add(*this, x); return res; }
gf2n_& operator-=(const gf2n_& x) { sub(*this, x); return *this; }
gf2n_ operator/(const gf2n_& x) const { return *this * x.invert(); }
gf2n_ operator*(const Bit& x) const;
gf2n_ operator*(int x) const { return *this * gf2n_(x); }
gf2n_ invert() const;
gf2n_ operator-() const { return *this; }
void negate() { return; }
/* Bitwise Ops */
gf2n_ operator&(const gf2n_& x) const { return a & x.a; }
gf2n_ operator^(const gf2n_& x) const { return a ^ x.a; }
gf2n_ operator|(const gf2n_& x) const { return a | x.a; }
gf2n_ operator~() const { return ~a; }
gf2n_ operator<<(int i) const;
gf2n_ operator>>(int i) const;
gf2n_& operator&=(const gf2n_& x) { *this = *this & x; return *this; }
gf2n_& operator^=(const gf2n_& x) { *this = *this ^ x; return *this; }
gf2n_& operator>>=(int i) { *this = *this >> i; return *this; }
gf2n_& operator<<=(int i) { *this = *this << i; return *this; }
/* Crap RNG */
void randomize(PRNG& G, int n = -1);
// compatibility with gfp
void almost_randomize(PRNG& G) { randomize(G); }
void force_to_bit() { a &= 1; }
void output(ostream& s,bool human) const;
void input(istream& s,bool human);
friend ostream& operator<<(ostream& s,const gf2n_& x)
{
x.output(s, true);
return s;
}
friend istream& operator>>(istream& s,gf2n_& x)
{
word tmp;
s >> hex >> tmp >> dec;
x = tmp;
return s;
}
// Pack and unpack in native format
// i.e. Dont care about conversion to human readable form
void pack(octetStream& o, int n = -1) const
{ (void) n; o.append((octet*) &a,sizeof(U)); }
void unpack(octetStream& o, int n = -1)
{ (void) n; o.consume((octet*) &a,sizeof(U)); }
};
class gf2n_short : public gf2n_<word>
{
typedef gf2n_<word> super;
public:
typedef gf2n_short value_type;
typedef gf2n_short next;
typedef ::Square<gf2n_short> Square;
typedef P2Data FD;
typedef gf2n_short Scalar;
static const int DEFAULT_LENGTH = 40;
static int length() { return n == 0 ? DEFAULT_LENGTH : n; }
static int default_degree() { return DEFAULT_LENGTH; }
static void init_field(int nn = 0);
static gf2n_short cut(int128 x);
gf2n_short() {}
template<class T>
gf2n_short(const T& other) : super(other) {}
gf2n_short(const int128& a);
word get_word() const { return a; }
};
#include "gf2nlong.h"
class gf2n_long;
#ifdef USE_GF2N_LONG
typedef gf2n_long gf2n;
#else
typedef gf2n_short gf2n;
#endif
template<class U>
const true_type gf2n_<U>::characteristic_two;
template<class U>
const true_type gf2n_<U>::invertible;
template<class U>
int gf2n_<U>::n = 0;
template<class U>
U gf2n_<U>::mask;
template<class U>
int gf2n_<U>::nterms;
template<class U>
int gf2n_<U>::t[4];
template<class U>
U gf2n_<U>::uppermask;
template<class U>
U gf2n_<U>::lowermask;
template<class U>
octet gf2n_<U>::mult_table[256][256];
template<>
inline gf2n_<octet>& gf2n_<octet>::mul(const gf2n_<octet>& x, const gf2n_<octet>& y)
{
return *this = mult_table[octet(x.a)][octet(y.a)];
}
#endif