package com.foxx.androidcast.network.transport.fec;

/*********************************************************************
 * GaloisField.java
 * Created at: Sun 17 May 2026 22:49:49 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (2 commits, 70 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	03db14e672d69bcc8be9a67a3dfdd09799b4f96c95c09c856bedba70e51de212
**********************************************************************/
/** GF(2^8) arithmetic for Reed-Solomon. */
final class GaloisField {
    private static final int[] EXP = new int[512];
    private static final int[] LOG = new int[256];

    static {
        int x = 1;
        for (int i = 0; i < 255; i++) {
            EXP[i] = x;
            LOG[x] = i;
            x <<= 1;
            if ((x & 0x100) != 0) {
                x ^= 0x11D;
            }
        }
        for (int i = 255; i < 512; i++) {
            EXP[i] = EXP[i - 255];
        }
    }

    private GaloisField() {}

    static int add(int a, int b) {
        return a ^ b;
    }

    static int mul(int a, int b) {
        if (a == 0 || b == 0) {
            return 0;
        }
        return EXP[LOG[a] + LOG[b]];
    }

    static int div(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("divide by zero");
        }
        if (a == 0) {
            return 0;
        }
        return EXP[(LOG[a] - LOG[b] + 255) % 255];
    }

    static int pow(int a, int power) {
        if (power == 0) {
            return 1;
        }
        if (a == 0) {
            return 0;
        }
        return EXP[(LOG[a] * power) % 255];
    }

    static void mulAddInto(byte[] dst, byte[] src, int coeff) {
        if (coeff == 0) {
            return;
        }
        for (int i = 0; i < dst.length && i < src.length; i++) {
            dst[i] ^= mul(src[i] & 0xFF, coeff);
        }
    }
}
