docs: def rs_correct_errata(msg_in, synd, err_pos, fcr=0, generator=2): # err_pos is a list of the positions of the errors/erasures/errata
      '''Forney algorithm, computes the values (error magnitude) to correct the input message.'''
      global field_charac
      msg = bytearray(msg_in)
      # calculate errata locator polynomial to correct both errors and erasures (by combining the errors positions given by the error locator polynomial found by BM with the erasures positions given by caller)
      coef_pos = [len(msg) - 1 - p for p in err_pos] # need to convert the positions to coefficients degrees for the errata locator algo to work (eg: instead of [0, 1, 2] it will become [len(msg)-1, len(msg)-2, len(msg) -3])
      err_loc = rs_find_errata_locator(coef_pos, generator)
      # calculate errata evaluator polynomial (often called Omega or Gamma in academic papers)
      err_eval = rs_find_error_evaluator(synd[::-1], err_loc, len(err_loc)-1)[::-1]
  
      # Second part of Chien search to get the error location polynomial X from the error positions in err_pos (the roots of the error locator polynomial, ie, where it evaluates to 0)
      X = [] # will store the position of the errors
      for i in xrange(len(coef_pos)):
          l = field_charac - coef_pos[i]
          X.append( gf_pow(generator, -l) )
  
      # Forney algorithm: compute the magnitudes
      E = bytearray(len(msg)) # will store the values that need to be corrected (substracted) to the message containing errors. This is sometimes called the error magnitude polynomial.
      Xlength = len(X)
      for i, Xi in enumerate(X):
  
          Xi_inv = gf_inverse(Xi)
  
          # Compute the formal derivative of the error locator polynomial (see Blahut, Algebraic codes for data transmission, pp 196-197).
          # the formal derivative of the errata locator is used as the denominator of the Forney Algorithm, which simply says that the ith error value is given by error_evaluator(gf_inverse(Xi)) / error_locator_derivative(gf_inverse(Xi)). See Blahut, Algebraic codes for data transmission, pp 196-197.
          err_loc_prime_tmp = []
          for j in xrange(Xlength):
              if j != i:
                  err_loc_prime_tmp.append( gf_sub(1, gf_mul(Xi_inv, X[j])) )
          # compute the product, which is the denominator of the Forney algorithm (errata locator derivative)
          err_loc_prime = 1
          for coef in err_loc_prime_tmp:
              err_loc_prime = gf_mul(err_loc_prime, coef)
          # equivalent to: err_loc_prime = functools.reduce(gf_mul, err_loc_prime_tmp, 1)
  
          # Compute y (evaluation of the errata evaluator polynomial)
          # This is a more faithful translation of the theoretical equation contrary to the old forney method. Here it is exactly copy/pasted from the included presentation decoding_rs.pdf: Yl = omega(Xl.inverse()) / prod(1 - Xj*Xl.inverse()) for j in len(X) (in the paper it's for j in s, but it's useless when len(X) < s because we compute neutral terms 1 for nothing, and wrong when correcting more than s erasures or erasures+errors since it prevents computing all required terms).
          # Thus here this method works with erasures too because firstly we fixed the equation to be like the theoretical one (don't know why it was modified in _old_forney(), if it's an optimization, it doesn't enhance anything), and secondly because we removed the product bound on s, which prevented computing errors and erasures above the s=(n-k)//2 bound.
          y = gf_poly_eval(err_eval[::-1], Xi_inv) # numerator of the Forney algorithm (errata evaluator evaluated)
          y = gf_mul(gf_pow(Xi, 1-fcr), y) # adjust to fcr parameter
          
          # Compute the magnitude
          magnitude = gf_div(y, err_loc_prime) # magnitude value of the error, calculated by the Forney algorithm (an equation in fact): dividing the errata evaluator with the errata locator derivative gives us the errata magnitude (ie, value to repair) the ith symbol
          E[err_pos[i]] = magnitude # store the magnitude for this error into the magnitude polynomial
  
      # Apply the correction of values to get our message corrected! (note that the ecc bytes also gets corrected!)
      # (this isn't the Forney algorithm, we just apply the result of decoding here)
      msg = gf_poly_add(msg, E) # equivalent to Ci = Ri - Ei where Ci is the correct message, Ri the received (senseword) message, and Ei the errata magnitudes (minus is replaced by XOR since it's equivalent in GF(2^p)). So in fact here we substract from the received message the errors magnitude, which logically corrects the value to what it should be.
      return msg