1

"The number of elements of a finite field is called its order or, sometimes, its size. A finite field of order $q$ exists if and only if $q$ is a prime power $p^k$ (where $p$ is a prime number and $k$ is a positive integer). In a field of order $p^k$, adding $p$ copies of any element always results in zero; that is, the characteristic of the field is $p$." https://en.wikipedia.org/wiki/Finite_field#Propeties.

So, I just tried to to take for example an element ($0001$) in $GF(16)$, which is $GF(2^4)$ and add it to itself, which results in $0001$ + $0001$ = $0010$, which doesn't result in 0. But I do notice that if you ignore the carry, it does result in 0, but if I do need to ignore the carry, why is it still under $GF(16)$?

When doing such adding, do I need to relate to each bit separately? Thank You!

Bernard
  • 175,478
  • 2
    Yes, you add each bit separately using 0+0=0, 0+1=1, 1+0=1, 1+1=0. As @Gae. S. says this is also called XOR. – Jack Schmidt May 18 '21 at 13:22
  • 1
    FWIW, you can do finite field arithmetic in Sage, see here for details. Here's a demo that prints addition & multiplication tables. – PM 2Ring May 19 '21 at 05:54
  • 1
    You can also study one of the tables in an old answer of mine, prepared with referrals like this in mind. Your $0001$ is what I call $1$, your $0010$ is $\gamma$ there, $0100$ is $\gamma^2$ and $1000$ is renamed $\gamma^3$. The addition is, as others explained, bitwise XOR. So your $1011$ is the element $\gamma^3+\gamma+1$ of my table. – Jyrki Lahtonen May 19 '21 at 16:30

3 Answers3

5

If you represent $GF(2^n)$ as the set of strings of $n$ BITs, then the sum is not the sum as binary numbers, but the XOR. This corresponds to identifying the string $\{a_{n-1}a_{n-1}\cdots a_0\}$ with the polynomial expression $\sum_{k=0}^{n-1}a_kX^k$ in the quotient ring $GF(2)[X]/(\mu(X))$, where $\mu(X)\in GF(2)[X]$ irreducible of degree $n$. This also tells you that product is a bit more complicated, because it requires to do all the shifts but followed by a polynomial long division.

See Wikipedia for a quick summary.

0

A finite field requires a prime $p$. I'll assume you want $p=2$. Then you also need a power $d$ in order to do the addition. Numbers in the field are just lists of numbers -- the list has length $d$ and each entry in the list is one of the numbers $0$, $1$, ..., all the way up to $p-1$. I'll assume you want $d=4$. This means the elements of the field are:

  • $(0,0,0,0)$,
  • $(0,0,0,1)$,
  • $(0,0,1,0)$,
  • ...
  • $(1,1,1,1)$

When $p=2$ more or less everyone agrees it is a good idea to think of these lists (of bits) as binary numbers and at this point it doesn't matter much which order you think of the bits. I wrote them as MSB-first, so:

  • $(0,0,0,0)$ = 0b0000 = 0 = 0x0
  • $(0,0,0,1)$ = 0b0001 = 1 = 0x1
  • $(0,0,1,0)$ = 0b0010 = 2 = 0x2
  • ...
  • $(1,1,1,1)$ = 0b1111 = 15 = 0xf

but when you add, you are just adding the numbers in the list, not the real binary number. Luckily computers are very quick at this (quicker than addition on smaller computers where there is a difference) because this is called XOR and it can ignore the carry, just like you suspected. Also if you don't like MSB-first, then luckily addition doesn't care what order you want the bits as long as you are consistent with yourself.

Multiplication is a little more complicated and larger computers now have instructions meant to speed this up. I'll use an old technique that can help you understand some related ideas in computer science.

But now we need to know more than just the size $d$ of the lists. We need to choose a specific field element to be a sort of "carry" for multiplying.

I'll choose 0x3 as my carry (you could use 0x9 or 0xf too). No matter the $d$, it helps to understand multiplying by 0x2 first. Much like regular numbers, multiplying by two can use the faster instruction n << 1 that shifts the bits to the left. However, in a field you need to be able to divide too, and if you shift to the left too much all the bits disappear! So like with addition finite fields change the rules ever so slightly, but this time they INCLUDE a carry while normally n << 1 does not. If the highest bit is set, n & 0x8, then shifting it left normally would lose it (take it outside the field), so instead of leaving that leftmost bit (which would be 0x10 now, too big for the field), we replace it with the carry. You can XOR by 0x13 if you keep track of that outside bit (0x10 ^ 0x13 is just 0x03), or just XOR by 0x03 if you ignore the higher bits (easier to do when d=8, d=16, d=32, or d=64).

So "multiply by 0x2" is (n<<1)^((n&0x8)?0x13:0x00). Multiply by 0x1 is easy: just leave it alone (just like a regular number 1*7 = 7, the 1 doesn't change anything).

To multiply by a general number we multiply by each of the bits. So to multiply by 0x6 we write 0x6 = 0x4 ^ 0x2 and then distribute to get "multiply by 0x4 and xor it with the answer you get when xor'ing by 0x2".

int multiply(int a,int b) {
  int ret = 0; // start with nothing to return, we'll add in as we go

if (b&1) ret ^= a; // multiply by 1 means "keep n"

b >>= 1; // done with least bit, scoot the multiplier bits over to the right a = (a<<1)^((a&0x8)?0x13:0x00); // multiply by 2, including the carry if (b&1) ret ^= a; // since we've changed b, this is really the multiply by 2, but we've already changed a, so it uses the same code as multiply by 1, so smart

b >>= 1; a = (a<<1)^((a&0x8)?0x13:0x00); if (b&1) ret ^= a; // this handles b & 0x4

b >>= 1; a = (a<<1)^((a&0x8)?0x13:0x00); if (b&1) ret ^= a; // this handles b & 0x8

assert(b<2); // no more bits for you! return ret; }

To use a different carry for multiply by 0x2 you just change the 0x13 to 0x19 or 0x1f. As @Gae. S. mentions, these are the irreducible polynomials of degree 4 over GF(2).

Bit order matters for multiplication, but luckily whether people use MSB or LSB, they usually use the same code above (if they swap what order they write down binary numbers, they also swap what order they write down polynomials, and so in the code it becomes the same except for printing).

Jack Schmidt
  • 55,589
0

${GF(2^4)}$ is a Galois Field. The concept of field/ring/group is that all the operation you do on them will remain within them.

  • Here,As they are elements of Field you can write 1 as ('1000' or '0001'), now you want to produce the elements of field, for ex. multiplicative field generated by prime 7 contains (1,2,3,4,5,6} , which is ${mod7}$ operation.
  • Let's do it with one of the irreducible polynomial in ${GF(2^4)}$, ${h(x)=1+x+x^4}$
  • The elements are ${\{0,1,x,x^2,x^3,x^4=1+x,x^5=x+x^2,... ,x^{14}=1+x^3}\}$, every time one should take ${mod(h(x))}$, when multiplying x with previous element. i.e., ${x^i mod (h(x))}$, where ${i=0,1,..,2^{n-2}}$ and you can represent them by word for ex. in our case ${\{0000,0001,0010=x,0100=x^2,...,1001= 1+x^3}\}$, and wit ${x^{15}=1 mod(h(x))}$ back to the first element if field is multiplicative.
  • Also According,Fermet's Last Theorem ${x^{p-1}= 1 mod(p)}$, where p is prime or in our case irreducible polynomial ${h(x)}$
  • All we've to remember is whatever operation we do in the field will remain within the field (among 16 elements of it) as we work on ${mod(h(x))}$ an irreducible polynomial or prime number.
SSA
  • 364