/ erasure_code / share.cpp
share.cpp
 1  #include "share.h"
 2  
 3  // returns a * (x+1) in the Galois field
 4  // (since (x+1) is a primitive root)
 5  static constexpr std::uint8_t tpl(std::uint8_t a) {
 6      return a ^ (a<<1) // a * (x+1)
 7          ^ ((a & (1<<7)) != 0
 8             ? // would overflow (have an x^8 term); reduce by the AES polynomial,
 9               // x^8 + x^4 + x^3 + x + 1
10               0b00011011u
11             : 0
12            );
13  }
14  
15  // constexpr functions to compute exp/log
16  // these are not intended to be fast, but they must be constexpr to populate a
17  // table at compile time
18  static constexpr std::uint8_t gexp(unsigned k) {
19      return k > 0 ? tpl(gexp(k-1)) : 1;
20  }
21  static constexpr std::uint8_t glog(unsigned k, unsigned i = 0, unsigned v = 1) {
22      return k == v ? i : glog(k, i+1, tpl(v));
23  }
24  
25  // insane hack (courtesy of Xeo on stackoverflow): gen_seq<N> expands to a
26  // struct that derives from seq<0, 1, ..., N-1>
27  template<unsigned... I> struct seq{};
28  template<unsigned N, unsigned... I>
29  struct gen_seq : gen_seq<N-1, N-1, I...>{};
30  template<unsigned... I>
31  struct gen_seq<0, I...> : seq<I...>{};
32  
33  // produce the actual tables in array form...
34  template<unsigned... I>
35  constexpr std::array<Galois, 255> exptbl(seq<I...>) {
36      return { { Galois(gexp(I))... } };
37  }
38  template<unsigned... I>
39  constexpr std::array<std::uint8_t, 256> logtbl(seq<I...>) {
40      // manually populate entry zero, for two reasons:
41      // - it makes glog simpler
42      // - it avoids clang++'s default template instantiation depth limit of 256
43      return { { 0, glog(I+1)... } };
44  }
45  
46  // and initialize the static variables
47  const std::array<Galois, 255> Galois::exptable = exptbl(gen_seq<255>{});
48  const std::array<std::uint8_t, 256> Galois::logtable = logtbl(gen_seq<255>{});
49  
50  // by populating everything at compile-time, we avoid a static initialization
51  // step and any possible associated static initialization "races"