#pragma once

#include <cstdint>
#include <cstddef>
#include <vector>

namespace paritypp {

// Galois Field GF(2^8) arithmetic using primitive polynomial x^8 + x^4 + x^3 + x^2 + 1 (0x11d)
class galois {
public:
    static void init();

    static uint8_t add(uint8_t a, uint8_t b);
    static uint8_t sub(uint8_t a, uint8_t b);
    static uint8_t mul(uint8_t a, uint8_t b);
    static uint8_t div(uint8_t a, uint8_t b);
    static uint8_t pow(uint8_t a, uint8_t n);
    static uint8_t inv(uint8_t a);

    // Bulk operations on data regions
    static void mul_region(uint8_t* dst, const uint8_t* src, uint8_t coeff, size_t len);
    static void addmul_region(uint8_t* dst, const uint8_t* src, uint8_t coeff, size_t len);

private:
    static uint8_t exp_table[512];
    static uint8_t log_table[256];
    static bool initialized;
};

} // namespace paritypp
