#include <stdio.h>
#include <stdint.h>
uint8_t gmul(uint8_t a, uint8_t b)
{
uint8_t p=0;
uint8_t carry;
int i;
for(i=0;i<8;i++)
{
if(b & 1)
p ^=a;
carry = a & 0x80;
a = a<<1;
if(carry)
a^=0x1b;
b = b>>1;
}
return p;
}
uint8_t log_table[256], antilog[255];
const uint8_t g = 3;
void init_log_table(void)
{
log_table[0] = 0; /* dummy value */
for (int i = 0, x = 1; i < 255; x = gmul(x, g), i++) {
log_table[x] = i;
antilog[i] = x;
}
}
uint8_t gmul_table(uint8_t a, uint8_t b)
{
if (a == 0 || b == 0) return 0;
uint8_t x = log_table[a];
uint8_t y = log_table[b];
uint8_t log_mult = (x + y) % 255;
return antilog[log_mult];
}
uint8_t ginv_table(uint8_t a)
{
if (a == 0) return 0; /* Error */
uint8_t x = log_table[a];
uint8_t log_inv = (255 - x) % 255;
return antilog[log_inv];
}
/* GCC __builtin_clz() counts the number of leading zeros in an unsigned int. */
/* The constant 32 doesn't actually matter for us, since we only use this to */
/* calculate the difference between two bit lengths. */
#define bitlength(x) (32 - __builtin_clz(x))
uint8_t ginv(uint8_t x)
{
uint16_t u1 = 0, u3 = 0x11b, v1 = 1, v3 = x;
while (v3 != 0) {
uint16_t t1 = u1, t3 = u3;
int8_t q = bitlength(u3) - bitlength(v3);
if (q >= 0) {
t1 ^= v1 << q;
t3 ^= v3 << q;
}
u1 = v1; u3 = v3;
v1 = t1; v3 = t3;
}
if (u1 >= 0x100) u1 ^= 0x11b;
return u1;
}
int main(void) {
init_log_table();
/* test multiplication */
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
uint8_t a = gmul(i, j), b = gmul_table(i, j);
if (a != b) {
printf("Fail: gmul(%d, %d) = %d != %d = gmul_table(%d, %d)!\n", i
, j
, a
, b
, i
, j
); return 1;
}
}
}
puts("Multiplication test passed OK!");
/* test inverse */
for (int i = 1; i < 256; i++) {
uint8_t a = ginv(i), b = ginv_table(i);
if (a != b) {
printf("Fail: ginv(%d) = %d != %d = ginv_table(%d)!\n", i
, a
, b
, i
); return 1;
}
uint8_t j = gmul_table(i, a);
if (j != 1) {
printf("Fail: ginv(%d) = %d, %d * %d = %d != 1!\n", i
, a
, i
, a
, j
); return 1;
}
}
puts("Inverse test passed OK!");
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRpbnQuaD4KCnVpbnQ4X3QgIGdtdWwodWludDhfdCAgYSwgdWludDhfdCAgYikKewogICAgdWludDhfdCBwPTA7CiAgICB1aW50OF90IGNhcnJ5OwogICAgaW50IGk7CiAgICBmb3IoaT0wO2k8ODtpKyspCiAgICB7CiAgICAgICAgaWYoYiAmIDEpCiAgICAgICAgICAgIHAgXj1hOwogICAgICAgIGNhcnJ5ID0gYSAmIDB4ODA7CiAgICAgICAgYSA9IGE8PDE7CiAgICAgICAgaWYoY2FycnkpCiAgICAgICAgICAgIGFePTB4MWI7CiAgICAgICAgYiA9IGI+PjE7CiAgICB9CiAgICByZXR1cm4gcDsKfQoKdWludDhfdCBsb2dfdGFibGVbMjU2XSwgYW50aWxvZ1syNTVdOwpjb25zdCB1aW50OF90IGcgPSAzOwoKdm9pZCBpbml0X2xvZ190YWJsZSh2b2lkKQp7CiAgICBsb2dfdGFibGVbMF0gPSAwOyAgLyogZHVtbXkgdmFsdWUgKi8KICAgIGZvciAoaW50IGkgPSAwLCB4ID0gMTsgaSA8IDI1NTsgeCA9IGdtdWwoeCwgZyksIGkrKykgewogICAgICAgIGxvZ190YWJsZVt4XSA9IGk7CiAgICAgICAgYW50aWxvZ1tpXSA9IHg7CiAgICB9Cn0KCnVpbnQ4X3QgZ211bF90YWJsZSh1aW50OF90IGEsIHVpbnQ4X3QgYikKewogICAgaWYgKGEgPT0gMCB8fCBiID09IDApIHJldHVybiAwOwoKICAgIHVpbnQ4X3QgeCA9IGxvZ190YWJsZVthXTsKICAgIHVpbnQ4X3QgeSA9IGxvZ190YWJsZVtiXTsKICAgIHVpbnQ4X3QgbG9nX211bHQgPSAoeCArIHkpICUgMjU1OwoKICAgIHJldHVybiBhbnRpbG9nW2xvZ19tdWx0XTsKfQoKdWludDhfdCBnaW52X3RhYmxlKHVpbnQ4X3QgYSkKewogICAgaWYgKGEgPT0gMCkgcmV0dXJuIDA7ICAgLyogRXJyb3IgKi8KCiAgICB1aW50OF90IHggPSBsb2dfdGFibGVbYV07CiAgICB1aW50OF90IGxvZ19pbnYgPSAoMjU1IC0geCkgJSAyNTU7CgogICAgcmV0dXJuIGFudGlsb2dbbG9nX2ludl07Cn0KCi8qIEdDQyBfX2J1aWx0aW5fY2x6KCkgY291bnRzIHRoZSBudW1iZXIgb2YgbGVhZGluZyB6ZXJvcyBpbiBhbiB1bnNpZ25lZCBpbnQuICovCi8qIFRoZSBjb25zdGFudCAzMiBkb2Vzbid0IGFjdHVhbGx5IG1hdHRlciBmb3IgdXMsIHNpbmNlIHdlIG9ubHkgdXNlIHRoaXMgdG8gICovCi8qIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHR3byBiaXQgbGVuZ3Rocy4gKi8KI2RlZmluZSBiaXRsZW5ndGgoeCkgKDMyIC0gX19idWlsdGluX2Nseih4KSkKCnVpbnQ4X3QgZ2ludih1aW50OF90IHgpCnsKICAgIHVpbnQxNl90IHUxID0gMCwgdTMgPSAweDExYiwgdjEgPSAxLCB2MyA9IHg7CgogICAgd2hpbGUgKHYzICE9IDApIHsKICAgICAgICB1aW50MTZfdCB0MSA9IHUxLCB0MyA9IHUzOwogICAgICAgIGludDhfdCBxID0gYml0bGVuZ3RoKHUzKSAtIGJpdGxlbmd0aCh2Myk7CgogICAgICAgIGlmIChxID49IDApIHsKICAgICAgICAgICAgdDEgXj0gdjEgPDwgcTsKICAgICAgICAgICAgdDMgXj0gdjMgPDwgcTsKICAgICAgICB9CiAgICAgICAgdTEgPSB2MTsgdTMgPSB2MzsKICAgICAgICB2MSA9IHQxOyB2MyA9IHQzOwogICAgfQoKICAgIGlmICh1MSA+PSAweDEwMCkgdTEgXj0gMHgxMWI7CgogICAgcmV0dXJuIHUxOwp9CgppbnQgbWFpbih2b2lkKSB7Cglpbml0X2xvZ190YWJsZSgpOwoJCgkvKiB0ZXN0IG11bHRpcGxpY2F0aW9uICovCglmb3IgKGludCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CgkJZm9yIChpbnQgaiA9IDA7IGogPCAyNTY7IGorKykgewoJCQl1aW50OF90IGEgPSBnbXVsKGksIGopLCBiID0gZ211bF90YWJsZShpLCBqKTsKCQkJaWYgKGEgIT0gYikgewoJCQkJcHJpbnRmKCJGYWlsOiBnbXVsKCVkLCAlZCkgPSAlZCAhPSAlZCA9IGdtdWxfdGFibGUoJWQsICVkKSFcbiIsIGksIGosIGEsIGIsIGksIGopOwoJCQkJcmV0dXJuIDE7CgkJCX0KCQl9Cgl9CglwdXRzKCJNdWx0aXBsaWNhdGlvbiB0ZXN0IHBhc3NlZCBPSyEiKTsgCgkKCS8qIHRlc3QgaW52ZXJzZSAqLwoJZm9yIChpbnQgaSA9IDE7IGkgPCAyNTY7IGkrKykgewoJCXVpbnQ4X3QgYSA9IGdpbnYoaSksIGIgPSBnaW52X3RhYmxlKGkpOwoJCWlmIChhICE9IGIpIHsKCQkJcHJpbnRmKCJGYWlsOiBnaW52KCVkKSA9ICVkICE9ICVkID0gZ2ludl90YWJsZSglZCkhXG4iLCBpLCBhLCBiLCBpKTsKCQkJcmV0dXJuIDE7CgkJfQoJCXVpbnQ4X3QgaiA9IGdtdWxfdGFibGUoaSwgYSk7CgkJaWYgKGogIT0gMSkgewoJCQlwcmludGYoIkZhaWw6IGdpbnYoJWQpID0gJWQsICVkICogJWQgPSAlZCAhPSAxIVxuIiwgaSwgYSwgaSwgYSwgaik7CgkJCXJldHVybiAxOwoJCX0KCX0JCglwdXRzKCJJbnZlcnNlIHRlc3QgcGFzc2VkIE9LISIpOwoJCglyZXR1cm4gMDsKfQ==