// File: marxn[P]pupp/3rdparty/gmp/mpn/mu_divappr_q.c
// Function: _gmpn_preinv_mu_divappr_q
mp_limb_t
mpn_preinv_mu_divappr_q (mp_ptr qp,
			 mp_srcptr np,
			 mp_size_t nn,
			 mp_srcptr dp,
			 mp_size_t dn,
			 mp_srcptr ip,
			 mp_size_t in,
			 mp_ptr scratch)
{
  mp_size_t qn;
  mp_limb_t cy, cx, qh;
  mp_limb_t r;
  mp_size_t tn, wn;

#define rp           scratch
#define tp           (scratch + dn)
#define scratch_out  (scratch + dn + tn)

  qn = nn - dn;

  np += qn;
  qp += qn;

  qh = mpn_cmp (np, dp, dn) >= 0;
  if (qh != 0)
    mpn_sub_n (rp, np, dp, dn);
  else
    MPN_COPY (rp, np, dn);

  if (qn == 0)
    return qh;			/* Degenerate use.  Should we allow this? */

  while (qn > 0)
    {
      if (qn < in)
	{
	  ip += in - qn;
	  in = qn;
	}
      np -= in;
      qp -= in;

      /* Compute the next block of quotient limbs by multiplying the inverse I
	 by the upper part of the partial remainder R.  */
      mpn_mul_n (tp, rp + dn - in, ip, in);		/* mulhi  */
      cy = mpn_add_n (qp, tp + in, rp + dn - in, in);	/* I's msb implicit */
      ASSERT_ALWAYS (cy == 0);

      qn -= in;
      if (qn == 0)
	break;

      /* Compute the product of the quotient block and the divisor D, to be
	 subtracted from the partial remainder combined with new limbs from the
	 dividend N.  We only really need the low dn limbs.  */

      if (BELOW_THRESHOLD (in, MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD))
	mpn_mul (tp, dp, dn, qp, in);		/* dn+in limbs, high 'in' cancels */
      else
	{
	  tn = mpn_mulmod_bnm1_next_size (dn + 1);
	  mpn_mulmod_bnm1 (tp, tn, dp, dn, qp, in, scratch_out);
	  wn = dn + in - tn;			/* number of wrapped limbs */
	  if (wn > 0)
	    {
	      cy = mpn_sub_n (tp, tp, rp + dn - wn, wn);
	      cy = mpn_sub_1 (tp + wn, tp + wn, tn - wn, cy);
	      cx = mpn_cmp (rp + dn - in, tp + dn, tn - dn) < 0;
	      ASSERT_ALWAYS (cx >= cy);
	      mpn_incr_u (tp, cx - cy);
	    }
	}

      r = rp[dn - in] - tp[dn];

      /* Subtract the product from the partial remainder combined with new
	 limbs from the dividend N, generating a new partial remainder R.  */
      if (dn != in)
	{
	  cy = mpn_sub_n (tp, np, tp, in);	/* get next 'in' limbs from N */
	  cy = mpn_sub_nc (tp + in, rp, tp + in, dn - in, cy);
	  MPN_COPY (rp, tp, dn);		/* FIXME: try to avoid this */
	}
      else
	{
	  cy = mpn_sub_n (rp, np, tp, in);	/* get next 'in' limbs from N */
	}

      STAT (int i; int err = 0;
	    static int errarr[5]; static int err_rec; static int tot);

      /* Check the remainder R and adjust the quotient as needed.  */
      r -= cy;
      while (r != 0)
	{
	  /* We loop 0 times with about 69% probability, 1 time with about 31%
	     probability, 2 times with about 0.6% probability, if inverse is
	     computed as recommended.  */
	  mpn_incr_u (qp, 1);
	  cy = mpn_sub_n (rp, rp, dp, dn);
	  r -= cy;
	  STAT (err++);
	}
      if (mpn_cmp (rp, dp, dn) >= 0)
	{
	  /* This is executed with about 76% probability.  */
	  mpn_incr_u (qp, 1);
	  cy = mpn_sub_n (rp, rp, dp, dn);
	  STAT (err++);
	}

      STAT (
	    tot++;
	    errarr[err]++;
	    if (err > err_rec)
	      err_rec = err;
	    if (tot % 0x10000 == 0)
	      {
		for (i = 0; i <= err_rec; i++)
		  printf ("  %d(%.1f%%)", errarr[i], 100.0*errarr[i]/tot);
		printf ("\n");
	      }
	    );
    }

  /* FIXME: We should perhaps be somewhat more elegant in our rounding of the
     quotient.  For now, just make sure the returned quotient is >= the real
     quotient; add 3 with saturating arithmetic.  */
  qn = nn - dn;
  cy += mpn_add_1 (qp, qp, qn, 3);
  if (cy != 0)
    {
      if (qh != 0)
	{
	  /* Return a quotient of just 1-bits, with qh set.  */
	  mp_size_t i;
	  for (i = 0; i < qn; i++)
	    qp[i] = GMP_NUMB_MAX;
	}
      else
	{
	  /* Propagate carry into qh.  */
	  qh = 1;
	}
    }

  return qh;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movq -0x20(%rbp), %rax
subq -0x30(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
shlq $0x3, %rax
addq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x40(%rbp), %rax
shlq $0x3, %rax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x18(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
setge %al
andb $0x1, %al
movzbl %al, %eax
cltq
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0x54717
movq 0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
jmp 0x5473c
jmp 0x54719
jmp 0x5471b
jmp 0x5471d
jmp 0x5471f
jmp 0x54721
jmp 0x54723
jmp 0x54725
jmp 0x54727
movq 0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x554c6
jmp 0x5473a
jmp 0x5473c
cmpq $0x0, -0x40(%rbp)
jne 0x54750
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x54cb4
jmp 0x54752
cmpq $0x0, -0x40(%rbp)
jle 0x54c29
movq -0x40(%rbp), %rax
cmpq 0x10(%rbp), %rax
jge 0x54783
movq 0x10(%rbp), %rax
subq -0x40(%rbp), %rax
shlq $0x3, %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
movq %rax, 0x10(%rbp)
movq 0x10(%rbp), %rdx
movq -0x18(%rbp), %rax
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movq 0x10(%rbp), %rdx
movq -0x10(%rbp), %rax
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
xorl %eax, %eax
subq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movq 0x10(%rbp), %rcx
callq 0x39000
movq -0x10(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x18(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
xorl %eax, %eax
subq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x10(%rbp), %rcx
callq 0x36c80
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
sete %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x5486c
leaq 0xf2f1(%rip), %rdi      # 0x63b4c
movl $0xce, %esi
leaq 0xf2b6(%rip), %rdx      # 0x63b1d
callq 0x562c0
jmp 0x5486e
movq 0x10(%rbp), %rcx
movq -0x40(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x54889
jmp 0x54c29
cmpq $0x21, 0x10(%rbp)
jge 0x548b9
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
movq 0x10(%rbp), %r8
callq 0x37f00
jmp 0x54a83
movq -0x30(%rbp), %rdi
addq $0x1, %rdi
callq 0x4eb40
movq %rax, -0x68(%rbp)
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x68(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %r8
movq 0x10(%rbp), %r9
movq 0x18(%rbp), %rax
movq -0x30(%rbp), %r10
shlq $0x3, %r10
addq %r10, %rax
movq -0x68(%rbp), %r10
shlq $0x3, %r10
addq %r10, %rax
movq %rax, (%rsp)
callq 0x4e150
movq -0x30(%rbp), %rax
addq 0x10(%rbp), %rax
subq -0x68(%rbp), %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jle 0x54a81
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x18(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
xorl %eax, %eax
subq -0x70(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x70(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x48(%rbp)
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x70(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x70(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x68(%rbp), %rdx
subq -0x70(%rbp), %rdx
movq -0x48(%rbp), %rcx
callq 0x36e60
movq %rax, -0x48(%rbp)
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
xorl %eax, %eax
subq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x68(%rbp), %rdx
subq -0x30(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
setl %al
andb $0x1, %al
movzbl %al, %eax
cltq
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq -0x48(%rbp), %rax
setae %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x54a4c
leaq 0xf111(%rip), %rdi      # 0x63b4c
movl $0xe4, %esi
leaq 0xf0fc(%rip), %rdx      # 0x63b43
callq 0x562c0
jmp 0x54a4e
jmp 0x54a50
movq 0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x50(%rbp), %rcx
subq -0x48(%rbp), %rcx
addq %rcx, (%rax)
jae 0x54a77
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x54a6c
movq %rax, -0x78(%rbp)
jmp 0x54a7d
jmp 0x54a7f
jmp 0x54a81
jmp 0x54a83
movq 0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
subq 0x10(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x18(%rbp), %rcx
movq -0x30(%rbp), %rdx
shlq $0x3, %rdx
addq %rdx, %rcx
movq -0x30(%rbp), %rdx
subq (%rcx,%rdx,8), %rax
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rax
cmpq 0x10(%rbp), %rax
je 0x54b66
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x18(%rbp), %rsi
movq 0x18(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x10(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x48(%rbp)
movq 0x18(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x18(%rbp), %rsi
movq 0x18(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x30(%rbp), %rcx
subq 0x10(%rbp), %rcx
movq -0x48(%rbp), %r8
callq 0x36fc0
movq %rax, -0x48(%rbp)
jmp 0x54b3a
jmp 0x54b3c
jmp 0x54b3e
jmp 0x54b40
jmp 0x54b42
jmp 0x54b44
jmp 0x54b46
movq 0x18(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rdx
callq 0x554c6
jmp 0x54b64
jmp 0x54b8a
movq 0x18(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq 0x18(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x10(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq -0x60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0x54bde
jmp 0x54ba2
movq -0x10(%rbp), %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x54ba6
movq %rax, -0x80(%rbp)
movq 0x18(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq -0x60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x60(%rbp)
jmp 0x54b99
movq 0x18(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
jl 0x54c24
jmp 0x54bf6
movq -0x10(%rbp), %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x54bfa
movq %rax, -0x88(%rbp)
movq 0x18(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x48(%rbp)
jmp 0x54752
movq -0x20(%rbp), %rax
subq -0x30(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x40(%rbp), %rdx
movl $0x3, %ecx
callq 0x564f0
addq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x54cac
cmpq $0x0, -0x58(%rbp)
je 0x54ca2
movq $0x0, -0x90(%rbp)
movq -0x90(%rbp), %rax
cmpq -0x40(%rbp), %rax
jge 0x54ca0
movq -0x10(%rbp), %rax
movq -0x90(%rbp), %rcx
movq $-0x1, (%rax,%rcx,8)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x54c6c
jmp 0x54caa
movq $0x1, -0x58(%rbp)
jmp 0x54cac
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)