int main(void) { gf a, b, c; gf_init(); a = 1; b = 37; c = 78; testit("1 * ( 37 + 78 ) = 1 * 37 + 1 * 78", GF_MUL(a, GF_ADD(b, c)), GF_ADD(GF_MUL(a, b), GF_MUL(a, c))); testit("(1 * 37) * 78 = 1 * (37 * 78)", GF_MUL(GF_MUL(a, b), c), GF_MUL(a, GF_MUL(b, c))); testit("(37 * 78) * 37 = (37 * 37) * 78", GF_MUL(GF_MUL(b, c), b), GF_MUL(GF_MUL(b, b), c)); testit("b * b^-1 = 1", GF_MUL(b, GF_INV(b)), 1); return 0; }
/* * Full implementation of the three error correcting Peterson decoder. For * t<6, it is faster than Massey - Berlekamp. It is also somewhat more * intuitive. */ extern void ecc_decode(uint8_t code[ECC_CAPACITY], uint8_t mesg[ECC_CAPACITY], int *errcode) { REVERSE(code, ECC_CAPACITY); uint8_t syn[ECC_OFFSET + 1], deter, z[4], e0, e1, e2, n0, n1, n2, w0, w1, w2, x0, x[3]; int sols; *errcode = 0; /* * First, get the message out of the code, so that even if we can't correct * it, we return an estimate. */ for (int i = 0; i < ECC_PAYLOAD; i++) mesg[i] = code[(ECC_CAPACITY - 1) - i]; syndrome(code, syn); if (syn[0] == 0) return; /* * We now know we have at least one error. If there are no errors detected, * we assume that something funny is going on, and so return with errcode 4, * else pass the number of errors back via errcode. */ errnum(syn, &deter, errcode); if (*errcode == 4) return; /* Having obtained the syndrome, the number of errors, and the determinant, * we now proceed to correct the block. If we do not find exactly the * number of solutions equal to the number of errors, we have exceeded our * error capacity, and return with the block uncorrected, and errcode 4. */ switch (*errcode) { case 1: x0 = GF_MUL(syn[2], GF_INV(syn[1])); w0 = GF_MUL(GF_EXP(syn[1], 2), GF_INV(syn[2])); if (v2e[x0] > 5) mesg[(ECC_CAPACITY - 1) - v2e[x0]] = GF_ADD(mesg[(ECC_CAPACITY - 1) - v2e[x0]], w0); return; case 2: z[0] = GF_MUL(GF_ADD(GF_MUL(syn[1], syn[3]), GF_EXP(syn[2], 2)), GF_INV(deter)); z[1] = GF_MUL(GF_ADD(GF_MUL(syn[2], syn[3]), GF_MUL(syn[1], syn[4])), GF_INV(deter)); z[2] = 1; z[3] = 0; polysolve(z, x, &sols); if (sols != 2) { *errcode = 4; return; } w0 = GF_MUL(z[0], syn[1]); w1 = GF_ADD(GF_MUL(z[0], syn[2]), GF_MUL(z[1], syn[1])); n0 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[0])]; n1 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[1])]; e0 = GF_MUL(GF_ADD(w0, GF_MUL(w1, x[0])), GF_INV(z[1])); e1 = GF_MUL(GF_ADD(w0, GF_MUL(w1, x[1])), GF_INV(z[1])); if (n0 < ECC_PAYLOAD) mesg[n0] = GF_ADD(mesg[n0], e0); if (n1 < ECC_PAYLOAD) mesg[n1] = GF_ADD(mesg[n1], e1); return; case 3: z[3] = 1; z[2] = GF_MUL(syn[1], GF_MUL(syn[4], syn[6])); z[2] = GF_ADD(z[2], GF_MUL(syn[1], GF_MUL(syn[5], syn[5]))); z[2] = GF_ADD(z[2], GF_MUL(syn[5], GF_MUL(syn[3], syn[3]))); z[2] = GF_ADD(z[2], GF_MUL(syn[3], GF_MUL(syn[4], syn[4]))); z[2] = GF_ADD(z[2], GF_MUL(syn[2], GF_MUL(syn[5], syn[4]))); z[2] = GF_ADD(z[2], GF_MUL(syn[2], GF_MUL(syn[3], syn[6]))); z[2] = GF_MUL(z[2], GF_INV(deter)); z[1] = GF_MUL(syn[1], GF_MUL(syn[3], syn[6])); z[1] = GF_ADD(z[1], GF_MUL(syn[1], GF_MUL(syn[5], syn[4]))); z[1] = GF_ADD(z[1], GF_MUL(syn[4], GF_MUL(syn[3], syn[3]))); z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[4], syn[4]))); z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[3], syn[5]))); z[1] = GF_ADD(z[1], GF_MUL(syn[2], GF_MUL(syn[2], syn[6]))); z[1] = GF_MUL(z[1], GF_INV(deter)); z[0] = GF_MUL(syn[2], GF_MUL(syn[3], syn[4])); z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[2], syn[4]))); z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[5], syn[1]))); z[0] = GF_ADD(z[0], GF_MUL(syn[4], GF_MUL(syn[4], syn[1]))); z[0] = GF_ADD(z[0], GF_MUL(syn[3], GF_MUL(syn[3], syn[3]))); z[0] = GF_ADD(z[0], GF_MUL(syn[2], GF_MUL(syn[2], syn[5]))); z[0] = GF_MUL(z[0], GF_INV(deter)); polysolve (z, x, &sols); if (sols != 3) { *errcode = 4; return; } w0 = GF_MUL(z[0], syn[1]); w1 = GF_ADD(GF_MUL(z[0], syn[2]), GF_MUL(z[1], syn[1])); w2 = GF_ADD(GF_MUL(z[0], syn[3]), GF_ADD(GF_MUL(z[1], syn[2]), GF_MUL(z[2], syn[1]))); n0 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[0])]; n1 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[1])]; n2 = (ECC_CAPACITY - 1) - v2e[GF_INV(x[2])]; e0 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[0]), GF_MUL(w2, GF_EXP(x[0], 2)))); e0 = GF_MUL(e0, GF_INV(GF_ADD(z[1], GF_EXP(x[0], 2)))); e1 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[1]), GF_MUL(w2, GF_EXP(x[1], 2)))); e1 = GF_MUL(e1, GF_INV(GF_ADD(z[1], GF_EXP(x[1], 2)))); e2 = GF_ADD(w0, GF_ADD(GF_MUL(w1, x[2]), GF_MUL(w2, GF_EXP(x[2], 2)))); e2 = GF_MUL(e2, GF_INV(GF_ADD(z[1], GF_EXP(x[2], 2)))); if (n0 < ECC_PAYLOAD) mesg[n0] = GF_ADD(mesg[n0], e0); if (n1 < ECC_PAYLOAD) mesg[n1] = GF_ADD(mesg[n1], e1); if (n2 < ECC_PAYLOAD) mesg[n2] = GF_ADD(mesg[n2], e2); return; } }