// File: marxn[P]pupp/3rdparty/gmp/mpn/mu_div_qr.c
// Function: _gmpn_preinv_mu_div_qr
mp_limb_t
mpn_preinv_mu_div_qr (mp_ptr qp,
		      mp_ptr rp,
		      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 tp           scratch
#define scratch_out  (scratch + 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_INCR (rp, np, dn);

  /* if (qn == 0) */			/* The while below handles this case */
  /*   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;

      /* 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+1 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");
	      }
	    );
    }

  return qh;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x20(%rbp), %rax
subq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq -0x8(%rbp), %rax
movq %rax, -0x8(%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, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x53c8b
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
jmp 0x53ca8
jmp 0x53c8d
jmp 0x53c8f
jmp 0x53c91
jmp 0x53c93
jmp 0x53c95
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x554c6
jmp 0x53ca8
jmp 0x53caa
cmpq $0x0, -0x38(%rbp)
jle 0x540a8
movq -0x38(%rbp), %rax
cmpq 0x18(%rbp), %rax
jge 0x53cdb
movq 0x18(%rbp), %rax
subq -0x38(%rbp), %rax
shlq $0x3, %rax
addq 0x10(%rbp), %rax
movq %rax, 0x10(%rbp)
movq -0x38(%rbp), %rax
movq %rax, 0x18(%rbp)
movq 0x18(%rbp), %rdx
movq -0x18(%rbp), %rax
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movq 0x18(%rbp), %rdx
movq -0x8(%rbp), %rax
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x8(%rbp)
movq 0x20(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
xorl %eax, %eax
subq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x10(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x39000
movq -0x8(%rbp), %rdi
movq 0x20(%rbp), %rsi
movq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x10(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
xorl %eax, %eax
subq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x18(%rbp), %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%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 0x53dae
leaq 0xfd9a(%rip), %rdi      # 0x63b37
movl $0x118, %esi            # imm = 0x118
leaq 0xfd74(%rip), %rdx      # 0x63b1d
callq 0x562c0
jmp 0x53db0
movq 0x18(%rbp), %rcx
movq -0x38(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x38(%rbp)
cmpq $0x21, 0x18(%rbp)
jge 0x53de4
movq 0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x8(%rbp), %rcx
movq 0x18(%rbp), %r8
callq 0x37f00
jmp 0x53f56
movq -0x30(%rbp), %rdi
addq $0x1, %rdi
callq 0x4eb40
movq %rax, -0x60(%rbp)
movq 0x20(%rbp), %rdi
movq -0x60(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x8(%rbp), %r8
movq 0x18(%rbp), %r9
movq 0x20(%rbp), %rax
movq -0x60(%rbp), %r10
shlq $0x3, %r10
addq %r10, %rax
movq %rax, (%rsp)
callq 0x4e150
movq -0x30(%rbp), %rax
addq 0x18(%rbp), %rax
subq -0x60(%rbp), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
jle 0x53f54
movq 0x20(%rbp), %rdi
movq 0x20(%rbp), %rsi
movq -0x10(%rbp), %rdx
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
xorl %eax, %eax
subq -0x68(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x68(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x40(%rbp)
movq 0x20(%rbp), %rdi
movq -0x68(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x20(%rbp), %rsi
movq -0x68(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x60(%rbp), %rdx
subq -0x68(%rbp), %rdx
movq -0x40(%rbp), %rcx
callq 0x36e60
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
xorl %eax, %eax
subq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq 0x20(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x60(%rbp), %rdx
subq -0x30(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
setl %al
andb $0x1, %al
movzbl %al, %eax
cltq
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x40(%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 0x53f2a
leaq 0xfc1e(%rip), %rdi      # 0x63b37
movl $0x12c, %esi            # imm = 0x12C
leaq 0xfc1e(%rip), %rdx      # 0x63b43
callq 0x562c0
jmp 0x53f2c
jmp 0x53f2e
movq 0x20(%rbp), %rax
movq -0x48(%rbp), %rcx
subq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x53f4a
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x53f3f
movq %rax, -0x70(%rbp)
jmp 0x53f50
jmp 0x53f52
jmp 0x53f54
jmp 0x53f56
movq -0x10(%rbp), %rax
movq -0x30(%rbp), %rcx
subq 0x18(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rbp), %rcx
movq -0x30(%rbp), %rdx
subq (%rcx,%rdx,8), %rax
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rax
cmpq 0x18(%rbp), %rax
je 0x53ff3
movq 0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq 0x20(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x40(%rbp)
movq 0x20(%rbp), %rdi
movq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
movq 0x20(%rbp), %rdx
movq 0x18(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x30(%rbp), %rcx
subq 0x18(%rbp), %rcx
movq -0x40(%rbp), %r8
callq 0x36fc0
movq %rax, -0x40(%rbp)
jmp 0x53fd2
jmp 0x53fd4
jmp 0x53fd6
jmp 0x53fd8
jmp 0x53fda
jmp 0x53fdc
jmp 0x53fde
movq -0x10(%rbp), %rdi
movq 0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x554c6
jmp 0x53ff1
jmp 0x5400c
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq 0x20(%rbp), %rdx
movq 0x18(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rcx
movq -0x58(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0x54060
jmp 0x54024
movq -0x8(%rbp), %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x54028
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rcx
movq -0x58(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x58(%rbp)
jmp 0x5401b
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
jl 0x540a3
jmp 0x54078
movq -0x8(%rbp), %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x5407c
movq %rax, -0x80(%rbp)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x36fe0
movq %rax, -0x40(%rbp)
jmp 0x53caa
movq -0x50(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)