// File: ke6jjj[P]r-dat/./ReedSolomon_EUA.h
// Function: bool RS_Solve<2ul>(unsigned char const*, unsigned char const*, unsigned long, unsigned char (&) [2 * 2ul + 1], unsigned char (&) [2 * 2ul])
bool
RS_Solve(const uint8_t syndrome[2*kT], const uint8_t erasures[2*kT],
  size_t erasure_count, uint8_t (&r_sigma)[2*kT+1], uint8_t (&r_omega)[2*kT])
{
  const size_t kTwoT = kT * 2;
  uint8_t U[kTwoT+1];
  uint8_t V[kTwoT+1];
  uint8_t W[kTwoT+1];
  uint8_t X[kTwoT+1];
  
  for (size_t i = 0; i < kTwoT; i++) {
    //
    // Clear out the parts of the big polynomials that will not
    // be otherwise initialized.
    //
    X[i+1] = 0;    
    W[i+1] = 0;
    U[i] = 0;

    //
    // Copy in the syndrome value.
    //
    V[i] = syndrome[i];
  }
  
  U[kTwoT] = 1;
  V[kTwoT] = 0;
  X[0] = 1;
  W[0] = 0;
  int D = -1;
  size_t p = 0;
  
  for (size_t i = 0; i < kTwoT; i++) {
    //
    // During the first phase of this algorithm, we incorporate erasures.
    // Determine if we're still in erasure-processing phase.
    //
    bool first = (p < erasure_count);
    
    //
    // Next we determine if the Euclidean algorithm requires us to swap
    // the parameters being processed.
    //
    bool swap = !first && (V[kTwoT - 1] != 0) && (D < 0);
    
    //
    // Examine the next element to be processed. In the erasures
    // phase we pull in the next erasure locator. In the error locator
    // phase we pull in the next thingamjig.
    //
    uint8_t G, Z;
    if (first) {
      //
      // Erasures processing. Get next erasure symbol and convert it
      // into a power of alpha.
      //
      G = ECC_GF28_pow_alpha(erasures[p++]);
      Z = 1;
    } else {
      //
      // Done with erasures. Get a thingamjig.
      //
      G = U[kTwoT];
      Z = V[kTwoT-1];
    }
    
    if (swap) {
      D = -D - 1;
    } else if (!first) {
      D = D - 1;
    }
    
    uint8_t v_adjust[kTwoT+1];
    uint8_t x_adjust[kTwoT+1];
    if (first) {
      poly_multiply_scalar<kTwoT+1>(V, Z, v_adjust);
      poly_multiply_scalar<kTwoT+1>(X, Z, x_adjust);
    } else {
      poly_multiply_scalar<kTwoT+1>(U, Z, v_adjust);
      poly_multiply_scalar<kTwoT+1>(W, Z, x_adjust);
    }
    
    //
    // Compute z V(z) and
    //         z X(z)
    //
    uint8_t new_V[kTwoT+1];
    uint8_t new_X[kTwoT+1];

    poly_multiply_by_x<kTwoT+1>(V, new_V);
    poly_multiply_by_x<kTwoT+1>(X, new_X);

    //
    // Compute G z V(z) and
    //         G z X(z)
    //
    poly_multiply_scalar<kTwoT+1>(new_V, G, new_V);
    poly_multiply_scalar<kTwoT+1>(new_X, G, new_X);
    
    poly_add<kTwoT+1>(new_V, v_adjust, new_V);
    poly_add<kTwoT+1>(new_X, x_adjust, new_X);
    
    if (swap) {
      poly_multiply_by_x<kTwoT+1>(V, U);
      poly_multiply_by_x<kTwoT+1>(X, W);
    }
    
    poly_copy<kTwoT+1>(new_V, V);
    poly_copy<kTwoT+1>(new_X, X);
  }

  if (D < 0 && (p == erasure_count)) {
    //
    // Everything should be correctable.
    // Return the location polynomial and the magnitude polynomial.
    //
    poly_copy<kTwoT+1>(X, r_sigma);
    for (size_t i = 0; i < kTwoT; i++)
      r_omega[i] = V[i];
    
    return true;
  }
  
  return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq $0x4, -0x38(%rbp)
movq $0x0, -0x58(%rbp)
cmpq $0x4, -0x58(%rbp)
jae 0x87d2
movq -0x58(%rbp), %rax
movb $0x0, -0x4b(%rbp,%rax)
movq -0x58(%rbp), %rax
movb $0x0, -0x46(%rbp,%rax)
movq -0x58(%rbp), %rax
movb $0x0, -0x3d(%rbp,%rax)
movq -0x10(%rbp), %rax
movq -0x58(%rbp), %rcx
movb (%rax,%rcx), %cl
movq -0x58(%rbp), %rax
movb %cl, -0x42(%rbp,%rax)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x878f
movb $0x1, -0x39(%rbp)
movb $0x0, -0x3e(%rbp)
movb $0x1, -0x4c(%rbp)
movb $0x0, -0x47(%rbp)
movl $0xffffffff, -0x5c(%rbp) # imm = 0xFFFFFFFF
movq $0x0, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
cmpq $0x4, -0x70(%rbp)
jae 0x89af
movq -0x68(%rbp), %rax
cmpq -0x20(%rbp), %rax
setb %al
andb $0x1, %al
movb %al, -0x71(%rbp)
xorl %eax, %eax
testb $0x1, -0x71(%rbp)
movb %al, -0x91(%rbp)
jne 0x8840
movzbl -0x3f(%rbp), %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x91(%rbp)
je 0x8840
cmpl $0x0, -0x5c(%rbp)
setl %al
movb %al, -0x91(%rbp)
movb -0x91(%rbp), %al
andb $0x1, %al
movb %al, -0x72(%rbp)
testb $0x1, -0x71(%rbp)
je 0x8876
movq -0x18(%rbp), %rax
movq -0x68(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x68(%rbp)
movzbl (%rax,%rcx), %edi
callq 0x9380
movb %al, -0x73(%rbp)
movb $0x1, -0x74(%rbp)
jmp 0x8882
movb -0x39(%rbp), %al
movb %al, -0x73(%rbp)
movb -0x3f(%rbp), %al
movb %al, -0x74(%rbp)
testb $0x1, -0x72(%rbp)
je 0x8895
xorl %eax, %eax
subl -0x5c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x88a6
testb $0x1, -0x71(%rbp)
jne 0x88a4
movl -0x5c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x88a6
testb $0x1, -0x71(%rbp)
je 0x88d0
leaq -0x42(%rbp), %rdi
leaq -0x79(%rbp), %rdx
movzbl -0x74(%rbp), %esi
callq 0x8b00
leaq -0x4c(%rbp), %rdi
leaq -0x7e(%rbp), %rdx
movzbl -0x74(%rbp), %esi
callq 0x8b00
jmp 0x88f2
leaq -0x3d(%rbp), %rdi
leaq -0x79(%rbp), %rdx
movzbl -0x74(%rbp), %esi
callq 0x8b00
leaq -0x47(%rbp), %rdi
leaq -0x7e(%rbp), %rdx
movzbl -0x74(%rbp), %esi
callq 0x8b00
leaq -0x42(%rbp), %rdi
leaq -0x83(%rbp), %rsi
callq 0x8b60
leaq -0x4c(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x8b60
leaq -0x83(%rbp), %rdx
movq %rdx, %rdi
movzbl -0x73(%rbp), %esi
callq 0x8b00
leaq -0x88(%rbp), %rdx
movq %rdx, %rdi
movzbl -0x73(%rbp), %esi
callq 0x8b00
leaq -0x83(%rbp), %rdx
leaq -0x79(%rbp), %rsi
movq %rdx, %rdi
callq 0x8bb0
leaq -0x88(%rbp), %rdx
leaq -0x7e(%rbp), %rsi
movq %rdx, %rdi
callq 0x8bb0
testb $0x1, -0x72(%rbp)
je 0x897e
leaq -0x42(%rbp), %rdi
leaq -0x3d(%rbp), %rsi
callq 0x8b60
leaq -0x4c(%rbp), %rdi
leaq -0x47(%rbp), %rsi
callq 0x8b60
leaq -0x83(%rbp), %rdi
leaq -0x42(%rbp), %rsi
callq 0x8c10
leaq -0x88(%rbp), %rdi
leaq -0x4c(%rbp), %rsi
callq 0x8c10
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x70(%rbp)
jmp 0x87f9
cmpl $0x0, -0x5c(%rbp)
jge 0x8a14
movq -0x68(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x8a14
movq -0x28(%rbp), %rsi
leaq -0x4c(%rbp), %rdi
callq 0x8c10
movq $0x0, -0x90(%rbp)
cmpq $0x4, -0x90(%rbp)
jae 0x8a0e
movq -0x90(%rbp), %rax
movb -0x42(%rbp,%rax), %dl
movq -0x30(%rbp), %rax
movq -0x90(%rbp), %rcx
movb %dl, (%rax,%rcx)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x89d7
movb $0x1, -0x1(%rbp)
jmp 0x8a18
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)