#include "common.h"
#include "reedsol.h"
#include "reedsol_logs.h"
INTERNAL void zint_rs_init_gf(rs_t *rs, const unsigned int prime_poly) {
struct item {
const unsigned char *logt;
const unsigned char *alog;
};
static const struct item data[] = {
{ logt_0x13, alog_0x13 },
{ logt_0x25, alog_0x25 },
{ logt_0x43, alog_0x43 },
{ NULL, NULL },
{ logt_0x89, alog_0x89 },
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL },
{ logt_0x11d, alog_0x11d },
{ logt_0x12d, alog_0x12d },
{ NULL, NULL },
{ logt_0x163, alog_0x163 },
};
const unsigned int hash = prime_poly >> 5;
rs->logt = data[hash].logt;
rs->alog = data[hash].alog;
}
INTERNAL void zint_rs_init_code(rs_t *rs, const int nsym, int index) {
int i, k;
const unsigned char *const logt = rs->logt;
const unsigned char *const alog = rs->alog;
unsigned char *rspoly = rs->rspoly;
unsigned char *log_rspoly = rs->log_rspoly;
rs->nsym = nsym;
rspoly[0] = 1;
for (i = 1; i <= nsym; i++) {
rspoly[i] = 1;
for (k = i - 1; k > 0; k--) {
if (rspoly[k])
rspoly[k] = alog[logt[rspoly[k]] + index];
rspoly[k] ^= rspoly[k - 1];
}
rspoly[0] = alog[logt[rspoly[0]] + index];
index++;
}
rs->zero = 0;
for (i = 0; i <= nsym; i++) {
log_rspoly[i] = logt[rspoly[i]];
rs->zero |= rspoly[i] == 0;
}
}
INTERNAL void zint_rs_encode(const rs_t *rs, const int datalen, const unsigned char *data, unsigned char *res) {
int i, k;
const unsigned char *const logt = rs->logt;
const unsigned char *const alog = rs->alog;
const unsigned char *const rspoly = rs->rspoly;
const unsigned char *const log_rspoly = rs->log_rspoly;
const int nsym = rs->nsym;
const int nsym_halved = nsym >> 1;
memset(res, 0, nsym);
if (rs->zero) {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
if (rspoly[k])
res[k] = (unsigned char) (res[k - 1] ^ alog[log_m + log_rspoly[k]]);
else
res[k] = res[k - 1];
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, nsym - 1);
res[0] = 0;
}
}
} else {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
res[k] = (unsigned char) (res[k - 1] ^ alog[log_m + log_rspoly[k]]);
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, nsym - 1);
res[0] = 0;
}
}
}
for (i = 0; i < nsym_halved; i++) {
const unsigned char tmp = res[i];
res[i] = res[nsym - 1 - i];
res[nsym - 1 - i] = tmp;
}
}
INTERNAL void zint_rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res) {
int i, k;
const unsigned char *const logt = rs->logt;
const unsigned char *const alog = rs->alog;
const unsigned char *const rspoly = rs->rspoly;
const unsigned char *const log_rspoly = rs->log_rspoly;
const int nsym = rs->nsym;
const int nsym_halved = nsym >> 1;
memset(res, 0, sizeof(unsigned int) * nsym);
if (rs->zero) {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
if (rspoly[k])
res[k] = res[k - 1] ^ alog[log_m + log_rspoly[k]];
else
res[k] = res[k - 1];
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1));
res[0] = 0;
}
}
} else {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
res[k] = res[k - 1] ^ alog[log_m + log_rspoly[k]];
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1));
res[0] = 0;
}
}
}
for (i = 0; i < nsym_halved; i++) {
const unsigned int tmp = res[i];
res[i] = res[nsym - 1 - i];
res[nsym - 1 - i] = tmp;
}
}
INTERNAL int zint_rs_uint_init_gf(rs_uint_t *rs_uint, const unsigned int prime_poly, const int logmod) {
int b, p, v;
unsigned int *logt, *alog;
b = logmod + 1;
rs_uint->logt = NULL;
rs_uint->alog = NULL;
if (!(logt = (unsigned int *) calloc(b, sizeof(unsigned int)))) {
return 0;
}
if (!(alog = (unsigned int *) calloc(b * 2, sizeof(unsigned int)))) {
free(logt);
return 0;
}
for (p = 1, v = 0; v < logmod; v++) {
alog[v] = p;
alog[logmod + v] = p;
logt[p] = v;
p <<= 1;
if (p & b)
p ^= prime_poly;
}
rs_uint->logt = logt;
rs_uint->alog = alog;
return 1;
}
INTERNAL void zint_rs_uint_init_code(rs_uint_t *rs_uint, const int nsym, int index) {
int i, k;
const unsigned int *const logt = rs_uint->logt;
const unsigned int *const alog = rs_uint->alog;
unsigned short *rspoly = rs_uint->rspoly;
unsigned int *log_rspoly = rs_uint->log_rspoly;
if (logt == NULL || alog == NULL) {
return;
}
rs_uint->nsym = nsym;
rspoly[0] = 1;
for (i = 1; i <= nsym; i++) {
rspoly[i] = 1;
for (k = i - 1; k > 0; k--) {
if (rspoly[k])
rspoly[k] = alog[(logt[rspoly[k]] + index)];
rspoly[k] ^= rspoly[k - 1];
}
rspoly[0] = alog[(logt[rspoly[0]] + index)];
index++;
}
rs_uint->zero = 0;
for (i = 0; i <= nsym; i++) {
log_rspoly[i] = logt[rspoly[i]];
rs_uint->zero |= rspoly[i] == 0;
}
}
INTERNAL void zint_rs_uint_encode(const rs_uint_t *rs_uint, const int datalen, const unsigned int *data,
unsigned int *res) {
int i, k;
const unsigned int *const logt = rs_uint->logt;
const unsigned int *const alog = rs_uint->alog;
const unsigned short *const rspoly = rs_uint->rspoly;
const unsigned int *const log_rspoly = rs_uint->log_rspoly;
const int nsym = rs_uint->nsym;
const int nsym_halved = nsym >> 1;
memset(res, 0, sizeof(unsigned int) * nsym);
if (logt == NULL || alog == NULL) {
return;
}
if (rs_uint->zero) {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
if (rspoly[k])
res[k] = res[k - 1] ^ alog[log_m + log_rspoly[k]];
else
res[k] = res[k - 1];
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1));
res[0] = 0;
}
}
} else {
for (i = 0; i < datalen; i++) {
const unsigned int m = res[nsym - 1] ^ data[i];
if (m) {
const unsigned int log_m = logt[m];
for (k = nsym - 1; k > 0; k--) {
res[k] = res[k - 1] ^ alog[log_m + log_rspoly[k]];
}
res[0] = alog[log_m + log_rspoly[0]];
} else {
memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1));
res[0] = 0;
}
}
}
for (i = 0; i < nsym_halved; i++) {
const unsigned int tmp = res[i];
res[i] = res[nsym - 1 - i];
res[nsym - 1 - i] = tmp;
}
}
INTERNAL void zint_rs_uint_free(rs_uint_t *rs_uint) {
if (rs_uint->logt) {
free(rs_uint->logt);
rs_uint->logt = NULL;
}
if (rs_uint->alog) {
free(rs_uint->alog);
rs_uint->alog = NULL;
}
}