galois-field.hpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #pragma once
  2. //table-driven galois field modulo 2
  3. //do not use with GF(2^17) or larger
  4. namespace nall {
  5. template<typename field, uint Elements, uint Polynomial>
  6. struct GaloisField {
  7. using type = GaloisField;
  8. GaloisField(uint x = 0) : x(x) {}
  9. operator field() const { return x; }
  10. auto operator^(field y) const -> type { return x ^ y; }
  11. auto operator+(field y) const -> type { return x ^ y; }
  12. auto operator-(field y) const -> type { return x ^ y; }
  13. auto operator*(field y) const -> type { return x && y ? exp(log(x) + log(y)) : 0; }
  14. auto operator/(field y) const -> type { return x && y ? exp(log(x) + Elements - log(y)) : 0; }
  15. auto& operator =(field y) { return x = y, *this; }
  16. auto& operator^=(field y) { return x = operator^(y), *this; }
  17. auto& operator+=(field y) { return x = operator^(y), *this; }
  18. auto& operator-=(field y) { return x = operator^(y), *this; }
  19. auto& operator*=(field y) { return x = operator*(y), *this; }
  20. auto& operator/=(field y) { return x = operator/(y), *this; }
  21. auto pow(field y) const -> type { return exp(log(x) * y); }
  22. auto inv() const -> type { return exp(Elements - log(x)); } // 1/x
  23. static auto log(uint x) -> uint {
  24. enum : uint { Size = bit::round(Elements), Mask = Size - 1 };
  25. static array<field[Size]> log = [] {
  26. uint shift = 0, polynomial = Polynomial;
  27. while(polynomial >>= 1) shift++;
  28. shift--;
  29. array<field[Size]> log;
  30. field x = 1;
  31. for(uint n : range(Elements)) {
  32. log[x] = n;
  33. x = x << 1 ^ (x >> shift ? Polynomial : 0);
  34. }
  35. log[0] = 0; //-inf (undefined)
  36. return log;
  37. }();
  38. return log[x & Mask];
  39. }
  40. static auto exp(uint x) -> uint {
  41. static array<field[Elements]> exp = [] {
  42. uint shift = 0, polynomial = Polynomial;
  43. while(polynomial >>= 1) shift++;
  44. shift--;
  45. array<field[Elements]> exp;
  46. field x = 1;
  47. for(uint n : range(Elements)) {
  48. exp[n] = x;
  49. x = x << 1 ^ (x >> shift ? Polynomial : 0);
  50. }
  51. return exp;
  52. }();
  53. return exp[x % Elements];
  54. }
  55. field x;
  56. };
  57. }