// File: ke6jjj[P]r-dat/ECC_C1.cc
// Function: ECC_C1::HandleSyndrome(unsigned char*, unsigned char const*, unsigned long)
bool
ECC_C1::HandleSyndrome(
  uint8_t syndrome[ECC_C1::kTwoT],
  const uint8_t erasures[ECC_C1::kTwoT],
  size_t numErasures)
{
  uint8_t locator[kTwoT+1], magnitude[kTwoT];
  
  //
  // Run the extended Euclidean algorithm, with erasures, to find the
  // error locator polynomial and the error magnitude polynomial.
  //
  bool correctable = RS_Solve<kT>(syndrome, erasures, numErasures, locator,
                                 magnitude);
  if (!correctable)
    return false;
  
  //
  // The errors should be correctable. Find the error locations by
  // testing roots of the error locator polynomial. Only test those
  // roots that correspond to locations in the code word.
  //
  uint8_t corrections[ECC_C1::kTwoT];
  size_t  correction_locations[ECC_C1::kTwoT];
  mCorrectionCount = 0;
  bool corrected = false;

  for (size_t i = 0; i < kN; i++) {
    //
    // Compute alpha^(-i)
    //
    uint8_t alpha_inv = ECC_GF28_invert(ECC_GF28_pow_alpha(i));
    
    //
    // Compute locator(alpha^(-i)).
    //
    uint8_t res = ECC_GF28_evaluate(locator, alpha_inv, kTwoT+1);

    //
    // If the result is zero then this location, i, has an error that
    // we can fix.
    //
    if (res == 0) {
      //
      // There's an error at this position. Use Forney's formula to
      // calculate the error value.
      //
      uint8_t correction = RS_GetErrorAtLocation<kT>(
        locator,
        magnitude,
        alpha_inv
      );
     
      //
      // The locations derived from this algorithm are relative
      // to the lowest-order element of the code word. This is
      // the opposite order that we store the codeword in memory.
      // Translate the algorithmic location to the memory location.
      // 
      size_t loc = kN - i - 1;

      //
      // Mark that there's a correction at this location.
      // 
      corrections[mCorrectionCount] = correction;
      correction_locations[mCorrectionCount] = loc;
      mCorrectionCount++;

      //
      // Update the syndrome with this correction.
      //
      corrected = true;
      for (size_t j = 0; j < kTwoT; j++) {
        syndrome[j] ^= ECC_GF28_multiply(correction, gHp[j][loc]);
        corrected = corrected && syndrome[j] == 0;
      }
    }
  }

  //
  // Do the planned corrections fix the syndrome completely?
  //
  if (corrected) {
    //
    // Yes. The planned corrections fix the syndrome. Let's
    // apply them.
    //
    for (size_t i = 0; i < mCorrectionCount; i++) {
      size_t location = correction_locations[i];
      uint8_t correction = corrections[i];

      //
      // Apply this correction.
      //
      mData[location] ^= correction;
    }
  }
  
  //
  // If the corrections didn't fix the problem then we have an uncorrectable
  // error syndrome.
  //
  return corrected;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x2d(%rbp), %rcx
leaq -0x31(%rbp), %r8
callq 0x8760
andb $0x1, %al
movb %al, -0x32(%rbp)
testb $0x1, -0x32(%rbp)
jne 0x84c3
movb $0x0, -0x1(%rbp)
jmp 0x86b4
movq -0xa8(%rbp), %rax
movl $0x0, 0x40(%rax)
movb $0x0, -0x61(%rbp)
movq $0x0, -0x70(%rbp)
cmpq $0x20, -0x70(%rbp)
jae 0x862c
movq -0x70(%rbp), %rax
movzbl %al, %edi
callq 0x9380
movzbl %al, %edi
callq 0x92e0
movb %al, -0x71(%rbp)
leaq -0x2d(%rbp), %rdi
movl $0x5, %edx
movzbl -0x71(%rbp), %esi
callq 0x9300
movb %al, -0x72(%rbp)
movzbl -0x72(%rbp), %eax
cmpl $0x0, %eax
jne 0x8619
leaq -0x2d(%rbp), %rdi
leaq -0x31(%rbp), %rsi
movzbl -0x71(%rbp), %edx
callq 0x8a30
movb %al, %cl
movq -0xa8(%rbp), %rax
movb %cl, -0x73(%rbp)
movl $0x20, %ecx
subq -0x70(%rbp), %rcx
subq $0x1, %rcx
movq %rcx, -0x80(%rbp)
movb -0x73(%rbp), %dl
movslq 0x40(%rax), %rcx
movb %dl, -0x36(%rbp,%rcx)
movq -0x80(%rbp), %rdx
movslq 0x40(%rax), %rcx
movq %rdx, -0x60(%rbp,%rcx,8)
movl 0x40(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x40(%rax)
movb $0x1, -0x61(%rbp)
movq $0x0, -0x88(%rbp)
cmpq $0x4, -0x88(%rbp)
jae 0x8617
movb -0x73(%rbp), %dl
movq -0x88(%rbp), %rcx
leaq 0x6ea2(%rip), %rax      # 0xf440
shlq $0x5, %rcx
addq %rcx, %rax
movq -0x80(%rbp), %rcx
movzbl %dl, %edi
movzbl (%rax,%rcx), %esi
callq 0x9250
movzbl %al, %esi
movq -0x18(%rbp), %rax
movq -0x88(%rbp), %rcx
movzbl (%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, (%rax,%rcx)
xorl %eax, %eax
testb $0x1, -0x61(%rbp)
movb %al, -0xa9(%rbp)
je 0x85f5
movq -0x18(%rbp), %rax
movq -0x88(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x0, %eax
sete %al
movb %al, -0xa9(%rbp)
movb -0xa9(%rbp), %al
andb $0x1, %al
movb %al, -0x61(%rbp)
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x88(%rbp)
jmp 0x857f
jmp 0x8619
jmp 0x861b
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x70(%rbp)
jmp 0x84dd
testb $0x1, -0x61(%rbp)
je 0x86ac
movq $0x0, -0x90(%rbp)
movq -0xa8(%rbp), %rcx
movq -0x90(%rbp), %rax
movslq 0x40(%rcx), %rcx
cmpq %rcx, %rax
jae 0x86aa
movq -0xa8(%rbp), %rax
movq -0x90(%rbp), %rcx
movq -0x60(%rbp,%rcx,8), %rcx
movq %rcx, -0x98(%rbp)
movq -0x90(%rbp), %rcx
movb -0x36(%rbp,%rcx), %cl
movb %cl, -0x99(%rbp)
movzbl -0x99(%rbp), %esi
movq -0x98(%rbp), %rcx
movzbl (%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x863d
jmp 0x86ac
movb -0x61(%rbp), %al
andb $0x1, %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)