BitPunch McEliece  v0.0.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gf2x.c
Go to the documentation of this file.
1 /*
2 This file is part of BitPunch
3 Copyright (C) 2013-2015 Frantisek Uhrecky <frantisek.uhrecky[what here]gmail.com>
4 Copyright (C) 2013-2014 Andrej Gulyas <andrej.guly[what here]gmail.com>
5 Copyright (C) 2013-2014 Marek Klein <kleinmrk[what here]gmail.com>
6 Copyright (C) 2013-2014 Filip Machovec <filipmachovec[what here]yahoo.com>
7 Copyright (C) 2013-2014 Jozef Kudlac <jozef[what here]kudlac.sk>
8 
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <bitpunch/debugio.h>
25 #include <bitpunch/prng/prng.h>
26 
27 #include "gf2x.h"
28 #include "int.h"
29 #include "mathctx.h"
30 
31 #ifdef BPU_CONF_PRINT
32 /* ==================================== Print functions ==================================== */
34  uint32_t i;
35  uint32_t j;
36  fprintf(stderr, "Matrix size: %dx%d\n", in->k, in->n);
37 
38  for(i = 0; i < in->k; i++) {
39  fprintf(stderr, "%3d: ",i);
40  for(j = 0; j < in->n; j++) {
41  fprintf(stderr, "%x ", in->elements[i][j]);//BPU_printBinary(in->elements[i][j], 4);
42  }
43  fprintf(stderr, "\n");
44  }
45 }
46 
47 void BPU_printGf2xPoly(const BPU_T_GF2_16x_Poly *p, const BPU_T_Math_Ctx *math_ctx) {
48  int i;
49 
50  fprintf(stderr, "Poly (deg = %d): ", p->deg);
51 
52  if (p->deg == -1) {
53  fprintf(stderr, "0\n");
54 
55  return;
56  }
57  for (i = p->deg; i >= 0; i--) {
58  if(p->coef[i] == 0)
59  continue;
60  if (i != p->deg) {
61  fprintf(stderr, "+ ");
62  }
63  fprintf(stderr, "alpha^(%d).x^%d ", math_ctx->log_table[p->coef[i]], i);
64  }
65  fprintf(stderr, "\n");
66 }
67 
69  int i;
70  for(i = 0; i < v->len; i++) {
71  fprintf(stderr, "%x ", v->elements[i]);
72  }
73  fprintf(stderr, "\n");
74 }
75 /* ------------------------------------ Print functions ------------------------------------ */
76 #endif
77 
79  BPU_T_GF2_16x tmp, tmp2;
80 
81  if (a == 0) {
82  return 0;
83  }
84  // (a/x * b)
85  tmp = BPU_gf2xMulMod(a >> 1, b, mod);
86 
87  // tmp * x
88  tmp = (tmp << 1);
89 
90  // tmp + mod
91  tmp2 = tmp ^ mod;
92 
93  if (tmp2 < tmp) {
94  tmp = tmp2;
95  }
96  if ((a & 1) == 1) {
97  tmp ^= b;
98  }
99  return tmp;
100 }
101 
102 //BPU_T_GF2_16x BPU_gf2xMulModT(const BPU_T_GF2_16x a, const BPU_T_GF2_16x b, const BPU_T_Math_Ctx *math_ctx) {
103 // if (a == 0 || b == 0) {
104 // return 0;
105 // }
106 // // look into tables
107 // return math_ctx->exp_table[(math_ctx->log_table[a] + math_ctx->log_table[b]) % math_ctx->ord];
108 //}
109 
111  if (e == 0) {
112  return 1;
113  }
114  if (a == 0) {
115  return 0;
116  }
117  // look into log table to find i (b^i) = a
118  e = e * math_ctx->log_table[a];
119  e = e % math_ctx->ord;
120 
121  if (e < 0) {
122  e = e + math_ctx->ord;
123  }
124  // look into exp table
125  return math_ctx->exp_table[e];
126 }
127 
128 /*** PZ: speedup critical instructions ***/
130  uint32_t i, j, k;
131  int loga;
132 
133  if (a->n != b->k || x->k != a->k || x->n != b->n){
134  BPU_printError("Wrong mat dimension.");
135 
136  return -1;
137  }
138  BPU_gf2xMatNull(x);
139 
140  for (i = 0; i < a->k; i++) {
141  for (j = 0; j < b->n; j++) {
142  x->elements[i][j] = 0;
143  }
144  }
145 
146  for (i = 0; i < a->k; i++) {
147  for (k = 0; k < a->n; k++) {
148  if (a->elements[i][k] == 0)
149  continue;
150  loga = math_ctx->log_table[a->elements[i][k]];
151  for (j = 0; j < b->n; j++) {
152  if (b->elements[k][j] == 0)
153  continue;
154  x->elements[i][j] ^= math_ctx->exp_table[(loga + math_ctx->log_table[b->elements[k][j]]) % math_ctx->ord];
155  }
156  }
157  }
158  return 0;
159 }
160 
162  int16_t out_deg;
163  int i = 0;
164 
165  out_deg = a->deg > b->deg ? a->deg : b->deg;
166 
167  if (out->max_deg < out_deg) {
168  BPU_gf2xPolyResize(out, out_deg);
169  }
170  else {
171  BPU_gf2xPolyNull(out);
172  }
173  for (i = 0; i <= out_deg; i++) {
174  if (i <= a->deg) {
175  out->coef[i] ^= a->coef[i];
176  }
177  if (i <= b->deg) {
178  out->coef[i] ^= b->coef[i];
179  }
180  }
181  out->deg = BPU_gf2xPolyGetDeg(out);
182 }
183 
185  // a:b = q+r
186  BPU_T_GF2_16x_Poly *tmp;
187  BPU_T_GF2_16x leader;
188  BPU_T_GF2_16x_Poly *dividend;
189  const BPU_T_GF2_16x_Poly *divider = b;
190  int exponent;
191  int i;
192  int max_deg_q;
193 
194  BPU_gf2xPolyMalloc(&dividend, a->max_deg);
195  BPU_gf2xPolyCopy(dividend, a);
196 
197  max_deg_q = a->deg - b->deg;
198 
199  // check size of outputs
200  if (q->max_deg < max_deg_q) {
201  BPU_gf2xPolyResize(q, max_deg_q);
202  }
203  else {
204  BPU_gf2xPolyNull(q);
205  }
206  if (r->max_deg < (b->max_deg - 1)) {
207  BPU_gf2xPolyResize(r, b->max_deg - 1);
208  }
209  else {
210  BPU_gf2xPolyNull(r);
211  }
212  BPU_gf2xPolyMalloc(&tmp, a->max_deg);
213 
214  for (i = a->deg; i >= 0; i--) {
215  if (dividend->deg < divider->deg) {
216  BPU_gf2xPolyCopy(r, dividend);
217  break;
218  }
219  BPU_gf2xPolyNull(tmp);
220  leader = BPU_gf2xMulModT(dividend->coef[i], BPU_gf2xPowerModT(divider->coef[divider->deg], -1, math_ctx), math_ctx);
221  exponent = dividend->deg - divider->deg;
222  q->coef[exponent] = leader;
223 
224  if(q->deg == -1) {
225  q->deg = BPU_gf2xPolyGetDeg(q);
226  }
227  BPU_gf2xPolyMul(tmp, divider, q, math_ctx);
228 
229  BPU_gf2xPolyAdd(dividend, a, tmp);
230  }
231  BPU_gf2xPolyFree(&dividend);
232  BPU_gf2xPolyFree(&tmp);
233 }
234 
236  int i;
237  int j;
238  int max_deg = a->deg + b->deg;
239 
240  if (out->max_deg < max_deg) {
241  BPU_gf2xPolyResize(out, max_deg);
242  }
243  else {
244  BPU_gf2xPolyNull(out);
245  }
246 
247  for (i = a->deg; i >= 0; i--) {
248  for (j = b->deg; j >= 0; j--) {
249  out->coef[i+j] ^= BPU_gf2xMulModT(a->coef[i], b->coef[j], math_ctx);
250  }
251  }
252  out->deg = BPU_gf2xPolyGetDeg(out);
253 }
254 
256  BPU_T_GF2_16x_Poly *tmp;
257 
258  // if there is nothing to shift, return
259  if (a->deg == -1 || n <= 0) {
260  return;
261  }
262  BPU_gf2xPolyMalloc(&tmp, a->deg);
263  BPU_gf2xPolyCopy(tmp, a);
264  BPU_gf2xPolyNull(a);
265 
266  if (n < tmp->deg + 1) {
267  memcpy((void *)(a->coef), (void *)(tmp->coef + n), (tmp->deg + 1 - n) * sizeof(BPU_T_GF2_16x));
268 
269  a->deg = BPU_gf2xPolyGetDeg(a);
270  }
271  BPU_gf2xPolyFree(&tmp);
272 }
273 
275  BPU_T_GF2_16x_Poly *tmp;
276 
277  // if there is nothing to shift, return
278  if (a->deg == -1 || n <= 0) {
279  return;
280  }
281  BPU_gf2xPolyMalloc(&tmp, a->deg);
282  BPU_gf2xPolyCopy(tmp, a);
283 
284  if (a->max_deg < a->deg + n) {
285  BPU_gf2xPolyResize(a, a->deg + n);
286  }
287  else {
288  BPU_gf2xPolyNull(a);
289  }
290  memcpy((void *)(a->coef + n), (void *)tmp->coef, (tmp->deg + 1) * sizeof(BPU_T_GF2_16x));
291  a->deg = BPU_gf2xPolyGetDeg(a);
292 
293  BPU_gf2xPolyFree(&tmp);
294 }
295 
296 void BPU_gf2xPolyPower(BPU_T_GF2_16x_Poly *a, int e, const BPU_T_Math_Ctx *math_ctx) {
297  int i;
298  BPU_T_GF2_16x_Poly *tmp, *tmp_2;
299 
300  if (e < 0) {
301  BPU_printError("gf2xPolyPower: e < 0, NOT IMPLEMENTED YET");
302 
303  return;
304  }
305  if (e == 0) {
306  BPU_gf2xPolyNull(a);
307  a->coef[0] = 1;
308  a->deg = 0;
309  }
310  else if (e == 1 || a->deg < 0) {
311  return;
312  }
313  else {
314  BPU_gf2xPolyMalloc(&tmp, a->deg * e);
315  BPU_gf2xPolyMalloc(&tmp_2, a->deg * e);
316 
317  BPU_gf2xPolyCopy(tmp, a);
318 
319  for (i = 1; i < e; i++) {
320  BPU_gf2xPolyCopy(tmp_2, tmp);
321 
322  BPU_gf2xPolyMul(tmp, tmp_2, a, math_ctx);
323  }
324  BPU_gf2xPolyCopy(a, tmp);
325 
326  BPU_gf2xPolyFree(&tmp);
327  BPU_gf2xPolyFree(&tmp_2);
328  }
329 }
330 
332  int i;
333 
334  for (i = a->deg; i >= 0; i--) {
335  a->coef[i] = BPU_gf2xMulModT(a->coef[i], el, math_ctx);
336  }
337  a->deg = BPU_gf2xPolyGetDeg(a);
338 }
339 
340 void BPU_gf2xPolyMod(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx) {
341  int i;
342  BPU_T_GF2_16x_Poly *tmp_out, *tmp_mod;
343  BPU_T_GF2_16x lead;
344 
345  if (mod->deg < 0) {
346  return;
347  }
348  if (out->max_deg < a->deg) {
349  BPU_gf2xPolyResize(out, a->deg);
350  }
351  else {
352  BPU_gf2xPolyNull(out);
353  }
354  // if there is nothing to do
355  if (a->deg < mod->deg) {
356  BPU_gf2xPolyCopy(out, a);
357 
358  return;
359  }
360  // prepare tmp variables
361  BPU_gf2xPolyMalloc(&tmp_mod, a->deg);
362  BPU_gf2xPolyMalloc(&tmp_out, a->deg);
363  BPU_gf2xPolyCopy(tmp_out, a);
364 
365  for (i = a->deg; i >= mod->deg; i--) {
366  BPU_gf2xPolyCopy(tmp_mod, mod);
367 
368  lead = BPU_gf2xGetPseudoInv(BPU_gf2xPolyLeadCoef(mod), tmp_out->coef[i], math_ctx);
369 
370  BPU_gf2xPolyMulEl(tmp_mod, lead, math_ctx);
371  BPU_gf2xPolyShl(tmp_mod, tmp_out->deg - mod->deg);
372  BPU_gf2xPolyAdd(out, tmp_out, tmp_mod);
373 
374  if (i > mod->deg) {
375  BPU_gf2xPolyCopy(tmp_out, out);
376  }
377  }
378  BPU_gf2xPolyFree(&tmp_mod);
379  BPU_gf2xPolyFree(&tmp_out);
380 }
381 
383  int i, j;
384  BPU_T_GF2_16x_Poly *row, *tmp;
385  BPU_T_GF2_16x_Matrix *bigMat;//, test;//, test_out; // matrix (S | I)
386 
387  // create square matrix
388  BPU_gf2xMatNull(out);
389  BPU_gf2xMatMalloc(&bigMat, mod->deg, mod->deg * 2);
390  BPU_gf2xPolyMalloc(&tmp, 0);
391  BPU_gf2xPolyMalloc(&row, (2 * out->k));
392 
393  for (i = 0; i < out->k; i++) {
394  BPU_gf2xPolyNull(row);
395  row->coef[2*i] = 1;
396  row->deg = 2*i;
397  // compute line
398  BPU_gf2xPolyMod(tmp, row, mod, math_ctx);
399  // copy elements from polynomial into matrix
400  BPU_gf2xMatInsertPoly(out, tmp, i);
401  }
402  BPU_gf2xPolyFree(&tmp);
403  BPU_gf2xPolyFree(&row);
404 
405  for (i = 0; i < out->k; i++) {
406  for (j = 0; j < out->k; j++) {
407  bigMat->elements[i][j] = out->elements[i][j];
408  }
409  bigMat->elements[i][out->n + i] = 1;
410  }
411  BPU_gf2xMatGEM(bigMat, math_ctx);
412 
413  for (i = 0; i < out->k; i++) {
414  for (j = 0; j < out->k; j++) {
415  out->elements[i][j] = BPU_gf2xRoot(bigMat->elements[i][out->k + j], math_ctx);
416  }
417  }
418  BPU_gf2xMatFree(&bigMat);
419 }
420 
422  int i, j;
423  BPU_T_GF2_16x element;
424 
425  for (i = 0; i < x->len; i++) {
426  element = 0;
427  for (j = 0; j < mat->n; j++) {
428  element = element ^ BPU_gf2xMulModT(x->elements[j], mat->elements[j][i], math_ctx);
429  }
430  out->elements[i] = element;
431  }
432 }
433 
435  BPU_T_GF2_16x sqr;
436  BPU_T_GF2_16x sqr_alpha;
437  int exponent;
438  if (element == 0) {
439  return 0;
440  }
441  exponent = math_ctx->log_table[element];
442  sqr = math_ctx->exp_table[exponent >> 1];
443  if ((exponent & 1) == 1) {
444  sqr_alpha = math_ctx->exp_table[(math_ctx->ord + 1) / 2];
445  sqr = BPU_gf2xMulModT(sqr, sqr_alpha, math_ctx);
446  }
447  return sqr;
448 }
449 
450 void BPU_gf2xPolyRoot(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *poly, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx) {
451  BPU_T_GF2_16x_Vector *tmp, *tmp_out;
452  BPU_T_GF2_16x_Matrix *squareMat;
453  int i;
454 
455  BPU_gf2xVecMalloc(&tmp_out, mod->deg);
456 
457  if (out->deg < mod->deg) {
458  BPU_gf2xPolyResize(out, mod->deg);
459  }
460  BPU_gf2xVecMalloc(&tmp, mod->deg);
461  BPU_gf2xPolyToVec(tmp, poly, mod->deg);
462  BPU_gf2xMatMalloc(&squareMat, mod->deg, mod->deg);
463  BPU_gf2xMatRoot(squareMat, mod, math_ctx);
464 
465  for (i = 0; i < tmp->len; i++) {
466  tmp->elements[i] = BPU_gf2xRoot(tmp->elements[i], math_ctx);
467  }
468  BPU_gf2xVecMulMat(tmp_out, tmp, squareMat, math_ctx);
469  BPU_gf2xPolyNull(out);
470  BPU_gf2xVecToPoly(out, tmp_out);
471 
472  BPU_gf2xMatFree(&squareMat);
473  BPU_gf2xVecFree(&tmp);
474  BPU_gf2xVecFree(&tmp_out);
475 }
476 
478  int i = 31;
479 
480  while (i >= 0) {
481  if (BPU_getBit(poly, i)) {
482  return i;
483  }
484  i--;
485  }
486  return -1;
487 }
488 
490  int i = poly->max_deg;
491 
492  while (i >= 0) {
493  if (poly->coef[i] != 0) {
494  return i;
495  }
496  i--;
497  }
498  return -1;
499 }
500 
502  int i, j;
503 
504  // check if the size is correct
505  if (m->n != permutation->size) {
506  BPU_printError("BPU_gf2MatPermute: permutation size not correct m->n = %d, p->size = %d", m->n, permutation->size);
507 
508  return -1;
509  }
510  // permute
511  for (j = 0; j < m->n; j++) { // column loop
512  for (i = 0; i < m->k; i++) { // row loop
513  out->elements[i][j] = m->elements[i][permutation->elements[j]]; // permute the columns
514  }
515  }
516  return 0;
517 }
518 
519 int BPU_gf2xMatConvertToGf2Mat(BPU_T_GF2_Matrix *out, const BPU_T_GF2_16x_Matrix *m, int element_bit_size) {
520  int i, j, bit, bit_in_element = -1, act_element = 0;
521 
522  if (out->k != m->k * element_bit_size || out->n != m->n) {
523  BPU_printError("Wrong matrix dimension.");
524 
525  return -1;
526  }
527  // converting
528  for (j = 0; j < m->n; j++) { // column loop
529  // check if there is shift through elements
530  if ((j - act_element * out->element_bit_size) >= out->element_bit_size) { // next elemenet, first bit
531  act_element++;
532  bit_in_element = 0;
533  }
534  else // same element, next bit
535  bit_in_element++;
536  for (i = 0; i < m->k; i++) { // row loop
537  for (bit = 0; bit < element_bit_size; bit++) { // bit loop through element of matrix
538  out->elements[i*element_bit_size + bit][act_element] ^= BPU_getBit(m->elements[i][j], bit) << (bit_in_element); // get bit from element and shift it
539  }
540  }
541  }
542  return 0;
543 }
544 
546  BPU_T_GF2_16x_Poly *tmp, *tmp_2, *old_s, *old_t, *old_r, *r, *q;
547  BPU_T_GF2_16x inv_lead;
548  int deg;
549 
550  deg = (a->deg > b->deg) ? a->deg : b->deg;
551 
552  // check GCD qoutient size
553  if (d->max_deg < deg) {
554  BPU_gf2xPolyResize(d, deg);
555  }
556  if (s->max_deg < deg) {
557  BPU_gf2xPolyResize(s, deg);
558  }
559  if (t->max_deg < deg) {
560  BPU_gf2xPolyResize(t, deg);
561  }
562  BPU_gf2xPolyMalloc(&tmp, deg);
563  BPU_gf2xPolyMalloc(&tmp_2, deg);
564  BPU_gf2xPolyMalloc(&old_s, deg);
565  BPU_gf2xPolyMalloc(&old_t, deg);
566  BPU_gf2xPolyMalloc(&old_r, deg);
567  BPU_gf2xPolyMalloc(&r, deg);
568  BPU_gf2xPolyMalloc(&q, deg);
569 
570  BPU_gf2xPolyCopy(r, b);
571  BPU_gf2xPolyCopy(old_r, a);
572 
573  if (a->deg == -1) {
574  BPU_gf2xPolyCopy(old_r, b);
575  old_t->coef[0] = 1;
576  old_t->deg = 0;
577  }
578  else if (b->deg == -1) {
579  BPU_gf2xPolyCopy(old_r, a);
580  old_s->coef[0] = 1;
581  old_s->deg = 0;
582  }
583  else {
584  old_s->coef[0] = 1;
585  old_s->deg = 0;
586 
587  t->coef[0] = 1;
588  t->deg = 0;
589 
590  while (old_r->deg > end_deg && r->deg > -1) {
591  BPU_gf2xPolyDiv(q, tmp, old_r, r, math_ctx);
592 
593  // save old reminder
594  BPU_gf2xPolyCopy(old_r, r);
595  // save current reminder
596  BPU_gf2xPolyCopy(r, tmp);
597 
598  // save s quocient
599  BPU_gf2xPolyCopy(tmp, old_s);
600  BPU_gf2xPolyCopy(old_s, s);
601  BPU_gf2xPolyMul(tmp_2, q, s, math_ctx);
602  BPU_gf2xPolyAdd(s, tmp, tmp_2);
603 
604  // save t quocient
605  BPU_gf2xPolyCopy(tmp, old_t);
606  BPU_gf2xPolyCopy(old_t, t);
607  BPU_gf2xPolyMul(tmp_2, q, t, math_ctx);
608  BPU_gf2xPolyAdd(t, tmp, tmp_2);
609  }
610  }
611  // prepare return values
612  BPU_gf2xPolyCopy(d, old_r);
613  BPU_gf2xPolyCopy(s, old_s);
614  BPU_gf2xPolyCopy(t, old_t);
615 
616  // make monic, if it is not
617  inv_lead = BPU_gf2xPolyMakeMonic(d, math_ctx);
618 
619  if (inv_lead != 0) {
620  BPU_gf2xPolyMulEl(s, inv_lead, math_ctx);
621  BPU_gf2xPolyMulEl(t, inv_lead, math_ctx);
622  }
623  BPU_gf2xPolyFree(&tmp);
624  BPU_gf2xPolyFree(&tmp_2);
625  BPU_gf2xPolyFree(&old_s);
626  BPU_gf2xPolyFree(&old_t);
627  BPU_gf2xPolyFree(&old_r);
628  BPU_gf2xPolyFree(&r);
629  BPU_gf2xPolyFree(&q);
630 
631  return 0;
632 }
633 
635  int i;
636  BPU_T_GF2_16x ret = 0;
637  ret = poly->coef[0];
638 
639  for (i = 1; i <= poly->deg; i++) {
640  ret = ret ^ BPU_gf2xMulModT(poly->coef[i], BPU_gf2xPowerModT(x, i, math_ctx), math_ctx);
641  }
642  return ret;
643 }
644 
646  int i;
647  if (p1->deg != p2->deg) {
648  return -1;
649  }
650  for (i = 0; i <= p1->deg; i++) {
651  if (p1->coef[i] != p2->coef[i]) {
652  return i + 1;
653  }
654  }
655  return 0;
656 }
657 
659  // x^(q^n) = x^((2^m)^n) = x^(2^(m*n))
660  // q = 2^m
661  // check if gcd(x^(q^n) - x, f)==f. if not, f is reducible
662  // find all prime factors of n = deg(f)
663  // for every prime factor t of n check if gcd(x^(q^(n/t)), f) == 1. if not f is reducible
664  // otherwise f is ireducible
665  int i, j;
666  int is_irred = 1;
667  int m = math_ctx->mod_deg;
668  int n = p->deg;
669  int exponent = m*n;
670  BPU_T_GF2_16x_Poly *tmp, *out, *qr, *x, *gcd, *s, *t, *one;
671 
672  // test if some alpha is root
673  for (i = 0; i < math_ctx->ord; i++) {
674  if (BPU_gf2xPolyEval(p, math_ctx->exp_table[i], math_ctx) == 0) {
675  return 0;
676  }
677  }
678  BPU_gf2xPolyMalloc(&out, 0);
679  BPU_gf2xPolyMalloc(&one, 0);
680  BPU_gf2xPolyMalloc(&qr, 0);
681  BPU_gf2xPolyMalloc(&tmp, 1);
682  BPU_gf2xPolyMalloc(&x, 1);
683  // gcd, s, t, will be allocated inside gf2xPolyExtEuclidA
684 
685  // set tmp polynomial tmp(x) = x
686  tmp->coef[0] = 0;
687  tmp->coef[1] = 1;
688  tmp->deg = BPU_gf2xPolyGetDeg(tmp);
689 
690  x->coef[0] = 0;
691  x->coef[1] = 1;
692  x->deg = BPU_gf2xPolyGetDeg(x);
693 
694  one->coef[0] = 1;
695  one->deg = 0;
696 
697  // simplify polynomial with big coeffitient
698  for (i = 0; i < exponent; i++) {
699  BPU_gf2xPolyMul(out, tmp, tmp, math_ctx);
700  BPU_gf2xPolyMod(tmp, out, p, math_ctx);
701  }
702  BPU_gf2xPolyAdd(qr, tmp, x);
703 
704  BPU_gf2xPolyMalloc(&gcd, (qr->deg > p->deg) ? qr->deg : p->deg);
705  BPU_gf2xPolyMalloc(&s, gcd->max_deg);
706  BPU_gf2xPolyMalloc(&t, gcd->max_deg);
707 
708  BPU_gf2xPolyExtEuclid(gcd, s, t, qr, p, -1, math_ctx);
709 
710  // if differs
711  if (BPU_gf2xPolyCmp(p, gcd)) {
712  BPU_gf2xPolyFree(&out);
713  BPU_gf2xPolyFree(&one);
714  BPU_gf2xPolyFree(&qr);
715  BPU_gf2xPolyFree(&tmp);
716  BPU_gf2xPolyFree(&x);
717  BPU_gf2xPolyFree(&gcd);
718  BPU_gf2xPolyFree(&s);
719  BPU_gf2xPolyFree(&t);
720  return 0;
721  }
722 
723  for (j = 2; j <= p->deg; j++) {
724  if (p->deg % j != 0 || BPU_isPrime(j) == 0){
725  continue;
726  }
727  BPU_gf2xPolyNull(tmp);
728  tmp->coef[0] = 0;
729  tmp->coef[1] = 1;
730  tmp->deg = BPU_gf2xPolyGetDeg(tmp);
731 
732  exponent = m*(n/j);
733 
734  for (i = 0; i < exponent; i++) {
735  BPU_gf2xPolyMul(out, tmp, tmp, math_ctx);
736  BPU_gf2xPolyMod(tmp, out, p, math_ctx);
737  }
738  BPU_gf2xPolyExtEuclid(gcd, s, t, tmp, p, -1, math_ctx);
739  // if differs
740  if (BPU_gf2xPolyCmp(one, gcd)) {
741  is_irred = 0;
742  break;
743  }
744  }
745  BPU_gf2xPolyFree(&out);
746  BPU_gf2xPolyFree(&one);
747  BPU_gf2xPolyFree(&qr);
748  BPU_gf2xPolyFree(&tmp);
749  BPU_gf2xPolyFree(&x);
750  BPU_gf2xPolyFree(&gcd);
751  BPU_gf2xPolyFree(&s);
752  BPU_gf2xPolyFree(&t);
753 
754  return is_irred;
755 }
756 
758  // if there is not enough space resize
759  if (dest->max_deg < src->max_deg) {
760  BPU_gf2xPolyResize(dest, src->max_deg);
761  }
762  else {
763  BPU_gf2xPolyNull(dest);
764  }
765  memcpy((void *) (dest->coef), (void *) (src->coef), sizeof(BPU_T_GF2_16x) * (src->max_deg + 1));
766 
767  dest->deg = src->deg;
768 }
769 
770 void BPU_gf2xPolyInv(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx) {
771  BPU_T_GF2_16x_Poly *d, *t;
772 
773  BPU_gf2xPolyMalloc(&d, (a->deg > mod->deg) ? a->deg : mod->deg);
774  BPU_gf2xPolyMalloc(&t, d->max_deg);
775 
776  BPU_gf2xPolyExtEuclid(d, out, t, a, mod, 0, math_ctx);
777 
778  if (d->deg != 0 || d->coef[0] != 1) {
779  BPU_printDebug("inverse polynomial NOT found");
780  BPU_printError("degree: %d\nelement: %d", d->deg, d->coef[0]);
781 #ifdef BPU_CONF_PRINT
782  BPU_printGf2xPoly(out, math_ctx);
783 #endif
784  BPU_gf2xPolyNull(out);
785  }
786  BPU_gf2xPolyFree(&d);
787  BPU_gf2xPolyFree(&t);
788 }
789 
791  BPU_T_GF2_16x inv_lead = 0;
792 
793  // if it is already monic do nothing
794  if ((a->deg > -1 && a->coef[a->deg] == 1) || a->deg == -1) {
795  return inv_lead;
796  }
797  inv_lead = BPU_gf2xInvElement(BPU_gf2xPolyLeadCoef(a), math_ctx);
798  BPU_gf2xPolyMulEl(a, inv_lead, math_ctx);
799 
800  return inv_lead;
801 }
802 
804  return BPU_gf2xMulModT(BPU_gf2xInvElement(a, math_ctx), res, math_ctx);
805 }
806 
808  int j;
809  for (j = 0; j <= poly->deg; j++) {
810  mat->elements[i][j] = poly->coef[j];
811  }
812 }
813 
815  int i;
816 
817  if (poly->deg >= len) {
818  BPU_printError("dimension missmatch");
819 
820  exit(-1);
821  }
822  vec->len = len;
823 
824  for (i = 0; i <= poly->deg; i++) {
825  vec->elements[i] = poly->coef[i];
826  }
827 }
828 
830  int i;
831 
832  for (i = 0; i < vec->len; i++) {
833  poly->coef[i] = vec->elements[i];
834  }
835  poly->deg = BPU_gf2xPolyGetDeg(poly);
836 }
837 
839  BPU_T_GF2_16x tmp;
840  tmp = *a;
841  *a = *b;
842  *b = tmp;
843 }
844 
845 void BPU_gf2xMatSwapRows(BPU_T_GF2_16x_Matrix *mat, int i, int j) {
846  int k;
847  for (k = 0; k < mat->n; k++) {
848  BPU_gf2xSwap(&(mat->elements[i][k]), &(mat->elements[j][k]));
849  }
850 }
851 
852 void BPU_gf2xMatMulElRow(BPU_T_GF2_16x_Matrix *mat, const BPU_T_GF2_16x element, int row, const BPU_T_Math_Ctx *math_ctx) {
853  int i;
854  for (i = 0; i < mat->n; i++) {
855  mat->elements[row][i] = BPU_gf2xMulModT(element, mat->elements[row][i], math_ctx);
856  }
857 }
858 
859 int BPU_gf2xMatFindPivot(const BPU_T_GF2_16x_Matrix *mat, int index) {
860  int i;
861  for (i = index; i < mat->k; i++) {
862  if(mat->elements[i][index] != 0) {
863  return i;
864  }
865  }
866  return -1;
867 }
868 
870  int i;
871  for (i = 0; i < vec->len; i++) {
872  vec->elements[i] = BPU_gf2xMulModT(element, vec->elements[i], math_ctx);
873  }
874 }
875 
876 void BPU_gf2xMatXorRows(BPU_T_GF2_16x_Matrix *mat, int index, int j, const BPU_T_Math_Ctx *math_ctx) {
877  int k;
878  BPU_T_GF2_16x element;
880 
881  BPU_gf2xVecMalloc(&tmp, mat->n);
882  for (k = 0; k < tmp->len; k++) {
883  tmp->elements[k] = mat->elements[index][k];
884  }
885  element = mat->elements[j][index];
886 
887  BPU_gf2xVecMulEl(tmp, element, math_ctx);
888 
889  for (k = 0; k < tmp->len; k++) {
890  mat->elements[j][k] = mat->elements[j][k] ^ tmp->elements[k];
891  }
892  BPU_gf2xVecFree(&tmp);
893 }
894 
895 void BPU_gf2xMatClearCol(BPU_T_GF2_16x_Matrix *mat, int index, const BPU_T_Math_Ctx *math_ctx) {
896  int i;
897  for (i = 0; i < mat->k; i++) {
898  if (i == index) {
899  continue;
900  }
901  BPU_gf2xMatXorRows(mat, index, i, math_ctx);
902  }
903 }
904 
906  int i, pivot;
907  BPU_T_GF2_16x element;
908  for (i = 0; i < mat->k; i++) {
909  pivot = BPU_gf2xMatFindPivot(mat, i);
910  if (pivot == -1)
911  BPU_printError("################# unbeliviable 'badness' ###########");
912  if (pivot != i) {
913  BPU_gf2xMatSwapRows(mat, i, pivot);
914  }
915  if (mat->elements[i][i] != 1) {
916  element = BPU_gf2xPowerModT(mat->elements[i][i], -1, math_ctx);
917  BPU_gf2xMatMulElRow(mat, element, i, math_ctx);
918  }
919  BPU_gf2xMatClearCol(mat, i, math_ctx);
920  }
921 }
922 
923 void BPU_gf2xPolyGenRandom(BPU_T_GF2_16x_Poly *p, int t, const BPU_T_Math_Ctx *math_ctx) {
924  int i;
925  p->coef[t] = 1;
926  p->coef[0] = BPU_prngGetRand(1, math_ctx->ord);
927 
928  for (i = 1; i < t; i++) {
929  p->coef[i] = BPU_prngGetRand(0, math_ctx->ord);
930  }
931  p->deg = t;
932 }
933 
934 void BPU_gf2xPolyGenGoppa(BPU_T_GF2_16x_Poly *p, int t, const BPU_T_Math_Ctx *math_ctx) {
935 #if defined(DEBUG_L) || defined(WARNING_L)
936  int i = 1;
937 #endif
938  while(1) {
939  BPU_gf2xPolyGenRandom(p, t, math_ctx);
940 
941  if (BPU_gf2xPolyIrredTest(p, math_ctx) == 1) {
942  break;
943  }
944  BPU_printWarning("new irreducibility test #%d", i++);
945  }
946 }
BPU_T_GF2_16x BPU_gf2xMulMod(BPU_T_GF2_16x a, BPU_T_GF2_16x b, BPU_T_GF2_16x mod)
Multiplication over Galois field, modulus mod.
Definition: gf2x.c:78
void BPU_gf2xMatNull(BPU_T_GF2_16x_Matrix *mat)
Definition: gf2xtypes.c:148
#define BPU_getBit(w, n)
Check if is set bit at n-th index.
Definition: gf2.h:173
#define BPU_gf2xPolyLeadCoef(poly_gf2_16x_p)
Definition: gf2x.h:72
void BPU_gf2xPolyMul(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *b, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:235
BPU_T_GF2_16x BPU_gf2xGetPseudoInv(const BPU_T_GF2_16x a, const BPU_T_GF2_16x res, const BPU_T_Math_Ctx *math_ctx)
Get GF2_16x element which is a * return = res.
Definition: gf2x.c:803
int BPU_gf2xPolyExtEuclid(BPU_T_GF2_16x_Poly *d, BPU_T_GF2_16x_Poly *s, BPU_T_GF2_16x_Poly *t, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *b, const int end_deg, const BPU_T_Math_Ctx *math_ctx)
Extended Euclidean to find greatest common divisor and Bézout coefficients s, t, where gcd(a...
Definition: gf2x.c:545
BPU_T_GF2_16x * exp_table
there are all elements referenced by i, so at i-th index is g^i element, g - generator ...
Definition: mathctx.h:33
BPU_T_Perm_Element * elements
permutation vector
Definition: permtypes.h:32
int BPU_gf2xGetDeg(BPU_T_GF2_32x poly)
Get degree of polynomial over GF2.
Definition: gf2x.c:477
void BPU_printGf2xVec(const BPU_T_GF2_16x_Vector *v)
BPU_printGf2xVec print GF2x vector.
Definition: gf2x.c:68
void BPU_gf2xPolyGenRandom(BPU_T_GF2_16x_Poly *p, int t, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:923
#define BPU_gf2xPolyNull(d_pointer)
Copy Polynomial.
Definition: gf2xtypes.h:64
int BPU_gf2xMatMalloc(BPU_T_GF2_16x_Matrix **m, int rows, int cols)
Allocate memory for matrix.
Definition: gf2xtypes.c:28
int BPU_gf2xMatMul(BPU_T_GF2_16x_Matrix *x, const BPU_T_GF2_16x_Matrix *a, const BPU_T_GF2_16x_Matrix *b, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:129
void BPU_gf2xMatRoot(BPU_T_GF2_16x_Matrix *out, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:382
BPU_T_GF2_16x ** elements
all element of matrix
Definition: gf2xtypes.h:45
int BPU_gf2xPolyMalloc(BPU_T_GF2_16x_Poly **p, int16_t max_deg)
Definition: gf2xtypes.c:111
void BPU_gf2xVecMulMat(BPU_T_GF2_16x_Vector *out, const BPU_T_GF2_16x_Vector *x, const BPU_T_GF2_16x_Matrix *mat, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:421
uint16_t BPU_T_GF2_16x
Definition: gf2xtypes.h:26
#define BPU_printWarning(fmt,...)
print warning message with filename, line
Definition: debugio.h:55
uint32_t k
rows
Definition: gf2types.h:47
void BPU_gf2xPolyShr(BPU_T_GF2_16x_Poly *a, int n)
Shift polynomial right, it is like a div x^n.
Definition: gf2x.c:255
BPU_T_GF2_16x * log_table
there are all indexes referenced by element, so alpha elemnet (g^i) -> i
Definition: mathctx.h:34
void BPU_gf2xPolyMod(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx)
Calculate reminder of a. Example a mod b = reminder.
Definition: gf2x.c:340
int BPU_gf2xPolyGetDeg(BPU_T_GF2_16x_Poly *poly)
Get degree of polynomial over GF2x.
Definition: gf2x.c:489
uint32_t BPU_prngGetRand(int from, int to)
Get random unsigned int 32 value from given range (from <= return <= to)
Definition: prng.c:28
BPU_T_GF2_16x * elements
Definition: gf2xtypes.h:37
void BPU_printGf2xPoly(const BPU_T_GF2_16x_Poly *p, const BPU_T_Math_Ctx *math_ctx)
BPU_printGf2xPoly print GF2x polynomial.
Definition: gf2x.c:47
int BPU_gf2xMatPermute(BPU_T_GF2_16x_Matrix *out, const BPU_T_GF2_16x_Matrix *m, const BPU_T_Perm_Vector *permutation)
Definition: gf2x.c:501
#define BPU_gf2xInvElement(gf2_16x_e, math_ctx_p)
Get inverse element of galois field.
Definition: gf2x.h:64
void BPU_gf2xMatMulElRow(BPU_T_GF2_16x_Matrix *mat, const BPU_T_GF2_16x element, int row, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:852
uint16_t n
cols
Definition: gf2xtypes.h:47
BPU_T_GF2_16x BPU_gf2xPolyMakeMonic(BPU_T_GF2_16x_Poly *a, const BPU_T_Math_Ctx *math_ctx)
Make from polynomial monic polynomial.
Definition: gf2x.c:790
uint8_t len
number of elements
Definition: gf2xtypes.h:38
void BPU_gf2xPolyMulEl(BPU_T_GF2_16x_Poly *a, BPU_T_GF2_16x el, const BPU_T_Math_Ctx *math_ctx)
Multiplication polynomial over GF2_16x and element from GF2_16x.
Definition: gf2x.c:331
void BPU_gf2xMatClearCol(BPU_T_GF2_16x_Matrix *mat, int index, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:895
#define BPU_printError(fmt,...)
print error message with filename, line
Definition: debugio.h:47
BPU_T_GF2_16x BPU_gf2xPowerModT(BPU_T_GF2_16x a, int e, const BPU_T_Math_Ctx *math_ctx)
E-th power of a. It uses precomputed log and exp tables.
Definition: gf2x.c:110
#define BPU_gf2xMulModT(a, b, math_ctx)
Multiplication over Galois field, modulus mod.
Definition: gf2x.h:94
int BPU_gf2xMatConvertToGf2Mat(BPU_T_GF2_Matrix *out, const BPU_T_GF2_16x_Matrix *m, int element_bit_size)
Definition: gf2x.c:519
uint8_t element_bit_size
element size, is sizeof(BPU_T_GF2) i.e. 64 bits
Definition: gf2types.h:45
void BPU_gf2xPolyToVec(BPU_T_GF2_16x_Vector *vec, const BPU_T_GF2_16x_Poly *poly, int len)
Definition: gf2x.c:814
void BPU_gf2xMatXorRows(BPU_T_GF2_16x_Matrix *mat, int index, int j, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:876
#define BPU_printDebug(fmt,...)
print debug message with filename, line
Definition: debugio.h:63
BPU_T_Perm_Element size
permutation size
Definition: permtypes.h:33
void BPU_gf2xSwap(BPU_T_GF2_16x *a, BPU_T_GF2_16x *b)
Definition: gf2x.c:838
void BPU_gf2xMatFree(BPU_T_GF2_16x_Matrix **m)
Free dynamically or statically allocated matrix.
Definition: gf2xtypes.c:86
int BPU_gf2xMatFindPivot(const BPU_T_GF2_16x_Matrix *mat, int index)
Definition: gf2x.c:859
void BPU_gf2xMatInsertPoly(BPU_T_GF2_16x_Matrix *mat, const BPU_T_GF2_16x_Poly *poly, int i)
Definition: gf2x.c:807
BPU_T_GF2_16x BPU_gf2xRoot(BPU_T_GF2_16x element, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:434
uint32_t BPU_T_GF2_32x
Definition: gf2xtypes.h:31
void BPU_gf2xPolyGenGoppa(BPU_T_GF2_16x_Poly *p, int t, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:934
void BPU_gf2xMatSwapRows(BPU_T_GF2_16x_Matrix *mat, int i, int j)
Definition: gf2x.c:845
int16_t max_deg
degree
Definition: gf2xtypes.h:56
void BPU_gf2xPolyRoot(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *poly, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx)
BPU_gf2xPolyRoot calculate root of given polynomial over GF2x.
Definition: gf2x.c:450
BPU_T_GF2_16x * coef
Polynomial over GF2m.
Definition: gf2xtypes.h:54
void BPU_gf2xPolyFree(BPU_T_GF2_16x_Poly **p)
Definition: gf2xtypes.c:102
uint32_t n
cols
Definition: gf2types.h:48
BPU_T_GF2_16x BPU_gf2xPolyEval(const BPU_T_GF2_16x_Poly *poly, const BPU_T_GF2_16x x, const BPU_T_Math_Ctx *math_ctx)
Evaluate polynomial over GF2^m with x.
Definition: gf2x.c:634
uint16_t k
rows
Definition: gf2xtypes.h:46
int BPU_gf2xPolyCmp(const BPU_T_GF2_16x_Poly *p1, const BPU_T_GF2_16x_Poly *p2)
Definition: gf2x.c:645
void BPU_gf2xPolyShl(BPU_T_GF2_16x_Poly *a, int n)
Shift polynomial left, it is like a mul 1/x^n.
Definition: gf2x.c:274
int16_t deg
degree
Definition: gf2xtypes.h:55
void BPU_gf2xPolyCopy(BPU_T_GF2_16x_Poly *dest, const BPU_T_GF2_16x_Poly *src)
Copy Polynomial.
Definition: gf2x.c:757
void BPU_gf2xMatGEM(BPU_T_GF2_16x_Matrix *mat, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:905
void BPU_gf2xVecToPoly(BPU_T_GF2_16x_Poly *poly, const BPU_T_GF2_16x_Vector *vec)
Definition: gf2x.c:829
void BPU_gf2xVecMulEl(BPU_T_GF2_16x_Vector *vec, BPU_T_GF2_16x element, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:869
void BPU_gf2xPolyAdd(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *b)
Definition: gf2x.c:161
int BPU_gf2xPolyResize(BPU_T_GF2_16x_Poly *p, int16_t max_deg)
BPU_gf2xPolyResize Resize polynomial, increase max deg.
Definition: gf2xtypes.c:121
int ord
group ord, number of elements
Definition: mathctx.h:37
int BPU_gf2xPolyIrredTest(const BPU_T_GF2_16x_Poly *p, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:658
void BPU_printGf2xMat(const BPU_T_GF2_16x_Matrix *in)
Definition: gf2x.c:33
int BPU_isPrime(int n)
Definition: int.c:24
void BPU_gf2xPolyPower(BPU_T_GF2_16x_Poly *a, int e, const BPU_T_Math_Ctx *math_ctx)
Calculate power of polynomial.
Definition: gf2x.c:296
uint8_t mod_deg
modulo degree, galois finite field GF(2^m)
Definition: mathctx.h:36
void BPU_gf2xPolyDiv(BPU_T_GF2_16x_Poly *q, BPU_T_GF2_16x_Poly *r, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *b, const BPU_T_Math_Ctx *math_ctx)
Definition: gf2x.c:184
void BPU_gf2xVecFree(BPU_T_GF2_16x_Vector **vec)
BPU_gf2xVecFree Free vector structure.
Definition: gf2xtypes.c:77
BPU_T_GF2 ** elements
all element of matrix
Definition: gf2types.h:44
void BPU_gf2xPolyInv(BPU_T_GF2_16x_Poly *out, const BPU_T_GF2_16x_Poly *a, const BPU_T_GF2_16x_Poly *mod, const BPU_T_Math_Ctx *math_ctx)
Get inverse polynomial over GF2_16x.
Definition: gf2x.c:770
int BPU_gf2xVecMalloc(BPU_T_GF2_16x_Vector **vec, int size)
BPU_gf2xVecMalloc Malloc vector structure.
Definition: gf2xtypes.c:60