// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %r9, %rbp
movq %r8, %r12
movq %rcx, %r13
movq %rdi, 0x8(%rsp)
movq 0xb8(%rsp), %r15
subq %r8, %rdx
movq %rdx, 0x18(%rsp)
leaq (%rsi,%rdx,8), %rbx
movq %rbx, %rdi
movq %rcx, %rsi
movq %r8, %rdx
callq 0x1ac5c
movl %eax, %r14d
xorl %eax, %eax
testl %r14d, %r14d
setns %al
movq %rax, 0x28(%rsp)
movq %rbx, 0x38(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
js 0x28829
movq %r13, %rdx
movq %r12, %rcx
callq 0x17ed0
jmp 0x28831
movq %r12, %rdx
callq 0x290c6
movq 0x18(%rsp), %r15
testq %r15, %r15
je 0x28b0d
movl %r14d, 0x24(%rsp)
movq 0xb0(%rsp), %rcx
movq 0x8(%rsp), %rdx
leaq (%rdx,%r15,8), %r14
movq 0xb8(%rsp), %rdx
leaq (%rdx,%r12,8), %rdx
leaq 0x1(%r12), %rsi
movq %rsi, 0x40(%rsp)
movq %rdx, 0x8(%rsp)
leaq (%rdx,%r12,8), %rdx
movq %rdx, 0x30(%rsp)
movq %rbp, %rdx
movq %r13, 0x10(%rsp)
testq %r15, %r15
jle 0x28b16
movq %r15, %rax
subq %rcx, %rax
movq %rcx, %rbx
cmovlq %r15, %rbx
negq %rax
cmpq %r15, %rcx
movl $0x0, %ecx
cmovleq %rcx, %rax
leaq (%rdx,%rax,8), %rdx
leaq (,%rbx,8), %rax
subq %rax, %r14
movq 0x8(%rsp), %r13
movq %r13, %rbp
movq %rax, 0x68(%rsp)
subq %rax, %rbp
movq %r13, %rdi
movq %rbp, %rsi
movq %rdx, 0x70(%rsp)
movq %rbx, %rcx
callq 0x19500
leaq (%r13,%rbx,8), %r13
movq %r14, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
callq 0x17cf0
testq %rax, %rax
jne 0x28b79
subq %rbx, %r15
movq %r15, 0x60(%rsp)
je 0x28b14
movq %r13, 0x50(%rsp)
cmpq $0x20, %rbx
jle 0x289d9
movq 0x40(%rsp), %rdi
callq 0x253ca
movq %rax, %r15
movq 0x8(%rsp), %rdi
leaq (%rdi,%rax,8), %rax
movq %rax, (%rsp)
movq %r15, %rsi
movq 0x10(%rsp), %rdx
movq %r12, %rcx
movq %r14, %r8
movq %rbx, %r9
callq 0x24f3e
leaq (%rbx,%r12), %rcx
subq %r15, %rcx
testq %rcx, %rcx
movq 0xb8(%rsp), %r13
jle 0x289f9
leaq (,%rcx,8), %rax
movq 0x8(%rsp), %r13
movq %r13, %rdx
subq %rax, %rdx
movq %r13, %rdi
movq %r13, %rsi
movq %rcx, 0x48(%rsp)
callq 0x17ed0
movq 0x48(%rsp), %rcx
leaq (,%rcx,8), %rdi
addq %r13, %rdi
movq %r15, %rdx
subq %rcx, %rdx
movq %rdi, %rsi
movq %rax, %rcx
callq 0x17e44
movq %rax, %r13
subq %r12, %r15
movq %rbp, %rdi
movq 0x30(%rsp), %rsi
movq %r15, %rdx
callq 0x1ac5c
shrl $0x1f, %eax
subq %r13, %rax
jb 0x28b91
movq 0x8(%rsp), %rcx
addq %rax, (%rcx)
jae 0x289d7
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x289cc
jmp 0x289f1
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
movq %r12, %rdx
movq %r14, %rcx
movq %rbx, %r8
callq 0x18a58
movq 0xb8(%rsp), %r13
movq 0x38(%rsp), %rsi
subq 0x68(%rsp), %rsi
movq %rbx, %rcx
movq %r12, %rbx
movq 0x30(%rsp), %rax
movq (%rax), %rbp
subq %rcx, %rbx
movq (%r13,%rbx,8), %r15
movq %rsi, 0x38(%rsp)
movq %rcx, 0x58(%rsp)
jne 0x28a3a
movq %r13, %rdi
movq 0x8(%rsp), %rdx
movq %r12, %rcx
callq 0x17ed0
movq %rax, %rbx
jmp 0x28a70
movq 0x8(%rsp), %rdi
movq %rdi, %rdx
callq 0x17ed0
movq 0x50(%rsp), %rdi
movq %r13, %rsi
movq %rdi, %rdx
movq %rbx, %rcx
movq %rax, %r8
callq 0x17eb0
movq %rax, %rbx
movq %r13, %rdi
movq 0x8(%rsp), %rsi
movq %r12, %rdx
callq 0x290c6
movq 0x10(%rsp), %r13
addq %rbx, %rbp
subq %rbp, %r15
testq %r15, %r15
je 0x28aab
movq %r14, %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x28a83
movq 0xb8(%rsp), %rdi
movq %rdi, %rsi
movq %r13, %rdx
movq %r12, %rcx
callq 0x17ed0
movq %rax, %rbx
subq %rax, %r15
jmp 0x28a7b
movq 0xb8(%rsp), %rbp
movq %rbp, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x1ac5c
movq 0x58(%rsp), %r8
movq %r8, %rcx
testl %eax, %eax
movq 0x70(%rsp), %rdx
movq 0x60(%rsp), %r15
js 0x28881
movq %r14, %rax
addq $0x1, (%rax)
leaq 0x8(%rax), %rax
jb 0x28ade
movq %rbp, %rdi
movq %rbp, %rsi
movq %r8, %rbp
movq %rdx, %rbx
movq %r13, %rdx
movq %r12, %rcx
callq 0x17ed0
movq %rbx, %rdx
movq %rax, %rbx
movq %rbp, %rcx
jmp 0x28881
movq 0x28(%rsp), %rax
jmp 0x28b6a
xorl %ebx, %ebx
pushq $0x3
popq %rcx
movq %r14, %rdi
movq %r14, %rsi
movq 0x18(%rsp), %rdx
callq 0x29e1c
movq %rax, %rcx
negq %rcx
cmpq %rcx, %rbx
pushq $0x1
popq %rax
movq 0x28(%rsp), %rdx
cmoveq %rdx, %rax
cmpl $0x0, 0x24(%rsp)
js 0x28b6a
cmpq %rcx, %rbx
je 0x28b6a
xorl %eax, %eax
movq 0x18(%rsp), %rcx
testq %rcx, %rcx
cmovleq %rax, %rcx
cmpq %rax, %rcx
je 0x28b67
orq $-0x1, (%r14,%rax,8)
incq %rax
jmp 0x28b58
movq %rdx, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xae8c(%rip), %rdi      # 0x33a0c
leaq 0xae56(%rip), %rdx      # 0x339dd
movl $0xce, %esi
callq 0x29ce6
leaq 0xae74(%rip), %rdi      # 0x33a0c
leaq 0xae64(%rip), %rdx      # 0x33a03
movl $0xe4, %esi
callq 0x29ce6