2 * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
3 * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
4 * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
8 * Routines for Galois fields for general w < 32. For specific w,
9 like 4, 8, 16, 32, 64 and 128, see the other files.
16 struct gf_wgen_table_w8_data {
22 struct gf_wgen_table_w16_data {
28 struct gf_wgen_log_w8_data {
35 struct gf_wgen_log_w16_data {
42 struct gf_wgen_log_w32_data {
49 struct gf_wgen_group_data {
60 gf_val_32_t gf_wgen_inverse_from_divide (gf_t *gf, gf_val_32_t a)
62 return gf->divide.w32(gf, 1, a);
67 gf_val_32_t gf_wgen_divide_from_inverse (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
69 b = gf->inverse.w32(gf, b);
70 return gf->multiply.w32(gf, a, b);
75 gf_val_32_t gf_wgen_euclid (gf_t *gf, gf_val_32_t b)
78 gf_val_32_t e_i, e_im1, e_ip1;
79 gf_val_32_t d_i, d_im1, d_ip1;
80 gf_val_32_t y_i, y_im1, y_ip1;
83 if (b == 0) return -1;
84 e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
86 d_im1 = ((gf_internal_t *) (gf->scratch))->w;
87 for (d_i = d_im1; ((1 << d_i) & e_i) == 0; d_i--) ;
97 while (d_ip1 >= d_i) {
98 c_i ^= (1 << (d_ip1 - d_i));
99 e_ip1 ^= (e_i << (d_ip1 - d_i));
100 if (e_ip1 == 0) return 0;
101 while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
104 y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
117 gf_val_32_t gf_wgen_extract_word(gf_t *gf, void *start, int bytes, int index)
125 h = (gf_internal_t *) gf->scratch;
130 ptr = (uint8_t *) start;
136 for (i = 0; i < h->w; i++) {
138 if ((*ptr) & (1 << bit)) rv |= 1;
147 gf_val_32_t gf_wgen_matrix (gf_t *gf, gf_val_32_t b)
149 return gf_bitmatrix_inverse(b, ((gf_internal_t *) (gf->scratch))->w,
150 ((gf_internal_t *) (gf->scratch))->prim_poly);
156 gf_wgen_shift_multiply (gf_t *gf, uint32_t a32, uint32_t b32)
158 uint64_t product, i, pp, a, b, one;
163 h = (gf_internal_t *) gf->scratch;
165 pp = h->prim_poly | (one << h->w);
169 for (i = 0; i < (uint64_t)h->w; i++) {
170 if (a & (one << i)) product ^= (b << i);
172 for (i = h->w*2-1; i >= (uint64_t)h->w; i--) {
173 if (product & (one << i)) product ^= (pp << (i-h->w));
179 int gf_wgen_shift_init(gf_t *gf)
181 SET_FUNCTION(gf,multiply,w32,gf_wgen_shift_multiply)
182 SET_FUNCTION(gf,inverse,w32,gf_wgen_euclid)
188 gf_wgen_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
190 uint32_t prod, pp, bmask;
193 h = (gf_internal_t *) gf->scratch;
197 bmask = (1 << (h->w-1));
200 if (a & 1) prod ^= b;
202 if (a == 0) return prod;
212 int gf_wgen_bytwo_b_init(gf_t *gf)
214 SET_FUNCTION(gf,multiply,w32,gf_wgen_bytwo_b_multiply)
215 SET_FUNCTION(gf,inverse,w32,gf_wgen_euclid)
222 gf_wgen_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
224 uint32_t prod, pp, pmask, amask;
227 h = (gf_internal_t *) gf->scratch;
231 pmask = (1 << ((h->w)-1)); /*Ben: Had an operator precedence warning here*/
236 prod = ((prod << 1) ^ pp);
240 if (a & amask) prod ^= b;
248 int gf_wgen_bytwo_p_init(gf_t *gf)
250 SET_FUNCTION(gf,multiply,w32,gf_wgen_bytwo_p_multiply)
251 SET_FUNCTION(gf,inverse,w32,gf_wgen_euclid)
257 gf_wgen_group_set_shift_tables(uint32_t *shift, uint32_t val, gf_internal_t *h)
263 if (h->mult_type == GF_MULT_DEFAULT) {
271 for (i = 1; i < ((uint32_t)1 << g_s); i <<= 1) {
272 for (j = 0; j < i; j++) shift[i|j] = shift[j]^val;
273 if (val & (1 << (h->w-1))) {
285 gf_wgen_group_s_equals_r_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
288 uint32_t p, l, ind, a32;
293 struct gf_wgen_group_data *gd;
294 gf_internal_t *h = (gf_internal_t *) gf->scratch;
298 gd = (struct gf_wgen_group_data *) h->private;
299 gf_wgen_group_set_shift_tables(gd->shift, b, h);
302 if (leftover == 0) leftover = g_s;
314 while (bits_left > 0) {
320 p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s)) & gd->mask;
325 char *bits(uint32_t v)
332 for (i = 27; i >= 0; i--) {
333 rv[j] = '0' + ((v & (1 << i)) ? 1 : 0);
339 char *bits_56(uint64_t v)
349 for (i = 55; i >= 0; i--) {
350 rv[j] = '0' + ((v & (one << i)) ? 1 : 0);
360 gf_wgen_group_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
367 struct gf_wgen_group_data *gd;
370 gf_internal_t *h = (gf_internal_t *) gf->scratch;
371 if (h->mult_type == GF_MULT_DEFAULT) {
379 gd = (struct gf_wgen_group_data *) h->private;
380 gf_wgen_group_set_shift_tables(gd->shift, b, h);
383 if (leftover == 0) leftover = g_s;
386 ind = a32 >> (w - leftover);
394 ind = a32 >> (w-g_s);
402 ind = a32 >> (h->w-g_s);
405 for (i = gd->tshift ; i >= 0; i -= g_r) {
406 l = p & (gd->rmask << i);
407 r = gd->reduce[l >> (i+w)];
415 int gf_wgen_group_init(gf_t *gf)
417 uint32_t i, j, p, index;
418 struct gf_wgen_group_data *gd;
419 gf_internal_t *h = (gf_internal_t *) gf->scratch;
422 if (h->mult_type == GF_MULT_DEFAULT) {
429 gd = (struct gf_wgen_group_data *) h->private;
430 gd->shift = &(gd->memory);
431 gd->reduce = gd->shift + (1 << g_s);
432 gd->mask = (h->w != 31) ? ((1 << h->w)-1) : 0x7fffffff;
434 gd->rmask = (1 << g_r) - 1;
437 gd->tshift = h->w % g_s;
438 if (gd->tshift == 0) gd->tshift = g_s;
439 gd->tshift = (h->w - gd->tshift);
440 gd->tshift = ((gd->tshift-1)/g_r) * g_r;
443 for (i = 0; i < ((uint32_t)1 << g_r); i++) {
446 for (j = 0; j < g_r; j++) {
448 p ^= (h->prim_poly << j);
449 index ^= (h->prim_poly >> (h->w-j));
452 gd->reduce[index] = (p & gd->mask);
456 SET_FUNCTION(gf,multiply,w32,gf_wgen_group_s_equals_r_multiply)
458 SET_FUNCTION(gf,multiply,w32,gf_wgen_group_multiply)
460 SET_FUNCTION(gf,divide,w32,NULL)
461 SET_FUNCTION(gf,divide,w32,NULL)
468 gf_wgen_table_8_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
471 struct gf_wgen_table_w8_data *std;
473 h = (gf_internal_t *) gf->scratch;
474 std = (struct gf_wgen_table_w8_data *) h->private;
476 return (std->mult[(a<<h->w)+b]);
481 gf_wgen_table_8_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
484 struct gf_wgen_table_w8_data *std;
486 h = (gf_internal_t *) gf->scratch;
487 std = (struct gf_wgen_table_w8_data *) h->private;
489 return (std->div[(a<<h->w)+b]);
493 int gf_wgen_table_8_init(gf_t *gf)
497 struct gf_wgen_table_w8_data *std;
500 h = (gf_internal_t *) gf->scratch;
502 std = (struct gf_wgen_table_w8_data *) h->private;
504 std->mult = &(std->base);
505 std->div = std->mult + ((1<<h->w)*(1<<h->w));
507 for (a = 0; a < ((uint32_t)1 << w); a++) {
514 for (a = 1; a < ((uint32_t)1 << w); a++) {
515 for (b = 1; b < ((uint32_t)1 << w); b++) {
516 p = gf_wgen_shift_multiply(gf, a, b);
517 std->mult[(a<<w)|b] = p;
518 std->div[(p<<w)|a] = b;
522 SET_FUNCTION(gf,multiply,w32,gf_wgen_table_8_multiply)
523 SET_FUNCTION(gf,divide,w32,gf_wgen_table_8_divide)
529 gf_wgen_table_16_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
532 struct gf_wgen_table_w16_data *std;
534 h = (gf_internal_t *) gf->scratch;
535 std = (struct gf_wgen_table_w16_data *) h->private;
537 return (std->mult[(a<<h->w)+b]);
542 gf_wgen_table_16_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
545 struct gf_wgen_table_w16_data *std;
547 h = (gf_internal_t *) gf->scratch;
548 std = (struct gf_wgen_table_w16_data *) h->private;
550 return (std->div[(a<<h->w)+b]);
554 int gf_wgen_table_16_init(gf_t *gf)
558 struct gf_wgen_table_w16_data *std;
561 h = (gf_internal_t *) gf->scratch;
563 std = (struct gf_wgen_table_w16_data *) h->private;
565 std->mult = &(std->base);
566 std->div = std->mult + ((1<<h->w)*(1<<h->w));
568 for (a = 0; a < ((uint32_t)1 << w); a++) {
575 for (a = 1; a < ((uint32_t)1 << w); a++) {
576 for (b = 1; b < ((uint32_t)1 << w); b++) {
577 p = gf_wgen_shift_multiply(gf, a, b);
578 std->mult[(a<<w)|b] = p;
579 std->div[(p<<w)|a] = b;
583 SET_FUNCTION(gf,multiply,w32,gf_wgen_table_16_multiply)
584 SET_FUNCTION(gf,divide,w32,gf_wgen_table_16_divide)
589 int gf_wgen_table_init(gf_t *gf)
593 h = (gf_internal_t *) gf->scratch;
594 if (h->w <= 8) return gf_wgen_table_8_init(gf);
595 if (h->w <= 14) return gf_wgen_table_16_init(gf);
597 /* Returning zero to make the compiler happy, but this won't get
598 executed, because it is tested in _scratch_space. */
605 gf_wgen_log_8_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
608 struct gf_wgen_log_w8_data *std;
610 h = (gf_internal_t *) gf->scratch;
611 std = (struct gf_wgen_log_w8_data *) h->private;
613 if (a == 0 || b == 0) return 0;
614 return (std->anti[std->log[a]+std->log[b]]);
619 gf_wgen_log_8_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
622 struct gf_wgen_log_w8_data *std;
625 h = (gf_internal_t *) gf->scratch;
626 std = (struct gf_wgen_log_w8_data *) h->private;
628 if (a == 0 || b == 0) return 0;
630 index -= std->log[b];
632 return (std->danti[index]);
636 int gf_wgen_log_8_init(gf_t *gf)
639 struct gf_wgen_log_w8_data *std;
644 h = (gf_internal_t *) gf->scratch;
646 std = (struct gf_wgen_log_w8_data *) h->private;
648 std->log = &(std->base);
649 std->anti = std->log + (1<<h->w);
650 std->danti = std->anti + (1<<h->w)-1;
652 for (i = 0; i < ((uint32_t)1 << w); i++)
656 for(i=0; i < ((uint32_t)1<<w)-1; i++)
658 if (std->log[a] != 0) check = 1;
669 _gf_errno = GF_E_LOGPOLY;
673 SET_FUNCTION(gf,multiply,w32,gf_wgen_log_8_multiply)
674 SET_FUNCTION(gf,divide,w32,gf_wgen_log_8_divide)
680 gf_wgen_log_16_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
683 struct gf_wgen_log_w16_data *std;
685 h = (gf_internal_t *) gf->scratch;
686 std = (struct gf_wgen_log_w16_data *) h->private;
688 if (a == 0 || b == 0) return 0;
689 return (std->anti[std->log[a]+std->log[b]]);
694 gf_wgen_log_16_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
697 struct gf_wgen_log_w16_data *std;
700 h = (gf_internal_t *) gf->scratch;
701 std = (struct gf_wgen_log_w16_data *) h->private;
703 if (a == 0 || b == 0) return 0;
705 index -= std->log[b];
707 return (std->danti[index]);
711 int gf_wgen_log_16_init(gf_t *gf)
714 struct gf_wgen_log_w16_data *std;
719 h = (gf_internal_t *) gf->scratch;
721 std = (struct gf_wgen_log_w16_data *) h->private;
723 std->log = &(std->base);
724 std->anti = std->log + (1<<h->w);
725 std->danti = std->anti + (1<<h->w)-1;
727 for (i = 0; i < ((uint32_t)1 << w); i++)
731 for(i=0; i < ((uint32_t)1<<w)-1; i++)
733 if (std->log[a] != 0) check = 1;
744 if (h->mult_type != GF_MULT_LOG_TABLE) return gf_wgen_shift_init(gf);
745 _gf_errno = GF_E_LOGPOLY;
749 SET_FUNCTION(gf,multiply,w32,gf_wgen_log_16_multiply)
750 SET_FUNCTION(gf,divide,w32,gf_wgen_log_16_divide)
756 gf_wgen_log_32_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
759 struct gf_wgen_log_w32_data *std;
761 h = (gf_internal_t *) gf->scratch;
762 std = (struct gf_wgen_log_w32_data *) h->private;
764 if (a == 0 || b == 0) return 0;
765 return (std->anti[std->log[a]+std->log[b]]);
770 gf_wgen_log_32_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
773 struct gf_wgen_log_w32_data *std;
776 h = (gf_internal_t *) gf->scratch;
777 std = (struct gf_wgen_log_w32_data *) h->private;
779 if (a == 0 || b == 0) return 0;
781 index -= std->log[b];
783 return (std->danti[index]);
787 int gf_wgen_log_32_init(gf_t *gf)
790 struct gf_wgen_log_w32_data *std;
795 h = (gf_internal_t *) gf->scratch;
797 std = (struct gf_wgen_log_w32_data *) h->private;
799 std->log = &(std->base);
800 std->anti = std->log + (1<<h->w);
801 std->danti = std->anti + (1<<h->w)-1;
803 for (i = 0; i < ((uint32_t)1 << w); i++)
807 for(i=0; i < ((uint32_t)1<<w)-1; i++)
809 if (std->log[a] != 0) check = 1;
820 _gf_errno = GF_E_LOGPOLY;
824 SET_FUNCTION(gf,multiply,w32,gf_wgen_log_32_multiply)
825 SET_FUNCTION(gf,divide,w32,gf_wgen_log_32_divide)
830 int gf_wgen_log_init(gf_t *gf)
834 h = (gf_internal_t *) gf->scratch;
835 if (h->w <= 8) return gf_wgen_log_8_init(gf);
836 if (h->w <= 16) return gf_wgen_log_16_init(gf);
837 if (h->w <= 32) return gf_wgen_log_32_init(gf);
839 /* Returning zero to make the compiler happy, but this won't get
840 executed, because it is tested in _scratch_space. */
845 int gf_wgen_scratch_size(int w, int mult_type, int region_type, int divide_type, int arg1, int arg2)
850 case GF_MULT_DEFAULT:
852 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w8_data) +
853 sizeof(uint8_t)*(1 << w)*(1<<w)*2 + 64;
854 } else if (w <= 16) {
855 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w16_data) +
856 sizeof(uint16_t)*(1 << w)*3;
858 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_group_data) +
859 sizeof(uint32_t) * (1 << 2) +
860 sizeof(uint32_t) * (1 << 8) + 64;
863 case GF_MULT_BYTWO_b:
864 case GF_MULT_BYTWO_p:
865 return sizeof(gf_internal_t);
868 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_group_data) +
869 sizeof(uint32_t) * (1 << arg1) +
870 sizeof(uint32_t) * (1 << arg2) + 64;
875 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w8_data) +
876 sizeof(uint8_t)*(1 << w)*(1<<w)*2 + 64;
878 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w16_data) +
879 sizeof(uint16_t)*(1 << w)*(1<<w)*2 + 64;
882 case GF_MULT_LOG_TABLE:
884 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w8_data) +
885 sizeof(uint8_t)*(1 << w)*3;
886 } else if (w <= 16) {
887 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w16_data) +
888 sizeof(uint16_t)*(1 << w)*3;
889 } else if (w <= 27) {
890 return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w32_data) +
891 sizeof(uint32_t)*(1 << w)*3;
900 gf_wgen_cauchy_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
907 gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, -1);
909 if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
910 if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
912 h = (gf_internal_t *) gf->scratch;
915 written = (xor) ? 0xffffffff : 0;
916 for (i = 0; i < h->w; i++) {
917 for (j = 0; j < h->w; j++) {
918 if (val & (1 << j)) {
919 gf_multby_one(src, ((uint8_t *)dest) + j*rs, rs, (written & (1 << j)));
923 src = (uint8_t *)src + rs;
924 val = gf->multiply.w32(gf, val, 2);
928 int gf_wgen_init(gf_t *gf)
932 h = (gf_internal_t *) gf->scratch;
933 if (h->prim_poly == 0) {
935 case 1: h->prim_poly = 1; break;
936 case 2: h->prim_poly = 7; break;
937 case 3: h->prim_poly = 013; break;
938 case 4: h->prim_poly = 023; break;
939 case 5: h->prim_poly = 045; break;
940 case 6: h->prim_poly = 0103; break;
941 case 7: h->prim_poly = 0211; break;
942 case 8: h->prim_poly = 0435; break;
943 case 9: h->prim_poly = 01021; break;
944 case 10: h->prim_poly = 02011; break;
945 case 11: h->prim_poly = 04005; break;
946 case 12: h->prim_poly = 010123; break;
947 case 13: h->prim_poly = 020033; break;
948 case 14: h->prim_poly = 042103; break;
949 case 15: h->prim_poly = 0100003; break;
950 case 16: h->prim_poly = 0210013; break;
951 case 17: h->prim_poly = 0400011; break;
952 case 18: h->prim_poly = 01000201; break;
953 case 19: h->prim_poly = 02000047; break;
954 case 20: h->prim_poly = 04000011; break;
955 case 21: h->prim_poly = 010000005; break;
956 case 22: h->prim_poly = 020000003; break;
957 case 23: h->prim_poly = 040000041; break;
958 case 24: h->prim_poly = 0100000207; break;
959 case 25: h->prim_poly = 0200000011; break;
960 case 26: h->prim_poly = 0400000107; break;
961 case 27: h->prim_poly = 01000000047; break;
962 case 28: h->prim_poly = 02000000011; break;
963 case 29: h->prim_poly = 04000000005; break;
964 case 30: h->prim_poly = 010040000007; break;
965 case 31: h->prim_poly = 020000000011; break;
966 case 32: h->prim_poly = 00020000007; break;
967 default: fprintf(stderr, "gf_wgen_init: w not defined yet\n"); exit(1);
971 h->prim_poly &= 0xffffffff;
973 h->prim_poly |= (1 << h->w);
974 if (h->prim_poly & ~((1ULL<<(h->w+1))-1)) return 0;
978 SET_FUNCTION(gf,multiply,w32,NULL)
979 SET_FUNCTION(gf,divide,w32,NULL)
980 SET_FUNCTION(gf,inverse,w32,NULL)
981 SET_FUNCTION(gf,multiply_region,w32,gf_wgen_cauchy_region)
982 SET_FUNCTION(gf,extract_word,w32,gf_wgen_extract_word)
984 switch(h->mult_type) {
985 case GF_MULT_DEFAULT:
987 if (gf_wgen_table_init(gf) == 0) return 0;
988 } else if (h->w <= 16) {
989 if (gf_wgen_log_init(gf) == 0) return 0;
991 if (gf_wgen_bytwo_p_init(gf) == 0) return 0;
994 case GF_MULT_SHIFT: if (gf_wgen_shift_init(gf) == 0) return 0; break;
995 case GF_MULT_BYTWO_b: if (gf_wgen_bytwo_b_init(gf) == 0) return 0; break;
996 case GF_MULT_BYTWO_p: if (gf_wgen_bytwo_p_init(gf) == 0) return 0; break;
997 case GF_MULT_GROUP: if (gf_wgen_group_init(gf) == 0) return 0; break;
998 case GF_MULT_TABLE: if (gf_wgen_table_init(gf) == 0) return 0; break;
999 case GF_MULT_LOG_TABLE: if (gf_wgen_log_init(gf) == 0) return 0; break;
1002 if (h->divide_type == GF_DIVIDE_EUCLID) {
1003 SET_FUNCTION(gf,divide,w32,gf_wgen_divide_from_inverse)
1004 SET_FUNCTION(gf,inverse,w32,gf_wgen_euclid)
1005 } else if (h->divide_type == GF_DIVIDE_MATRIX) {
1006 SET_FUNCTION(gf,divide,w32,gf_wgen_divide_from_inverse)
1007 SET_FUNCTION(gf,inverse,w32,gf_wgen_matrix)
1010 if (gf->inverse.w32== NULL && gf->divide.w32 == NULL) SET_FUNCTION(gf,inverse,w32,gf_wgen_euclid)
1012 if (gf->inverse.w32 != NULL && gf->divide.w32 == NULL) {
1013 SET_FUNCTION(gf,divide,w32,gf_wgen_divide_from_inverse)
1015 if (gf->inverse.w32 == NULL && gf->divide.w32 != NULL) {
1016 SET_FUNCTION(gf,inverse,w32,gf_wgen_inverse_from_divide)