How to optimise a finite field multiplication? I'm currently trying to optimise the finite field multiplication in $ \operatorname{GF}(2)[x]/(p)$, where $p = x^8 ⊕ x^7 ⊕ x^6 ⊕ x ⊕1 ∈ \operatorname{GF}(2)[x] $.

The thing is that I have to multiply by $ 16,32,133,148,192,194 \ \ and \ \ 251 $. Actually, what I do is that I declare 7 arrays (one for each multiplication; length 256) which contains every result. for example, when i want to multiply $ i = 145 $ by 32, i just assign $ array_{16}[i] $ to the result.

Is there an other way to do the multiplication, in order to reduce the memory used by my algorithm for example?
a better way to optimize the code is to use multiplication by 2 concept(xtime).

xtime(x) is multiplication by 2 which is left-shift modulo irreducible polynomial ($x^8\oplus x^7\oplus x^6\oplus x\oplus1$ = 0x1C3)

xtime is implemented in c code with irreducible polynomial (0x1c3) as following

#define xtime(x)   ((x&lt;&lt;1) ^ (((x&gt;&gt;7) &amp; 1) * 0xc3))



= addition modulo 2(xor in code)


The binary representation of your values is as following:

16  : 00010000

32  : 00100000

133: 10000101

148: 10010100

192: 11000000

194: 11000010

251: 11111011

16*x (mul16) is as following 
16 is $2^4$ (4 times left shift)-> mul16(x)=xtime(xtime(xtime(xtime(x)))). it can be rewritten as of mul8 as following xtime(mul8(x)). mul8 is defined as nested triple time

32*x (mul32) is as following 
32 is $2^5$-> mul32(x)=xtime(xtime(xtime(xtime(xtime (x)))))= xtime(mul16(x)).

133*x = (128+4+1)x = 128*x+ 4*x + x;
= ($2^7 + 2^2 +1$)x = (mul128(x)^xtime(xtime(x))^x) = (mul128(x)^mul4(x))^x)

192= (128+64)x = mul128(x)^mul64(x)
194= (192+2)x =  mul192(x)^xtime(x)

I will let you do the 148 and 251 multiplication, you can use the following code for assistance:

#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;

#define xtime(x)   ((x&lt;&lt;1) ^ (((x&gt;&gt;7) &amp; 1) * 0xc3)) //P: x8⊕x7⊕x6⊕x⊕1
#define mul4(x)    (xtime(xtime(x)))
#define mul8(x)    (xtime(mul4(x)))
#define mul16(x)   (xtime(mul8(x)))

#define mul32(x)      (xtime(mul16(x)))
#define mul64(x)      (xtime(mul32(x)))
#define mul128(x)     (xtime(mul64(x)))&amp;0xFF
#define mul133(x)  (mul128(x)^xtime(xtime(x))^x)&amp;0xFF
#define mul192(x)  mul128(x)^mul64(x)&amp;0xFF
#define mul194(x)  mul192(x)^xtime(x)&amp;0xFF



uint8_t gmul(uint8_t a, uint8_t b) {
    uint8_t p = 0; /* the product of the multiplication */
    while (a &amp;&amp; b) {
            if (b &amp; 1) /* if b is odd, then add the corresponding a to p (final product = sum of all a's corresponding to odd b's) */
                p ^= a; /* since we're in GF(2^m), addition is an XOR */

            if (a &amp; 0x80) /* GF modulo: if a &gt;= 128, then it will overflow when shifted left, so reduce */
                a = (a &lt;&lt; 1) ^ 0x1c3; /* XOR with the primitive polynomial x^8 + x^4 + x^3 + x + 1 (0b1_0001_1011) – you can change it but it must be irreducible */
            else
                a &lt;&lt;= 1; /* equivalent to a*2 */
            b &gt;&gt;= 1; /* equivalent to b // 2 */
    }
    return p;
}

int main(){
    // printf("%x\n",mul16(0x06)&amp;0xFF);
    // printf("%x\n",mul32(0x06)&amp;0xFF);


    // printf("%x\n",mul32(0x22)&amp;0xFF);
    // printf("%x\n",gmul(0x22,32)&amp;0xFF);

    printf("---------\n");
    printf("%x\n",mul128(0xf5)&amp;0xFF);
    printf("%x\n",gmul(0xf5,128)&amp;0xFF);

        printf("---------\n");
    printf("%x\n",mul64(0xf5)&amp;0xFF);
    printf("%x\n",gmul(64,0xf5)&amp;0xFF);

        printf("---------\n");
    printf("%x\n",mul192(0x35)&amp;0xFF);
    printf("%x\n",gmul(192,0x35)&amp;0xFF);

        printf("---------\n");
    printf("%x\n",mul133(0x35)&amp;0xFF);
    printf("%x\n",gmul(133,0x35)&amp;0xFF);

            printf("---------\n");
    printf("%x\n",mul194(0xe5)&amp;0xFF);
    printf("%x\n",gmul(194,0xe5)&amp;0xFF);


    return 0;
}