-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhqs.c
282 lines (250 loc) · 7 KB
/
hqs.c
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
275
276
277
278
279
280
281
#include "hqs.h"
#include <stdlib.h>
#include <stdio.h>
/**
* hqs
* Create homogeneous quadratic system object from a list of
* of quadratic forms and the system's dimensions.
*/
hqsystem hqs( gfpmatrix* qfs, unsigned int n, unsigned int m )
{
hqsystem hqs;
hqs.quadratic_forms = qfs;
hqs.n = n;
hqs.m = m;
return hqs;
}
/**
* hqs_init
* Creates a homogeneous quadratic system object from the given
* dimensions and allocates memory for it. Don't forget to call
* hqs_destroy afterwards.
*/
hqsystem hqs_init( unsigned int n, unsigned int m )
{
unsigned int i;
hqsystem hqs;
hqs.n = n;
hqs.m = m;
hqs.quadratic_forms = malloc(sizeof(gfpmatrix) * m);
for( i = 0 ; i < m ; ++i )
{
hqs.quadratic_forms[i] = gfpm_init(n,n);
}
return hqs;
}
/**
* hqs_destroy
* Deallocates space allocated for a homogeneous quadratic system
* object.
*/
int hqs_destroy( hqsystem sys )
{
unsigned int i;
for( i = 0 ; i < sys.m ; ++i )
{
gfpm_destroy(sys.quadratic_forms[i]);
}
free(sys.quadratic_forms);
return 1;
}
/**
* hqs_copy
* Copies the data associated to a homogeneous quadratic system. Does
* not allocate the space necessary -- you have to do that yourself.
* (And consequently you have the option of keeping everything in the
* stack.)
*/
int hqs_copy( hqsystem dest, hqsystem source )
{
unsigned int i;
#ifdef DEBUG
if( dest.n != source.n || dest.m != source.m )
{
printf("in hqs_copy: cannot copy hqs object because dimensions do not match! dest: %i -> %i vs. source: %i -> %i\n", dest.n, dest.m, source.n, source.m);
return 0;
}
#endif
for( i = 0 ; i < dest.m ; ++i )
{
gfpm_copy(dest.quadratic_forms[i], source.quadratic_forms[i]);
}
return 1;
}
/**
* hqs_clone
* Copy one homogeneous quadratic system to a new one. Remember to
* destroy it when scope ends!
* @params
* * source : the homogeneous quadratic system to copy
* @return
* * dest : a new homogeneous quadratic system identical to source
*/
hqsystem hqs_clone( hqsystem source )
{
hqsystem dest;
dest = hqs_init(source.n, source.m);
hqs_copy(dest, source);
return dest;
}
/**
* hqs_random
* Given an empty homogeneous quadratic system, assign random values
* to its coefficients.
* The amount of randomness required is m*n*n bytes.
* @params
* * sys : a homogeneous quadratic system; the dimensions of this
* system will be retained; the coefficients (entries of the
* matrices) will be forgotten
* * randomness : a pointer to a large enough string of random bytes
* "large enough" means n*n*m*(1+GF_NUMBYTES)
* @result
* * sys will contain random coefficients
* @return
* * 1 if success, 0 otherwise
*/
int hqs_random( hqsystem sys, unsigned char * randomness )
{
unsigned int i, j, k, l;
l = 0;
for( k = 0 ; k < sys.m ; ++k )
{
for( i = 0 ; i < sys.n ; ++i )
{
for( j = 0 ; j < sys.n ; ++j )
{
gfp_random(&sys.quadratic_forms[k].data[i*sys.n + j], &randomness[l]);
l = l + (GFP_NUMBITS + sizeof(unsigned long int) * 8 - 1) / (sizeof(unsigned long int) * 8);
}
}
}
return 1;
}
/**
* hqs_compose_output
* Compose a homogeneous quadratic system on the left with a
* linear transform.
* @params
* * T : a gfpmatrix object of dimensions mxm
* * F : an hqsystem object of dimensions n -> m
* @promise
* * T is square
* * has the same number of columns as the number of quadratic
* forms in F
* @result
* new.F = T * old.F
* @return
* 1 if success, 0 otherwise
*/
int hqs_compose_output( gfpmatrix T, hqsystem F )
{
unsigned int i, j;
/* declare helper variables */
hqsystem P;
gfpmatrix temp;
#ifdef DEBUG
if( T.width != F.m )
{
printf("in hqs_compose_output: cannot compose homogeneous quadratic system with linear transform on output side because dimension mismatch! T: %ix%i vs F: %i -> %i\n", T.height, T.width, F.n, F.m);
return 0;
}
#endif
/* init helper variables */
P = hqs_init(F.n, T.height);
temp = gfpm_init(F.n, F.n);
/* perform multiplication */
for( i = 0 ; i < T.height ; ++i )
{
gfpm_zeros(P.quadratic_forms[i]);
for( j = 0 ; j < T.width ; ++j )
{
gfpm_multiply_constant(temp, F.quadratic_forms[j], T.data[i*T.width + j]);
gfpm_add(P.quadratic_forms[i], P.quadratic_forms[i], temp);
}
}
/* copy to argument */
hqs_copy(F, P);
/* destroy helper variables */
hqs_destroy(P);
gfpm_destroy(temp);
return 1;
}
/**
* hqs_compose_input
* Compose a homogeneous quadratic system with a linear transform on
* the input variables.
* @params
* * F : homogeneous quadratic system object to which the input
* transform is to be applied
* * S : matrix object that represents the linear transform
* @promise
* * F.n = S.width
* * S.width = S.height
* @result
* * new.F = old.F o S
* @return
* * 1 if success, 0 otherwise
*/
int hqs_compose_input( hqsystem F, gfpmatrix S )
{
unsigned int i;
/* declare helper variables */
gfpmatrix temp;
/* debug stuff */
#ifdef DEBUG
if( F.n != S.height || S.height != S.width )
{
printf("hqs_compose_input: cannot compose homogeneous quadratic system with linear transform on input side because of dimension mismatch! F : %i -> %i vs. S : %ix%i\n", F.n, F.m, S.height, S.width);
return 0;
}
#endif
/* init helper variables */
temp = gfpm_init(S.height, S.height);
/* perform multiplication */
for( i = 0 ; i < F.m ; ++i )
{
gfpm_transpose_multiply(&temp, S, F.quadratic_forms[i]);
gfpm_multiply(&F.quadratic_forms[i], temp, S);
}
/* destroy helper variables */
gfpm_destroy(temp);
return 1;
}
/**
* hqs_eval
* Evaluate a homogeneous quadratic system in a vector or, by
* treating the columns as a list of vectors, as a matrix.
*/
int hqs_eval( gfpmatrix y, hqsystem sys, gfpmatrix x )
{
unsigned int i, j, k;
gfpmatrix vector, transposed_vector, temp, e;
#ifdef DEBUG
if( y.height != sys.m || sys.n != x.height || y.width != x.width )
{
printf("hqs_eval: cannot evaluate quadratic system because of dimension mismatch! F: %i -> %i vs. in: %ix%i, out: %ix%i\n", sys.n, sys.m, x.height, x.width, y.height, y.width);
return 0;
}
#endif
vector = gfpm_init(sys.n, 1);
transposed_vector = gfpm(1, sys.n, vector.data);
temp = gfpm_init(sys.n, 1);
e = gfpm_init(1, 1);
for( j = 0 ; j < x.width ; ++j )
{
gfpm_slice(vector, x, 0, j);
for( i = 0 ; i < x.height ; ++i )
{
for( k = 0 ; k < sys.m ; ++k )
{
gfpm_multiply(&temp, sys.quadratic_forms[k], vector);
gfpm_multiply(&e, transposed_vector, temp);
gfp_copy(&y.data[k*y.width + j], e.data[0]);
}
}
}
gfpm_destroy(e);
gfpm_destroy(vector);
gfpm_destroy(temp);
return 1;
}