// File: /workspace/github_cpp_makefile_star2_O3/marxn[P]pupp/3rdparty/gmp/mpn/mulmod_bnm1.c
// Function: _gmpn_mulmod_bnm1
void
mpn_mulmod_bnm1 (mp_ptr rp, mp_size_t rn, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn, mp_ptr tp)
{
  ASSERT (0 < bn);
  ASSERT (bn <= an);
  ASSERT (an <= rn);

  if ((rn & 1) != 0 || BELOW_THRESHOLD (rn, MULMOD_BNM1_THRESHOLD))
    {
      if (UNLIKELY (bn < rn))
	{
	  if (UNLIKELY (an + bn <= rn))
	    {
	      mpn_mul (rp, ap, an, bp, bn);
	    }
	  else
	    {
	      mp_limb_t cy;
	      mpn_mul (tp, ap, an, bp, bn);
	      cy = mpn_add (rp, tp, rn, tp + rn, an + bn - rn);
	      MPN_INCR_U (rp, rn, cy);
	    }
	}
      else
	mpn_bc_mulmod_bnm1 (rp, ap, bp, rn, tp);
    }
  else
    {
      mp_size_t n;
      mp_limb_t cy;
      mp_limb_t hi;

      n = rn >> 1;

      /* We need at least an + bn >= n, to be able to fit one of the
	 recursive products at rp. Requiring strict inequality makes
	 the code slightly simpler. If desired, we could avoid this
	 restriction by initially halving rn as long as rn is even and
	 an + bn <= rn/2. */

      ASSERT (an + bn > n);

      /* Compute xm = a*b mod (B^n - 1), xp = a*b mod (B^n + 1)
	 and crt together as

	 x = -xp * B^n + (B^n + 1) * [ (xp + xm)/2 mod (B^n-1)]
      */

#define a0 ap
#define a1 (ap + n)
#define b0 bp
#define b1 (bp + n)

#define xp  tp	/* 2n + 2 */
      /* am1  maybe in {xp, n} */
      /* bm1  maybe in {xp + n, n} */
#define sp1 (tp + 2*n + 2)
      /* ap1  maybe in {sp1, n + 1} */
      /* bp1  maybe in {sp1 + n + 1, n + 1} */

      {
	mp_srcptr am1, bm1;
	mp_size_t anm, bnm;
	mp_ptr so;

	bm1 = b0;
	bnm = bn;
	if (LIKELY (an > n))
	  {
	    am1 = xp;
	    cy = mpn_add (xp, a0, n, a1, an - n);
	    MPN_INCR_U (xp, n, cy);
	    anm = n;
	    so = xp + n;
	    if (LIKELY (bn > n))
	      {
		bm1 = so;
		cy = mpn_add (so, b0, n, b1, bn - n);
		MPN_INCR_U (so, n, cy);
		bnm = n;
		so += n;
	      }
	  }
	else
	  {
	    so = xp;
	    am1 = a0;
	    anm = an;
	  }

	mpn_mulmod_bnm1 (rp, n, am1, anm, bm1, bnm, so);
      }

      {
	int       k;
	mp_srcptr ap1, bp1;
	mp_size_t anp, bnp;

	bp1 = b0;
	bnp = bn;
	if (LIKELY (an > n)) {
	  ap1 = sp1;
	  cy = mpn_sub (sp1, a0, n, a1, an - n);
	  sp1[n] = 0;
	  MPN_INCR_U (sp1, n + 1, cy);
	  anp = n + ap1[n];
	  if (LIKELY (bn > n)) {
	    bp1 = sp1 + n + 1;
	    cy = mpn_sub (sp1 + n + 1, b0, n, b1, bn - n);
	    sp1[2*n+1] = 0;
	    MPN_INCR_U (sp1 + n + 1, n + 1, cy);
	    bnp = n + bp1[n];
	  }
	} else {
	  ap1 = a0;
	  anp = an;
	}

	if (BELOW_THRESHOLD (n, MUL_FFT_MODF_THRESHOLD))
	  k=0;
	else
	  {
	    int mask;
	    k = mpn_fft_best_k (n, 0);
	    mask = (1<<k) - 1;
	    while (n & mask) {k--; mask >>=1;};
	  }
	if (k >= FFT_FIRST_K)
	  xp[n] = mpn_mul_fft (xp, n, ap1, anp, bp1, bnp, k);
	else if (UNLIKELY (bp1 == b0))
	  {
	    ASSERT (anp + bnp <= 2*n+1);
	    ASSERT (anp + bnp > n);
	    ASSERT (anp >= bnp);
	    mpn_mul (xp, ap1, anp, bp1, bnp);
	    anp = anp + bnp - n;
	    ASSERT (anp <= n || xp[2*n]==0);
	    anp-= anp > n;
	    cy = mpn_sub (xp, xp, n, xp + n, anp);
	    xp[n] = 0;
	    MPN_INCR_U (xp, n+1, cy);
	  }
	else
	  mpn_bc_mulmod_bnp1 (xp, ap1, bp1, n, xp);
      }

      /* Here the CRT recomposition begins.

	 xm <- (xp + xm)/2 = (xp + xm)B^n/2 mod (B^n-1)
	 Division by 2 is a bitwise rotation.

	 Assumes xp normalised mod (B^n+1).

	 The residue class [0] is represented by [B^n-1]; except when
	 both input are ZERO.
      */

#if HAVE_NATIVE_mpn_rsh1add_n || HAVE_NATIVE_mpn_rsh1add_nc
#if HAVE_NATIVE_mpn_rsh1add_nc
      cy = mpn_rsh1add_nc(rp, rp, xp, n, xp[n]); /* B^n = 1 */
      hi = cy << (GMP_NUMB_BITS - 1);
      cy = 0;
      /* next update of rp[n-1] will set cy = 1 only if rp[n-1]+=hi
	 overflows, i.e. a further increment will not overflow again. */
#else /* ! _nc */
      cy = xp[n] + mpn_rsh1add_n(rp, rp, xp, n); /* B^n = 1 */
      hi = (cy<<(GMP_NUMB_BITS-1))&GMP_NUMB_MASK; /* (cy&1) << ... */
      cy >>= 1;
      /* cy = 1 only if xp[n] = 1 i.e. {xp,n} = ZERO, this implies that
	 the rsh1add was a simple rshift: the top bit is 0. cy=1 => hi=0. */
#endif
#if GMP_NAIL_BITS == 0
      add_ssaaaa(cy, rp[n-1], cy, rp[n-1], 0, hi);
#else
      cy += (hi & rp[n-1]) >> (GMP_NUMB_BITS-1);
      rp[n-1] ^= hi;
#endif
#else /* ! HAVE_NATIVE_mpn_rsh1add_n */
#if HAVE_NATIVE_mpn_add_nc
      cy = mpn_add_nc(rp, rp, xp, n, xp[n]);
#else /* ! _nc */
      cy = xp[n] + mpn_add_n(rp, rp, xp, n); /* xp[n] == 1 implies {xp,n} == ZERO */
#endif
      cy += (rp[0]&1);
      mpn_rshift(rp, rp, n, 1);
      ASSERT (cy <= 2);
      hi = (cy<<(GMP_NUMB_BITS-1))&GMP_NUMB_MASK; /* (cy&1) << ... */
      cy >>= 1;
      /* We can have cy != 0 only if hi = 0... */
      ASSERT ((rp[n-1] & GMP_NUMB_HIGHBIT) == 0);
      rp[n-1] |= hi;
      /* ... rp[n-1] + cy can not overflow, the following INCR is correct. */
#endif
      ASSERT (cy <= 1);
      /* Next increment can not overflow, read the previous comments about cy. */
      ASSERT ((cy == 0) || ((rp[n-1] & GMP_NUMB_HIGHBIT) == 0));
      MPN_INCR_U(rp, n, cy);

      /* Compute the highest half:
	 ([(xp + xm)/2 mod (B^n-1)] - xp ) * B^n
       */
      if (UNLIKELY (an + bn < rn))
	{
	  /* Note that in this case, the only way the result can equal
	     zero mod B^{rn} - 1 is if one of the inputs is zero, and
	     then the output of both the recursive calls and this CRT
	     reconstruction is zero, not B^{rn} - 1. Which is good,
	     since the latter representation doesn't fit in the output
	     area.*/
	  cy = mpn_sub_n (rp + n, rp, xp, an + bn - n);

	  /* FIXME: This subtraction of the high parts is not really
	     necessary, we do it to get the carry out, and for sanity
	     checking. */
	  cy = xp[n] + mpn_sub_nc (xp + an + bn - n, rp + an + bn - n,
				   xp + an + bn - n, rn - (an + bn), cy);
	  ASSERT (an + bn == rn - 1 ||
		  mpn_zero_p (xp + an + bn - n + 1, rn - 1 - (an + bn)));
	  cy = mpn_sub_1 (rp, rp, an + bn, cy);
	  ASSERT (cy == (xp + an + bn - n)[0]);
	}
      else
	{
	  cy = xp[n] + mpn_sub_n (rp + n, rp, xp, n);
	  /* cy = 1 only if {xp,n+1} is not ZERO, i.e. {rp,n} is not ZERO.
	     DECR will affect _at most_ the lowest n limbs. */
	  MPN_DECR_U (rp, 2*n, cy);
	}
#undef a0
#undef a1
#undef b0
#undef b1
#undef xp
#undef sp1
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r9, %r15
movq %r8, %r13
movq %rcx, %r14
movq %rdx, %r12
movq %rsi, %r8
movq 0x80(%rsp), %rbx
testb $0x1, %r8b
sete %al
cmpq $0x12, %rsi
setge %cl
testb %al, %cl
je 0x2a5c0
movq %r8, %rbp
shrq %rbp
cmpq %rbp, %r14
movq %r8, 0x10(%rsp)
movq %r15, 0x30(%rsp)
movq %rdi, 0x18(%rsp)
movq %rbx, 0x20(%rsp)
movq %r14, 0x38(%rsp)
jle 0x2a9b0
leaq (%r12,%rbp,8), %rdx
subq %rbp, %r14
movq %rdx, 0x28(%rsp)
je 0x2a5e8
movq %rbx, %rdi
movq %r12, %rsi
movq %r14, %rcx
callq 0x1ba80
movq 0x30(%rsp), %r15
movq %r14, %rcx
testq %rax, %rax
je 0x2a5ea
movq %r14, %rax
cmpq %rbp, %rax
jge 0x2a611
movq (%r12,%rax,8), %rdx
leaq 0x1(%rax), %rcx
incq %rdx
movq %rdx, (%rbx,%rax,8)
movq %rcx, %rax
je 0x2a5a5
jmp 0x2a5ea
cmpq %r8, %r15
jl 0x2a9e3
movq %r12, %rsi
movq %r13, %rdx
movq %r8, %rcx
movq %rbx, %r8
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2a4dc
xorl %ecx, %ecx
cmpq %r12, %rbx
setne %al
cmpq %rbp, %rcx
setl %dl
andb %al, %dl
xorl %eax, %eax
cmpb $0x1, %dl
jne 0x2a616
movq (%r12,%rcx,8), %rdx
movq %rdx, (%rbx,%rcx,8)
incq %rcx
cmpq %rcx, %rbp
jne 0x2a5ff
jmp 0x2a616
movl $0x1, %eax
movq %rbx, %rcx
addq %rax, (%rcx)
jae 0x2a629
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2a61e
leaq (%rbx,%rbp,8), %rbx
cmpq %rbp, %r15
jle 0x2aac8
subq %rbp, %r15
je 0x2a682
leaq (,%rbp,8), %rdx
addq %r13, %rdx
movq %rbx, %rdi
movq %r13, %rsi
movq %r15, %rcx
callq 0x1ba80
testq %rax, %rax
je 0x2a685
movq 0x20(%rsp), %rax
movq 0x30(%rsp), %rcx
leaq (%rax,%rcx,8), %rax
cmpq %rbp, %r15
jge 0x2a6ad
movq (%r13,%r15,8), %rcx
incq %r15
incq %rcx
movq %rcx, (%rax)
leaq 0x8(%rax), %rax
je 0x2a667
jmp 0x2a685
xorl %r15d, %r15d
cmpq %r13, %rbx
setne %al
cmpq %rbp, %r15
setl %cl
andb %al, %cl
xorl %eax, %eax
cmpb $0x1, %cl
jne 0x2a6b2
movq (%r13,%r15,8), %rcx
movq %rcx, (%rbx,%r15,8)
incq %r15
cmpq %r15, %rbp
jne 0x2a69a
jmp 0x2a6b2
movl $0x1, %eax
leaq (%rbx,%rbp,8), %rcx
movq %rbx, %r8
addq %rax, (%rbx)
jae 0x2a6c9
addq $0x1, 0x8(%rbx)
leaq 0x8(%rbx), %rbx
jb 0x2a6be
movq %rbp, %r9
movq %rcx, %rbx
movq 0x18(%rsp), %rdi
movq %rbx, (%rsp)
movq %rbp, %rsi
movq 0x20(%rsp), %rbx
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x2a51a
movq 0x10(%rsp), %rsi
leaq (%rbx,%rsi,8), %r15
addq $0x10, %r15
testq %r14, %r14
je 0x2a736
movq %r15, %rdi
movq %r12, %rsi
movq 0x28(%rsp), %rdx
movq %r14, %rcx
callq 0x1bca0
testq %rax, %rax
je 0x2a73a
movq 0x10(%rsp), %rsi
cmpq %rbp, %r14
jge 0x2a769
movq (%r12,%r14,8), %rcx
leaq 0x1(%r14), %rax
subq $0x1, %rcx
movq %rcx, (%r15,%r14,8)
movq %rax, %r14
jb 0x2a71a
jmp 0x2a742
xorl %eax, %eax
jmp 0x2a742
movq %r14, %rax
movq 0x10(%rsp), %rsi
cmpq %r12, %r15
setne %cl
cmpq %rbp, %rax
setl %dl
andb %cl, %dl
xorl %ecx, %ecx
cmpb $0x1, %dl
jne 0x2a76e
movq (%r12,%rax,8), %rdx
movq %rdx, (%r15,%rax,8)
incq %rax
cmpq %rax, %rbp
jne 0x2a757
jmp 0x2a76e
movl $0x1, %ecx
movq $0x0, (%r15,%rbp,8)
movq %r15, %rax
addq %rcx, (%rax)
jae 0x2a789
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x2a77e
movq (%r15,%rbp,8), %rax
addq %rbp, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %r14
cmpq %rbp, %r14
jle 0x2aad3
leaq (%r15,%rbp,8), %r12
addq $0x8, %r12
subq %rbp, %r14
je 0x2a804
leaq (,%rbp,8), %rdx
addq %r13, %rdx
movq %r12, %rdi
movq %r13, %rsi
movq %r14, %rcx
callq 0x1bca0
testq %rax, %rax
je 0x2a809
movq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rax
addq %rsi, %rax
movq 0x20(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
addq $0x18, %rax
cmpq %rbp, %r14
jge 0x2a836
movq (%r13,%r14,8), %rcx
incq %r14
subq $0x1, %rcx
movq %rcx, (%rax)
leaq 0x8(%rax), %rax
jb 0x2a7e8
jmp 0x2a80e
xorl %r14d, %r14d
jmp 0x2a80e
movq 0x10(%rsp), %rsi
cmpq %r13, %r12
setne %al
cmpq %rbp, %r14
setl %cl
andb %al, %cl
xorl %eax, %eax
cmpb $0x1, %cl
jne 0x2a83b
movq (%r13,%r14,8), %rcx
movq %rcx, (%r12,%r14,8)
incq %r14
cmpq %r14, %rbp
jne 0x2a823
jmp 0x2a83b
movl $0x1, %eax
movq $0x0, 0x8(%r15,%rsi,8)
movq %r12, %rcx
addq %rax, (%rcx)
jae 0x2a857
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2a84c
movq (%r12,%rbp,8), %r14
addq %rbp, %r14
cmpq $0x51b, %rsi            # imm = 0x51B
jb 0x2a8ba
movq %rbp, %rdi
xorl %esi, %esi
callq 0x302e8
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %eax, %ecx
shll %cl, %edx
notl %edx
testl %edx, %ebp
je 0x2a886
decl %eax
shrl %edx
jmp 0x2a87c
cmpl $0x4, %eax
movq 0x10(%rsp), %r8
jl 0x2a8ba
movl %eax, (%rsp)
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq %rbp, %rsi
movq %r15, %rdx
movq 0x28(%rsp), %rcx
movq %r8, %r13
movq %r12, %r8
movq %r14, %r9
callq 0x30331
movq %rax, (%rbx,%rbp,8)
jmp 0x2a915
cmpq %r13, %r12
je 0x2aadb
leaq 0x1(%rbp), %rcx
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x1d348
movq 0x10(%rsp), %r13
movq (%rbx,%r13,8), %r14
leaq (%rbx,%rbp,8), %r15
movq %rbx, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movq %rbp, %rcx
callq 0x1bca0
addq %r14, %rax
movq $0x0, (%r15)
movq %rbx, %rcx
addq %rax, (%rcx)
jae 0x2a915
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2a90a
movq (%rbx,%rbp,8), %r8
movq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r12, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x2f520
shlq $0x3f, %rax
leaq (%r12,%rbp,8), %rdi
movq -0x8(%rdi), %rcx
movq %rax, 0x40(%rsp)
xorl %eax, %eax
addq 0x40(%rsp), %rcx
adcq $0x0, %rax
movq %rcx, -0x8(%rdi)
movq %r12, %rcx
addq %rax, (%rcx)
jae 0x2a962
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2a957
movq 0x30(%rsp), %r15
movq 0x38(%rsp), %rax
leaq (%r15,%rax), %r14
subq %r14, %r13
jg 0x2aa45
movq (%rbx,%rbp,8), %r14
movq %r12, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x1bca0
addq %r14, %rax
subq %rax, (%r12)
jae 0x2a9a1
subq $0x1, 0x8(%r12)
leaq 0x8(%r12), %r12
jb 0x2a994
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, (%rsp)
movq %rbp, %rsi
movq %r12, %rdx
movq %r14, %rcx
movq %r13, %r8
movq %r15, %r9
callq 0x2a51a
movq 0x10(%rsp), %rsi
movq %r14, %rax
movq %r15, %r14
movq %r12, %r15
movq %r13, %r12
movq %rax, 0x28(%rsp)
jmp 0x2a85e
movq %rdi, 0x18(%rsp)
movq %rbx, %rbp
leaq (%r15,%r14), %rbx
subq %r8, %rbx
movq %r14, %rdx
jle 0x2ab50
movq %r8, %r14
movq %rbp, %rdi
movq %r12, %rsi
movq %r13, %rcx
movq %r15, %r8
callq 0x1c838
leaq (,%r14,8), %rcx
addq %rbp, %rcx
movq 0x18(%rsp), %r15
movq %r15, %rdi
movq %rbp, %rsi
movq %r14, %rdx
movq %rbx, %r8
callq 0x2fe0c
addq %rax, (%r15)
jae 0x2aa40
addq $0x1, 0x8(%r15)
leaq 0x8(%r15), %r15
jb 0x2aa35
jmp 0x2a9a1
movq %rbp, %rax
negq %rax
movq %rax, 0x10(%rsp)
movq %r14, %rcx
subq %rbp, %rcx
movq %r12, %rsi
movq %rbx, %rdx
callq 0x1bca0
movq (%rbx,%rbp,8), %rbp
movq 0x38(%rsp), %rsi
leaq (%rbx,%rsi,8), %rcx
leaq (%rcx,%r15,8), %rcx
movq 0x10(%rsp), %r8
leaq (%rcx,%r8,8), %rdi
leaq (%r12,%rsi,8), %rcx
leaq (%rcx,%r15,8), %rcx
leaq (%rcx,%r8,8), %rsi
movq %rdi, %rdx
movq %r13, %rcx
movq %rax, %r8
callq 0x1bc80
addq %rbp, %rax
subq %rax, (%r12)
jae 0x2a9a1
cmpq $0x2, %r14
movl $0x1, %eax
cmovlq %rax, %r14
cmpq %rax, %r14
je 0x2a9a1
subq $0x1, (%r12,%rax,8)
leaq 0x1(%rax), %rax
jb 0x2aaaf
jmp 0x2a9a1
movq %r13, %r8
movq %r15, %r9
jmp 0x2a6cf
movq %r13, %r12
jmp 0x2a85e
movq 0x20(%rsp), %r13
movq %r13, %rdi
movq %r15, %rsi
movq 0x28(%rsp), %r15
movq %r15, %rdx
movq %r12, %rcx
movq %r14, %r8
callq 0x1c838
subq %rbp, %r15
addq %r14, %r15
xorl %eax, %eax
cmpq %rbp, %r15
setg %al
subq %rax, %r15
leaq (,%rbp,8), %rbx
addq %r13, %rbx
movq %r13, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
movq %r15, %r8
callq 0x1bb58
movq $0x0, (%rbx)
movq %r13, %rbx
movq %r13, %rcx
addq %rax, (%rcx)
jae 0x2ab46
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2ab3b
movq 0x10(%rsp), %r13
jmp 0x2a915
movq 0x18(%rsp), %rdi
movq %r12, %rsi
movq %r13, %rcx
movq %r15, %r8
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1c838