// File: /workspace/github_cpp_makefile_star2_O1/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, %r9
movq 0x80(%rsp), %rbx
testb $0x1, %r9b
sete %al
cmpq $0x12, %rsi
setge %cl
testb %al, %cl
je 0x2a92a
movq %r9, %rbp
shrq %rbp
cmpq %rbp, %r14
movq %r9, 0x10(%rsp)
movq %rdi, 0x38(%rsp)
movq %rbx, 0x18(%rsp)
movq %r15, 0x20(%rsp)
movq %r14, 0x30(%rsp)
jle 0x2ad32
movq %rdi, %r15
leaq (%r12,%rbp,8), %rdx
subq %rbp, %r14
movq %rdx, 0x28(%rsp)
je 0x2a952
movq %rbx, %rdi
movq %r12, %rsi
movq %r14, %rcx
callq 0x1bfa0
movq %r14, %rcx
testq %rax, %rax
je 0x2a954
movq %r14, %rax
cmpq %rbp, %rax
jge 0x2a97e
movq (%r12,%rax,8), %rdx
leaq 0x1(%rax), %rcx
incq %rdx
movq %rdx, (%rbx,%rax,8)
movq %rcx, %rax
je 0x2a90f
jmp 0x2a954
cmpq %r9, %r15
jl 0x2ad5f
movq %r12, %rsi
movq %r13, %rdx
movq %r9, %rcx
movq %rbx, %r8
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2a848
xorl %ecx, %ecx
cmpq %r12, %rbx
setne %al
cmpq %rbp, %rcx
setl %dl
andb %al, %dl
xorl %eax, %eax
cmpb $0x1, %dl
jne 0x2a983
movq %r15, %rdi
movq (%r12,%rcx,8), %rdx
movq %rdx, (%rbx,%rcx,8)
incq %rcx
cmpq %rcx, %rbp
jne 0x2a96c
jmp 0x2a986
movl $0x1, %eax
movq %r15, %rdi
movq 0x20(%rsp), %r15
movq %rbx, %rcx
addq %rax, (%rcx)
jae 0x2a99e
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2a993
leaq (%rbx,%rbp,8), %rbx
cmpq %rbp, %r15
jle 0x2ae3c
subq %rbp, %r15
je 0x2a9f7
leaq (,%rbp,8), %rdx
addq %r13, %rdx
movq %rbx, %rdi
movq %r13, %rsi
movq %r15, %rcx
callq 0x1bfa0
testq %rax, %rax
je 0x2a9fa
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
leaq (%rax,%rcx,8), %rax
cmpq %rbp, %r15
jge 0x2aa22
movq (%r13,%r15,8), %rcx
incq %r15
incq %rcx
movq %rcx, (%rax)
leaq 0x8(%rax), %rax
je 0x2a9dc
jmp 0x2a9fa
xorl %r15d, %r15d
cmpq %r13, %rbx
setne %al
cmpq %rbp, %r15
setl %cl
andb %al, %cl
xorl %eax, %eax
cmpb $0x1, %cl
jne 0x2aa27
movq (%r13,%r15,8), %rcx
movq %rcx, (%rbx,%r15,8)
incq %r15
cmpq %r15, %rbp
jne 0x2aa0f
jmp 0x2aa27
movl $0x1, %eax
leaq (%rbx,%rbp,8), %rcx
movq %rbx, %r8
addq %rax, (%rbx)
jae 0x2aa3e
addq $0x1, 0x8(%rbx)
leaq 0x8(%rbx), %rbx
jb 0x2aa33
movq %rbp, %r9
movq %rcx, %rbx
movq 0x38(%rsp), %rdi
movq 0x20(%rsp), %r15
movq %rbx, (%rsp)
movq %rbp, %rsi
movq 0x18(%rsp), %rbx
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x2a886
movq 0x10(%rsp), %r8
leaq (%rbx,%r8,8), %rbx
addq $0x10, %rbx
testq %r14, %r14
je 0x2aab0
movq %rbx, %rdi
movq %r12, %rsi
movq 0x28(%rsp), %rdx
movq %r14, %rcx
callq 0x1c1c0
testq %rax, %rax
je 0x2aab4
movq 0x10(%rsp), %r8
cmpq %rbp, %r14
jge 0x2aae3
movq (%r12,%r14,8), %rcx
leaq 0x1(%r14), %rax
subq $0x1, %rcx
movq %rcx, (%rbx,%r14,8)
movq %rax, %r14
jb 0x2aa94
jmp 0x2aabc
xorl %eax, %eax
jmp 0x2aabc
movq %r14, %rax
movq 0x10(%rsp), %r8
cmpq %r12, %rbx
setne %cl
cmpq %rbp, %rax
setl %dl
andb %cl, %dl
xorl %ecx, %ecx
cmpb $0x1, %dl
jne 0x2aae8
movq (%r12,%rax,8), %rdx
movq %rdx, (%rbx,%rax,8)
incq %rax
cmpq %rax, %rbp
jne 0x2aad1
jmp 0x2aae8
movl $0x1, %ecx
movq $0x0, (%rbx,%rbp,8)
movq %rbx, %rax
addq %rcx, (%rax)
jae 0x2ab03
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x2aaf8
movq (%rbx,%rbp,8), %rax
addq %rbp, %rax
movq %rax, 0x28(%rsp)
cmpq %rbp, %r15
jle 0x2ae47
leaq (%rbx,%rbp,8), %r12
addq $0x8, %r12
movq %r15, %r14
subq %rbp, %r14
je 0x2ab78
leaq (,%rbp,8), %rdx
addq %r13, %rdx
movq %r12, %rdi
movq %r13, %rsi
movq %r14, %rcx
callq 0x1c1c0
testq %rax, %rax
je 0x2ab7d
movq 0x10(%rsp), %r8
leaq (%r15,%r8), %rax
movq 0x18(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
addq $0x18, %rax
cmpq %rbp, %r14
jge 0x2abaa
movq (%r13,%r14,8), %rcx
incq %r14
subq $0x1, %rcx
movq %rcx, (%rax)
leaq 0x8(%rax), %rax
jb 0x2ab5c
jmp 0x2ab82
xorl %r14d, %r14d
jmp 0x2ab82
movq 0x10(%rsp), %r8
cmpq %r13, %r12
setne %al
cmpq %rbp, %r14
setl %cl
andb %al, %cl
xorl %eax, %eax
cmpb $0x1, %cl
jne 0x2abaf
movq (%r13,%r14,8), %rcx
movq %rcx, (%r12,%r14,8)
incq %r14
cmpq %r14, %rbp
jne 0x2ab97
jmp 0x2abaf
movl $0x1, %eax
movq $0x0, 0x8(%rbx,%r8,8)
movq %r12, %rcx
addq %rax, (%rcx)
jae 0x2abcb
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2abc0
movq (%r12,%rbp,8), %r14
addq %rbp, %r14
xorl %eax, %eax
cmpq $0x51b, %r8             # imm = 0x51B
jb 0x2ac0a
movq %rbp, %rdi
xorl %esi, %esi
callq 0x306a8
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %eax, %ecx
shll %cl, %edx
notl %edx
testl %edx, %ebp
je 0x2ac05
movq 0x10(%rsp), %r8
decl %eax
shrl %edx
testl %edx, %ebp
jne 0x2abfb
jmp 0x2ac0a
movq 0x10(%rsp), %r8
cmpl $0x4, %eax
jl 0x2ac3c
movl %eax, (%rsp)
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
movq %rbx, %rdx
movq %rdi, %rbx
movq 0x28(%rsp), %rcx
movq %r8, %r13
movq %r12, %r8
movq %r14, %r9
callq 0x306f1
movq %rax, (%rbx,%rbp,8)
movq %r15, %r14
jmp 0x2ac9f
cmpq %r13, %r12
je 0x2ae52
leaq 0x1(%rbp), %rcx
movq 0x18(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x1d864
movq 0x10(%rsp), %r13
movq (%r15,%r13,8), %r14
leaq (%r15,%rbp,8), %rbx
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x1c1c0
addq %r14, %rax
movq $0x0, (%rbx)
movq %r15, %rbx
movq 0x20(%rsp), %r14
movq %r15, %rcx
addq %rax, (%rcx)
jae 0x2ac9f
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2ac94
movq (%rbx,%rbp,8), %r8
movq 0x38(%rsp), %r15
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x2f8e0
shlq $0x3f, %rax
leaq (%r15,%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 %r15, %rcx
addq %rax, (%rcx)
jae 0x2acec
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2ace1
movq 0x30(%rsp), %rax
leaq (%r14,%rax), %r12
subq %r12, %r13
jg 0x2adba
movq (%rbx,%rbp,8), %r14
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x1c1c0
addq %r14, %rax
subq %rax, (%r15)
jae 0x2ad23
subq $0x1, 0x8(%r15)
leaq 0x8(%r15), %r15
jb 0x2ad18
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 0x2a886
movq 0x10(%rsp), %r8
movq %r12, %rbx
movq %r13, %r12
movq %r14, 0x28(%rsp)
jmp 0x2ae4a
movq %r15, %r8
movq %rdi, %r15
movq %rbx, %rbp
leaq (%r8,%r14), %rbx
subq %r9, %rbx
movq %r14, %rdx
jle 0x2aec7
movq %r9, %r14
movq %rbp, %rdi
movq %r12, %rsi
movq %r13, %rcx
callq 0x1cd58
leaq (,%r14,8), %rcx
addq %rbp, %rcx
movq %r15, %rdi
movq %rbp, %rsi
movq %r14, %rdx
movq %rbx, %r8
callq 0x301cc
addq %rax, (%r15)
jae 0x2adb5
addq $0x1, 0x8(%r15)
leaq 0x8(%r15), %r15
jb 0x2adaa
jmp 0x2ad23
movq %rbp, %rax
negq %rax
movq %rax, 0x10(%rsp)
movq %r12, %rcx
subq %rbp, %rcx
movq %r15, %rsi
movq %rbx, %rdx
callq 0x1c1c0
movq (%rbx,%rbp,8), %rbp
movq 0x30(%rsp), %rsi
leaq (%rbx,%rsi,8), %rcx
leaq (%rcx,%r14,8), %rcx
movq 0x10(%rsp), %r8
leaq (%rcx,%r8,8), %rdi
leaq (%r15,%rsi,8), %rcx
leaq (%rcx,%r14,8), %rcx
leaq (%rcx,%r8,8), %rsi
movq %rdi, %rdx
movq %r13, %rcx
movq %rax, %r8
callq 0x1c1a0
addq %rbp, %rax
subq %rax, (%r15)
jae 0x2ad23
cmpq $0x2, %r12
movl $0x1, %eax
cmovlq %rax, %r12
cmpq %rax, %r12
je 0x2ad23
subq $0x1, (%r15,%rax,8)
leaq 0x1(%rax), %rax
jb 0x2ae23
jmp 0x2ad23
movq %r13, %r8
movq %r15, %r9
jmp 0x2aa4e
movq %r13, %r12
movq %r15, %r14
jmp 0x2abd2
movq 0x18(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
movq 0x28(%rsp), %rbx
movq %rbx, %rdx
movq %r12, %rcx
movq %r14, %r8
callq 0x1cd58
subq %rbp, %rbx
addq %r14, %rbx
xorl %eax, %eax
cmpq %rbp, %rbx
setg %al
subq %rax, %rbx
leaq (,%rbp,8), %r14
addq %r13, %r14
movq %r13, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %r14, %rcx
movq %rbx, %r8
callq 0x1c078
movq $0x0, (%r14)
movq %r13, %rbx
movq %r13, %rcx
addq %rax, (%rcx)
jae 0x2aebd
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2aeb2
movq 0x10(%rsp), %r13
jmp 0x2ac37
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rcx
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1cd58