// File: ke6jjj[P]r-dat/ECC_C2.cc
// Function: ECC_C2::HandleSyndrome(unsigned char*, unsigned char const*, unsigned long)
bool
ECC_C2::HandleSyndrome(
  uint8_t syndrome[ECC_C2::kTwoT],
  const uint8_t erasures[ECC_C2::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[kTwoT];
  size_t  correction_locations[kTwoT];
  size_t  correction_count = 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[correction_count] = correction;
      correction_locations[correction_count] = loc;
      correction_count++;

      //
      // Update the syndrome with this correction.
      //
      corrected = true;
      for (size_t j = 0; j < kTwoT; j++) {
        syndrome[j] ^= ECC_GF28_multiply(correction, gHq[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 < correction_count; 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 $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x2f(%rbp), %rcx
leaq -0x35(%rbp), %r8
callq 0x99b0
andb $0x1, %al
movb %al, -0x36(%rbp)
testb $0x1, -0x36(%rbp)
jne 0x9703
movb $0x0, -0x1(%rbp)
jmp 0x9911
movq $0x0, -0x78(%rbp)
movb $0x0, -0x79(%rbp)
movq $0x0, -0x88(%rbp)
cmpq $0x20, -0x88(%rbp)
jae 0x9893
movq -0x88(%rbp), %rax
movzbl %al, %edi
callq 0x9380
movzbl %al, %edi
callq 0x92e0
movb %al, -0x89(%rbp)
leaq -0x2f(%rbp), %rdi
movl $0x7, %edx
movzbl -0x89(%rbp), %esi
callq 0x9300
movb %al, -0x8a(%rbp)
movzbl -0x8a(%rbp), %eax
cmpl $0x0, %eax
jne 0x987a
leaq -0x2f(%rbp), %rdi
leaq -0x35(%rbp), %rsi
movzbl -0x89(%rbp), %edx
callq 0x9c90
movb %al, -0x8b(%rbp)
movl $0x20, %eax
subq -0x88(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x98(%rbp)
movb -0x8b(%rbp), %cl
movq -0x78(%rbp), %rax
movb %cl, -0x3c(%rbp,%rax)
movq -0x98(%rbp), %rcx
movq -0x78(%rbp), %rax
movq %rcx, -0x70(%rbp,%rax,8)
movq -0x78(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
movb $0x1, -0x79(%rbp)
movq $0x0, -0xa0(%rbp)
cmpq $0x6, -0xa0(%rbp)
jae 0x9878
movb -0x8b(%rbp), %dl
movq -0xa0(%rbp), %rcx
leaq 0x5ff4(%rip), %rax      # 0xf7f0
shlq $0x5, %rcx
addq %rcx, %rax
movq -0x98(%rbp), %rcx
movzbl %dl, %edi
movzbl (%rax,%rcx), %esi
callq 0x9250
movzbl %al, %esi
movq -0x18(%rbp), %rax
movq -0xa0(%rbp), %rcx
movzbl (%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, (%rax,%rcx)
xorl %eax, %eax
testb $0x1, -0x79(%rbp)
movb %al, -0xc1(%rbp)
je 0x9856
movq -0x18(%rbp), %rax
movq -0xa0(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x0, %eax
sete %al
movb %al, -0xc1(%rbp)
movb -0xc1(%rbp), %al
andb $0x1, %al
movb %al, -0x79(%rbp)
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0x97da
jmp 0x987a
jmp 0x987c
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x88(%rbp)
jmp 0x971a
testb $0x1, -0x79(%rbp)
je 0x9909
movq $0x0, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
cmpq -0x78(%rbp), %rax
jae 0x9907
movq -0xc0(%rbp), %rax
movq -0xa8(%rbp), %rcx
movq -0x70(%rbp,%rcx,8), %rcx
movq %rcx, -0xb0(%rbp)
movq -0xa8(%rbp), %rcx
movb -0x3c(%rbp,%rcx), %cl
movb %cl, -0xb1(%rbp)
movzbl -0xb1(%rbp), %esi
movq -0xb0(%rbp), %rcx
movzbl (%rax,%rcx), %edx
xorl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0xa8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa8(%rbp)
jmp 0x98a4
jmp 0x9909
movb -0x79(%rbp), %al
andb $0x1, %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xd0, %rsp
popq %rbp
retq
nop