void ReedSolomonDecoder::decode(ArrayRef<int> received, int twoS) {

  Ref<GenericGFPoly> poly(new GenericGFPoly(field, received));


#ifdef DEBUG
  cout << "decoding with poly " << *poly << "\n";
#endif

  ArrayRef<int> syndromeCoefficients(new Array<int> (twoS));


#ifdef DEBUG
  cout << "syndromeCoefficients array = " <<
       syndromeCoefficients.array_ << "\n";
#endif

  bool dataMatrix = (field.object_ == GenericGF::DATA_MATRIX_FIELD_256.object_);
  bool noError = true;
  for (int i = 0; i < twoS; i++) {
    int eval = poly->evaluateAt(field->exp(dataMatrix ? i + 1 : i));
    syndromeCoefficients[syndromeCoefficients->size() - 1 - i] = eval;
    if (eval != 0) {
      noError = false;
    }
  }
  if (noError) {
    return;
  }

  Ref<GenericGFPoly> syndrome(new GenericGFPoly(field, syndromeCoefficients));
  Ref<GenericGFPoly> monomial = field->buildMonomial(twoS, 1);
  vector<Ref<GenericGFPoly> > sigmaOmega = runEuclideanAlgorithm(monomial, syndrome, twoS);
  ArrayRef<int> errorLocations = findErrorLocations(sigmaOmega[0]);
  ArrayRef<int> errorMagitudes = findErrorMagnitudes(sigmaOmega[1], errorLocations, dataMatrix);
  for (unsigned i = 0; i < errorLocations->size(); i++) {
    int position = received->size() - 1 - field->log(errorLocations[i]);
    //TODO: check why the position would be invalid
    if (position < 0 || (size_t)position >= received.size())
      throw IllegalArgumentException("Invalid position (ReedSolomonDecoder)");
    received[position] = GenericGF::addOrSubtract(received[position], errorMagitudes[i]);
  }
}
  void ReedSolomonDecoder::decode(ArrayRef<int> received, int twoS) {
    
    Ref<GF256Poly> poly(new GF256Poly(field, received));
    
#ifdef DEBUG
    cout << "decoding with poly " << *poly << "\n";
#endif
    
    ArrayRef<int> syndromeCoefficients(new Array<int>(twoS));
    
#ifdef DEBUG
    cout << "syndromeCoefficients array = " << 
      syndromeCoefficients.array_ << "\n";
#endif
    
    bool noError = true;
    for (int i = 0; i < twoS; i++) {
      int eval = poly->evaluateAt(field.exp(i));
      syndromeCoefficients[syndromeCoefficients->size() - 1 - i] = eval;
      if (eval != 0) {
        noError = false;
      }
    }
    if (noError) {
      return;
    }

    Ref<GF256Poly> syndrome(new GF256Poly(field, syndromeCoefficients));
    Ref<GF256Poly> monomial(field.buildMonomial(twoS, 1));
    vector<Ref<GF256Poly> > sigmaOmega
      (runEuclideanAlgorithm(monomial, syndrome, twoS));
    ArrayRef<int> errorLocations = findErrorLocations(sigmaOmega[0]);
    ArrayRef<int> errorMagitudes = findErrorMagnitudes(sigmaOmega[1],
                                                       errorLocations);
    for (unsigned i = 0; i < errorLocations->size(); i++) {
      int position = received->size() - 1 - field.log(errorLocations[i]);
      received[position] = GF256::addOrSubtract(received[position],
                                                errorMagitudes[i]);
    }
  }