// File: marxn[P]pupp/3rdparty/gmp/./mini-gmp/mini-gmp.c
// Function: mpz_powm
void
mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
{
  mpz_t tr;
  mpz_t base;
  mp_size_t en, mn;
  mp_srcptr mp;
  struct gmp_div_inverse minv;
  unsigned shift;
  mp_ptr tp = NULL;

  en = GMP_ABS (e->_mp_size);
  mn = GMP_ABS (m->_mp_size);
  if (mn == 0)
    gmp_die ("mpz_powm: Zero modulo.");

  if (en == 0)
    {
      mpz_set_ui (r, 1);
      return;
    }

  mp = m->_mp_d;
  mpn_div_qr_invert (&minv, mp, mn);
  shift = minv.shift;

  if (shift > 0)
    {
      /* To avoid shifts, we do all our reductions, except the final
	 one, using a *normalized* m. */
      minv.shift = 0;

      tp = gmp_xalloc_limbs (mn);
      gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
      mp = tp;
    }

  mpz_init (base);

  if (e->_mp_size < 0)
    {
      if (!mpz_invert (base, b, m))
	gmp_die ("mpz_powm: Negative exponent and non-invertible base.");
    }
  else
    {
      mp_size_t bn;
      mpz_abs (base, b);

      bn = base->_mp_size;
      if (bn >= mn)
	{
	  mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv);
	  bn = mn;
	}

      /* We have reduced the absolute value. Now take care of the
	 sign. Note that we get zero represented non-canonically as
	 m. */
      if (b->_mp_size < 0)
	{
	  mp_ptr bp = MPZ_REALLOC (base, mn);
	  gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn));
	  bn = mn;
	}
      base->_mp_size = mpn_normalized_size (base->_mp_d, bn);
    }
  mpz_init_set_ui (tr, 1);

  while (--en >= 0)
    {
      mp_limb_t w = e->_mp_d[en];
      mp_limb_t bit;

      bit = GMP_LIMB_HIGHBIT;
      do
	{
	  mpz_mul (tr, tr, tr);
	  if (w & bit)
	    mpz_mul (tr, tr, base);
	  if (tr->_mp_size > mn)
	    {
	      mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
	      tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
	    }
	  bit >>= 1;
	}
      while (bit > 0);
    }

  /* Final reduction */
  if (tr->_mp_size >= mn)
    {
      minv.shift = shift;
      mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
      tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
    }
  if (tp)
    gmp_free (tp);

  mpz_swap (r, tr);
  mpz_clear (tr);
  mpz_clear (base);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq $0x0, -0x88(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jl 0x778f
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xbc(%rbp)
jmp 0x779e
movq -0x18(%rbp), %rcx
xorl %eax, %eax
subl 0x4(%rcx), %eax
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
cltq
movq %rax, -0x48(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jl 0x77c3
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0xc0(%rbp)
jmp 0x77d2
movq -0x20(%rbp), %rcx
xorl %eax, %eax
subl 0x4(%rcx), %eax
movl %eax, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
cltq
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x77f1
leaq 0x6d5b(%rip), %rdi      # 0xe547
callq 0x7b50
cmpq $0x0, -0x48(%rbp)
jne 0x780b
movq -0x8(%rbp), %rdi
movl $0x1, %esi
callq 0x3350
jmp 0x7b3d
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdx
leaq -0x78(%rbp), %rdi
callq 0x7b80
movl -0x78(%rbp), %eax
movl %eax, -0x7c(%rbp)
cmpl $0x0, -0x7c(%rbp)
jbe 0x78a1
movl $0x0, -0x78(%rbp)
movq -0x50(%rbp), %rdi
callq 0x3220
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdx
movl -0x7c(%rbp), %ecx
callq 0x20b0
movq %rax, -0x90(%rbp)
cmpq $0x0, -0x90(%rbp)
jne 0x7875
jmp 0x7894
leaq 0x6c29(%rip), %rdi      # 0xe4a5
leaq 0x6851(%rip), %rsi      # 0xe0d4
movl $0xc21, %edx            # imm = 0xC21
leaq 0x6ccf(%rip), %rcx      # 0xe55e
callq 0x1070
jmp 0x7896
movq -0x88(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x31e0
movq -0x18(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jge 0x78db
leaq -0x40(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x7580
cmpl $0x0, %eax
jne 0x78d6
leaq 0x6ced(%rip), %rdi      # 0xe5be
callq 0x7b50
jmp 0x79e6
leaq -0x40(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x43f0
movslq -0x3c(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rax
cmpq -0x50(%rbp), %rax
jl 0x7928
movq -0x38(%rbp), %rsi
movslq -0x3c(%rbp), %rdx
movq -0x58(%rbp), %rcx
movq -0x50(%rbp), %r8
xorl %eax, %eax
movl %eax, %edi
leaq -0x78(%rbp), %r9
callq 0x7d60
movq -0x50(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jge 0x79d3
movq -0x50(%rbp), %rax
movslq -0x40(%rbp), %rcx
cmpq %rcx, %rax
jle 0x7959
leaq -0x40(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x3440
movq %rax, -0xc8(%rbp)
jmp 0x7964
movq -0x38(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rdi
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq -0xa0(%rbp), %rcx
movq -0x98(%rbp), %r8
callq 0x18f0
movq %rax, -0xa8(%rbp)
cmpq $0x0, -0xa8(%rbp)
jne 0x79a7
jmp 0x79c6
leaq 0x6af7(%rip), %rdi      # 0xe4a5
leaq 0x671f(%rip), %rsi      # 0xe0d4
movl $0xc3e, %edx            # imm = 0xC3E
leaq 0x6b9d(%rip), %rcx      # 0xe55e
callq 0x1070
jmp 0x79c8
movq -0x50(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x38(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x14d0
movl %eax, -0x3c(%rbp)
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
callq 0x3520
movq -0x48(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, %rax
jl 0x7ac3
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x48(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xb0(%rbp)
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
movq %rax, -0xb8(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x30(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x4e70
movq -0xb0(%rbp), %rax
andq -0xb8(%rbp), %rax
cmpq $0x0, %rax
je 0x7a68
leaq -0x30(%rbp), %rdi
leaq -0x30(%rbp), %rsi
leaq -0x40(%rbp), %rdx
callq 0x4e70
movslq -0x2c(%rbp), %rax
cmpq -0x50(%rbp), %rax
jle 0x7a9f
movq -0x28(%rbp), %rsi
movslq -0x2c(%rbp), %rdx
movq -0x58(%rbp), %rcx
movq -0x50(%rbp), %r8
xorl %eax, %eax
movl %eax, %edi
leaq -0x78(%rbp), %r9
callq 0x7d60
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x14d0
movl %eax, -0x2c(%rbp)
movq -0xb8(%rbp), %rax
shrq %rax
movq %rax, -0xb8(%rbp)
cmpq $0x0, -0xb8(%rbp)
ja 0x7a32
jmp 0x79f4
movslq -0x2c(%rbp), %rax
cmpq -0x50(%rbp), %rax
jl 0x7b00
movl -0x7c(%rbp), %eax
movl %eax, -0x78(%rbp)
movq -0x28(%rbp), %rsi
movslq -0x2c(%rbp), %rdx
movq -0x58(%rbp), %rcx
movq -0x50(%rbp), %r8
xorl %eax, %eax
movl %eax, %edi
leaq -0x78(%rbp), %r9
callq 0x7d60
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x14d0
movl %eax, -0x2c(%rbp)
cmpq $0x0, -0x88(%rbp)
je 0x7b1e
movq 0xb587(%rip), %rax      # 0x13098
movq -0x88(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
callq *%rax
movq -0x8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x4480
leaq -0x30(%rbp), %rdi
callq 0x32c0
leaq -0x40(%rbp), %rdi
callq 0x32c0
addq $0xd0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)