diff options
Diffstat (limited to 'lpg/libqr/rs-encode.c')
-rw-r--r-- | lpg/libqr/rs-encode.c | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/lpg/libqr/rs-encode.c b/lpg/libqr/rs-encode.c index ec99c6b..ea54d77 100644 --- a/lpg/libqr/rs-encode.c +++ b/lpg/libqr/rs-encode.c @@ -3,11 +3,56 @@ #include "bitstream.h" #include "rs.h" -struct bitstream * rs_generate_words(int k, const int * coeff, struct bitstream * data) +static unsigned int gf_mult(unsigned int a, unsigned int b) +{ + /* Reduce modulo x^8 + x^4 + x^3 + x^2 + 1 + * using the peasant's algorithm + */ + const unsigned int m = 0x11D; + unsigned int x = 0; + int i; + + for (i = 0; i < 8; ++i) { + x ^= (b & 0x1) ? a : 0; + a = (a << 1) ^ ((a & 0x80) ? m : 0); + b >>= 1; + } + + return x & 0xFF; +} + +static unsigned int * make_generator(int k) +{ + unsigned int * g; + unsigned int a; + int i, j; + + g = calloc(k, sizeof(*g)); + if (!g) + return 0; + + g[0] = 1; /* Start with g(x) = 1 */ + a = 1; /* 2^0 = 1 */ + + for (i = 0; i < k; ++i) { + /* Multiply our poly g(x) by (x + 2^i) */ + for (j = k - 1; j > 0; --j) + g[j] = gf_mult(g[j], a) ^ g[j-1]; + g[0] = gf_mult(g[0], a); + + a = gf_mult(a, 2); + } + + return g; +} + +struct bitstream * rs_generate_words(int n, struct bitstream * data) { struct bitstream * ec = 0; unsigned int * b = 0; - size_t n, i, dlen; + unsigned int * g; + size_t dlen; + int i, r; dlen = bitstream_size(data); assert(dlen % 8 == 0); @@ -17,30 +62,35 @@ struct bitstream * rs_generate_words(int k, const int * coeff, struct bitstream if (!ec) return 0; - if (bitstream_resize(ec, k * 8) != 0) + if (bitstream_resize(ec, n * 8) != 0) goto fail; - b = calloc(k, sizeof(*b)); + b = calloc(n, sizeof(*b)); if (!b) goto fail; - /* First, prepare the registers (b) with data bits. Note that - * the registers are in reverse of the normal order - */ + g = make_generator(n); + if (!g) + goto fail; + + /* First, prepare the registers (b) with data bits */ bitstream_seek(data, 0); - for (n = 0; n < dlen; ++n) { - unsigned int x = b[0] + bitstream_read(data, 8); - for (i = 0; i < k-1; ++i) - b[i] = b[i+1] + coeff[(k-1) - i] * x; - b[k-1] = coeff[0] * x; + for (i = 0; i < dlen; ++i) { + unsigned int x = b[n-1] ^ bitstream_read(data, 8); + for (r = n-1; r > 0; --r) + b[r] = b[r-1] ^ gf_mult(g[r], x); + b[0] = gf_mult(g[0], x); } /* Read off the registers */ - bitstream_pack(ec, b, k, 8); + for (r = 0; r < n; ++r) + bitstream_write(ec, b[(n-1)-r], 8); + free(g); free(b); return ec; fail: + free(b); bitstream_destroy(ec); return 0; } |