// File: /workspace/github_cpp_makefile_star2_O2/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 $0x58, %rsp
movq %r8, %r10
movq %rdx, %r12
movq %rsi, %r14
movq %rdi, %r13
movq 0x90(%rsp), %r15
testb $0x1, %r14b
sete %al
cmpq $0x12, %rsi
setge %dl
testb %al, %dl
je 0x25109
movq %r13, 0x18(%rsp)
movq %r14, %rbp
shrq %rbp
movq %rcx, %r13
subq %rbp, %r13
movq %r9, 0x28(%rsp)
movq %rcx, 0x38(%rsp)
movq %r10, 0x20(%rsp)
jle 0x25246
leaq (%r12,%rbp,8), %rcx
movq %r15, %rdi
movq %r12, %rsi
movq %rbp, %rdx
movq %rcx, 0x48(%rsp)
movq %r13, %r8
callq 0x17c54
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq %r15, %rcx
addq %rax, (%rcx)
jae 0x24fd3
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x24fc8
leaq (%r15,%rbp,8), %rbx
movq %rdx, %r8
leaq (%rsi,%rbp,8), %rcx
subq %rbp, %r8
movq %r12, 0x10(%rsp)
movq %rcx, 0x40(%rsp)
jle 0x25334
movq %rbx, %rdi
movq %rbp, %rdx
callq 0x17c54
leaq (%rbx,%rbp,8), %rcx
movq %rbx, %r8
addq %rax, (%rbx)
jae 0x25013
addq $0x1, 0x8(%rbx)
leaq 0x8(%rbx), %rbx
jb 0x25008
movq %rbp, %r9
movq %rcx, %rbx
movq %rbx, (%rsp)
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
movq %r15, %rdx
movq %rbp, %rcx
callq 0x24f3e
leaq (%r15,%r14,8), %rbx
movq %r15, %rax
movq %r14, %r15
movq %rax, 0x30(%rsp)
leaq 0x10(%rax,%r14,8), %r14
movq %r14, %rdi
movq 0x10(%rsp), %rsi
movq %rbp, %rdx
movq 0x48(%rsp), %rcx
movq %r13, %r8
callq 0x17dc8
andq $0x0, 0x10(%rbx,%rbp,8)
movq %r14, %rcx
addq %rax, (%rcx)
jae 0x25075
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2506a
movq 0x10(%rbx,%rbp,8), %rax
addq %rbp, %rax
movq %rax, 0x10(%rsp)
movq 0x28(%rsp), %r13
movq %r13, %r8
subq %rbp, %r8
jle 0x2533f
leaq (%rbx,%rbp,8), %rbx
addq $0x10, %rbx
leaq 0x8(%rbx), %r12
movq %r12, %rdi
movq 0x20(%rsp), %rsi
movq %rbp, %rdx
movq 0x40(%rsp), %rcx
callq 0x17dc8
andq $0x0, 0x8(%r14,%r15,8)
movq %r12, %rcx
addq %rax, (%rcx)
jae 0x250cd
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x250c2
movq 0x8(%rbx,%rbp,8), %r13
addq %rbp, %r13
movq %r14, %rdx
movq %r15, %r14
movq 0x30(%rsp), %r15
cmpq $0x51b, %r14            # imm = 0x51B
jb 0x2515b
movq %rdx, %rbx
movq %rbp, %rdi
xorl %esi, %esi
callq 0x2a2c8
pushq $-0x1
popq %rdx
movl %eax, %ecx
shll %cl, %edx
notl %edx
testl %edx, %ebp
je 0x25134
decl %eax
shrl %edx
jmp 0x250ff
cmpq %r14, %r9
jl 0x25278
movq %r13, %rdi
movq %r12, %rsi
movq %r10, %rdx
movq %r14, %rcx
movq %r15, %r8
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x24f00
cmpl $0x4, %eax
movq %rbx, %rdx
jl 0x2515b
movl %eax, (%rsp)
movq %r15, %rdi
movq %rbp, %rsi
movq 0x10(%rsp), %rcx
movq %r12, %r8
movq %r13, %r9
callq 0x2a311
movq %rax, (%r15,%rbp,8)
jmp 0x251ab
cmpq 0x20(%rsp), %r12
je 0x25349
leaq 0x1(%rbp), %rcx
movq %r15, %rdi
movq %rdx, %rsi
movq %r12, %rdx
callq 0x19500
movq (%r15,%r14,8), %r12
leaq (%r15,%rbp,8), %rbx
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
callq 0x17ed0
andq $0x0, (%rbx)
addq %r12, %rax
movq %r15, %rcx
addq %rax, (%rcx)
jae 0x251ab
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x251a0
movq (%r15,%rbp,8), %r8
movq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r12, %rsi
movq %r15, %rdx
movq %rbp, %rcx
callq 0x294e0
shlq $0x3f, %rax
leaq (%r12,%rbp,8), %rdi
movq -0x8(%rdi), %rcx
movq %rax, 0x50(%rsp)
xorl %eax, %eax
addq 0x50(%rsp), %rcx
adcq $0x0, %rax
movq %rcx, -0x8(%rdi)
movq %r12, %rcx
addq %rax, (%rcx)
jae 0x251f8
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x251ed
movq 0x28(%rsp), %rax
movq 0x38(%rsp), %r8
leaq (%rax,%r8), %rbx
subq %rbx, %r14
jg 0x252c4
movq (%r15,%rbp,8), %rbx
movq %r12, %rsi
movq %r15, %rdx
movq %rbp, %rcx
callq 0x17ed0
addq %rbx, %rax
subq %rax, (%r12)
jae 0x25237
subq $0x1, 0x8(%r12)
leaq 0x8(%r12), %r12
jb 0x2522a
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r15, (%rsp)
movq 0x18(%rsp), %rdi
movq %rbp, %rsi
movq %r12, %rdx
movq %r10, %r8
movq %r9, %r13
movq %r10, %rbx
callq 0x24f3e
movq %r12, %rdx
movq %rbx, %r12
movq 0x38(%rsp), %rax
movq %rax, 0x10(%rsp)
jmp 0x250e0
leaq (%r9,%rcx), %rbx
subq %r14, %rbx
jle 0x253a8
movq %r15, %rdi
movq %r12, %rsi
movq %rcx, %rdx
movq %r10, %rcx
movq %r9, %r8
callq 0x18a58
leaq (%r15,%r14,8), %rcx
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rdx
movq %rbx, %r8
callq 0x17c54
addq %rax, (%r13)
jae 0x252bf
addq $0x1, 0x8(%r13)
leaq 0x8(%r13), %r13
jb 0x252b4
jmp 0x25237
movq %rbp, %r13
negq %r13
movq %rbx, %rcx
subq %rbp, %rcx
movq %r12, %rsi
movq %r15, %rdx
movq %r8, %r12
callq 0x17ed0
movq (%r15,%rbp,8), %rbp
leaq (%r15,%r12,8), %rcx
movq 0x28(%rsp), %rdx
leaq (%rcx,%rdx,8), %rcx
leaq (%rcx,%r13,8), %rdi
movq 0x18(%rsp), %r15
leaq (%r15,%r12,8), %rcx
leaq (%rcx,%rdx,8), %rcx
leaq (%rcx,%r13,8), %rsi
movq %rdi, %rdx
movq %r14, %rcx
movq %rax, %r8
callq 0x17eb0
addq %rax, %rbp
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x17e44
movq %rsi, %r8
movq %rdx, %r9
jmp 0x25019
movq 0x20(%rsp), %r12
jmp 0x250d5
movq %r15, %rdi
movq %rdx, %rsi
movq 0x10(%rsp), %rbx
movq %rbx, %rdx
movq %r12, %rcx
movq %r13, %r8
callq 0x18a58
subq %rbp, %rbx
addq %r13, %rbx
xorl %eax, %eax
cmpq %rbp, %rbx
setg %al
subq %rax, %rbx
leaq (%r15,%rbp,8), %r12
movq %r15, %rdi
movq %r15, %rsi
movq %rbp, %rdx
movq %r12, %rcx
movq %rbx, %r8
callq 0x17dc8
andq $0x0, (%r12)
movq %r15, %rcx
addq %rax, (%rcx)
jae 0x253a3
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x25398
jmp 0x251ab
movq %r13, %rdi
movq %r12, %rsi
movq %rcx, %rdx
movq %r10, %rcx
movq %r9, %r8
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x18a58