docs: def find_prime_polys(generator=2, c_exp=8, fast_primes=False, single=False):
      '''Compute the list of prime polynomials for the given generator and galois field characteristic exponent.'''
      # fast_primes will output less results but will be significantly faster.
      # single will output the first prime polynomial found, so if all you want is to just find one prime polynomial to generate the LUT for Reed-Solomon to work, then just use that.
  
      # A prime polynomial (necessarily irreducible) is necessary to reduce the multiplications in the Galois Field, so as to avoid overflows.
      # Why do we need a "prime polynomial"? Can't we just reduce modulo 255 (for GF(2^8) for example)? Because we need the values to be unique.
      # For example: if the generator (alpha) = 2 and c_exp = 8 (GF(2^8) == GF(256)), then the generated Galois Field (0, 1, α, α^1, α^2, ..., α^(p-1)) will be galois field it becomes 0, 1, 2, 4, 8, 16, etc. However, upon reaching 128, the next value will be doubled (ie, next power of 2), which will give 256. Then we must reduce, because we have overflowed above the maximum value of 255. But, if we modulo 255, this will generate 256 == 1. Then 2, 4, 8, 16, etc. giving us a repeating pattern of numbers. This is very bad, as it's then not anymore a bijection (ie, a non-zero value doesn't have a unique index). That's why we can't just modulo 255, but we need another number above 255, which is called the prime polynomial.
      # Why so much hassle? Because we are using precomputed look-up tables for multiplication: instead of multiplying a*b, we precompute alpha^a, alpha^b and alpha^(a+b), so that we can just use our lookup table at alpha^(a+b) and get our result. But just like in our original field we had 0,1,2,...,p-1 distinct unique values, in our "LUT" field using alpha we must have unique distinct values (we don't care that they are different from the original field as long as they are unique and distinct). That's why we need to avoid duplicated values, and to avoid duplicated values we need to use a prime irreducible polynomial.
  
      # Here is implemented a bruteforce approach to find all these prime polynomials, by generating every possible prime polynomials (ie, every integers between field_charac+1 and field_charac*2), and then we build the whole Galois Field, and we reject the candidate prime polynomial if it duplicates even one value or if it generates a value above field_charac (ie, cause an overflow).
      # Note that this algorithm is slow if the field is too big (above 12), because it's an exhaustive search algorithm. There are probabilistic approaches, and almost surely prime approaches, but there is no determistic polynomial time algorithm to find irreducible monic polynomials. More info can be found at: http://people.mpi-inf.mpg.de/~csaha/lectures/lec9.pdf
      # Another faster algorithm may be found at Adleman, Leonard M., and Hendrik W. Lenstra. "Finding irreducible polynomials over finite fields." Proceedings of the eighteenth annual ACM symposium on Theory of computing. ACM, 1986.
  
      # Prepare the finite field characteristic (2^p - 1), this also represent the maximum possible value in this field
      root_charac = 2 # we're in GF(2)
      field_charac = int(root_charac**c_exp - 1)
      field_charac_next = int(root_charac**(c_exp+1) - 1)
  
      prim_candidates = []
      if fast_primes:
          prim_candidates = rwh_primes1(field_charac_next) # generate maybe prime polynomials and check later if they really are irreducible
          prim_candidates = [x for x in prim_candidates if x > field_charac] # filter out too small primes
      else:
          prim_candidates = xrange(field_charac+2, field_charac_next, root_charac) # try each possible prime polynomial, but skip even numbers (because divisible by 2 so necessarily not irreducible)
  
      # Start of the main loop
      correct_primes = []
      for prim in prim_candidates: # try potential candidates primitive irreducible polys
          seen = bytearray(field_charac+1) # memory variable to indicate if a value was already generated in the field (value at index x is set to 1) or not (set to 0 by default)
          conflict = False # flag to know if there was at least one conflict
  
          # Second loop, build the whole Galois Field
          x = 1
          for i in xrange(field_charac):
              # Compute the next value in the field (ie, the next power of alpha/generator)
              x = gf_mult_noLUT(x, generator, prim, field_charac+1)
  
              # Rejection criterion: if the value overflowed (above field_charac) or is a duplicate of a previously generated power of alpha, then we reject this polynomial (not prime)
              if x > field_charac or seen[x] == 1:
                  conflict = True
                  break
              # Else we flag this value as seen (to maybe detect future duplicates), and we continue onto the next power of alpha
              else:
                  seen[x] = 1
  
          # End of the second loop: if there's no conflict (no overflow nor duplicated value), this is a prime polynomial!
          if not conflict: 
              correct_primes.append(prim)
              if single: return prim
  
      # Return the list of all prime polynomials
      return correct_primes