// File: marxn[P]pupp/3rdparty/gmp/mpn/mul_fft.c
// Function: _gmpn_mul_fft
mp_limb_t
mpn_mul_fft (mp_ptr op, mp_size_t pl,
	     mp_srcptr n, mp_size_t nl,
	     mp_srcptr m, mp_size_t ml,
	     int k)
{
  int i;
  mp_size_t K, maxLK;
  mp_size_t N, Nprime, nprime, M, Mp, l;
  mp_ptr *Ap, *Bp, A, T, B;
  int **fft_l, *tmp;
  int sqr = (n == m && nl == ml);
  mp_limb_t h;
  TMP_DECL;

  TRACE (printf ("\nmpn_mul_fft pl=%ld nl=%ld ml=%ld k=%d\n", pl, nl, ml, k));
  ASSERT_ALWAYS (mpn_fft_next_size (pl, k) == pl);

  TMP_MARK;
  N = pl * GMP_NUMB_BITS;
  fft_l = TMP_BALLOC_TYPE (k + 1, int *);
  tmp = TMP_BALLOC_TYPE ((size_t) 2 << k, int);
  for (i = 0; i <= k; i++)
    {
      fft_l[i] = tmp;
      tmp += (mp_size_t) 1 << i;
    }

  mpn_fft_initl (fft_l, k);
  K = (mp_size_t) 1 << k;
  M = N >> k;	/* N = 2^k M */
  l = 1 + (M - 1) / GMP_NUMB_BITS;
  maxLK = mpn_mul_fft_lcm (GMP_NUMB_BITS, k); /* lcm (GMP_NUMB_BITS, 2^k) */

  Nprime = (1 + (2 * M + k + 2) / maxLK) * maxLK;
  /* Nprime = ceil((2*M+k+3)/maxLK)*maxLK; */
  nprime = Nprime / GMP_NUMB_BITS;
  TRACE (printf ("N=%ld K=%ld, M=%ld, l=%ld, maxLK=%ld, Np=%ld, np=%ld\n",
		 N, K, M, l, maxLK, Nprime, nprime));
  /* we should ensure that recursively, nprime is a multiple of the next K */
  if (nprime >= (sqr ? SQR_FFT_MODF_THRESHOLD : MUL_FFT_MODF_THRESHOLD))
    {
      mp_size_t K2;
      for (;;)
	{
	  K2 = (mp_size_t) 1 << mpn_fft_best_k (nprime, sqr);
	  if ((nprime & (K2 - 1)) == 0)
	    break;
	  nprime = (nprime + K2 - 1) & -K2;
	  Nprime = nprime * GMP_LIMB_BITS;
	  /* warning: since nprime changed, K2 may change too! */
	}
      TRACE (printf ("new maxLK=%ld, Np=%ld, np=%ld\n", maxLK, Nprime, nprime));
    }
  ASSERT_ALWAYS (nprime < pl); /* otherwise we'll loop */

  T = TMP_BALLOC_LIMBS (2 * (nprime + 1));
  Mp = Nprime >> k;

  TRACE (printf ("%ldx%ld limbs -> %ld times %ldx%ld limbs (%1.2f)\n",
		pl, pl, K, nprime, nprime, 2.0 * (double) N / Nprime / K);
	 printf ("   temp space %ld\n", 2 * K * (nprime + 1)));

  A = TMP_BALLOC_LIMBS (K * (nprime + 1));
  Ap = TMP_BALLOC_MP_PTRS (K);
  mpn_mul_fft_decompose (A, Ap, K, nprime, n, nl, l, Mp, T);
  if (sqr)
    {
      mp_size_t pla;
      pla = l * (K - 1) + nprime + 1; /* number of required limbs for p */
      B = TMP_BALLOC_LIMBS (pla);
      Bp = TMP_BALLOC_MP_PTRS (K);
    }
  else
    {
      B = TMP_BALLOC_LIMBS (K * (nprime + 1));
      Bp = TMP_BALLOC_MP_PTRS (K);
      mpn_mul_fft_decompose (B, Bp, K, nprime, m, ml, l, Mp, T);
    }
  h = mpn_mul_fft_internal (op, pl, k, Ap, Bp, A, B, nprime, l, Mp, fft_l, T, sqr);

  TMP_FREE;
  return h;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x120, %rsp            # imm = 0x120
movl 0x10(%rbp), %eax
movq %rdi, -0x28(%rbp)
movq %rsi, -0x30(%rbp)
movq %rdx, -0x38(%rbp)
movq %rcx, -0x40(%rbp)
movq %r8, -0x48(%rbp)
movq %r9, -0x50(%rbp)
movq -0x38(%rbp), %rcx
xorl %eax, %eax
cmpq -0x48(%rbp), %rcx
movb %al, -0xf9(%rbp)
jne 0x56bc0
movq -0x40(%rbp), %rax
cmpq -0x50(%rbp), %rax
sete %al
movb %al, -0xf9(%rbp)
movb -0xf9(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0xd4(%rbp)
movq -0x30(%rbp), %rdi
movl 0x10(%rbp), %esi
callq 0x56b40
cmpq -0x30(%rbp), %rax
sete %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x56c16
leaq 0xd44b(%rip), %rdi      # 0x64050
movl $0x349, %esi            # imm = 0x349
leaq 0xd449(%rip), %rdx      # 0x6405a
callq 0x562c0
jmp 0x56c18
movq $0x0, -0xe8(%rbp)
movq -0x30(%rbp), %rax
shlq $0x6, %rax
movq %rax, -0x70(%rbp)
movl 0x10(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xc8(%rbp)
movl 0x10(%rbp), %eax
movl %eax, %ecx
movl $0x2, %esi
shlq %cl, %rsi
shlq $0x2, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xd0(%rbp)
movl $0x0, -0x54(%rbp)
movl -0x54(%rbp), %eax
cmpl 0x10(%rbp), %eax
jg 0x56cc2
movq -0xd0(%rbp), %rdx
movq -0xc8(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x54(%rbp), %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
shlq $0x2, %rax
addq -0xd0(%rbp), %rax
movq %rax, -0xd0(%rbp)
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x56c7a
movq -0xc8(%rbp), %rdi
movl 0x10(%rbp), %esi
callq 0x570a0
movl 0x10(%rbp), %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0x60(%rbp)
movq -0x70(%rbp), %rax
movl 0x10(%rbp), %ecx
sarq %cl, %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
subq $0x1, %rax
movl $0x40, %ecx
cqto
idivq %rcx
addq $0x1, %rax
movq %rax, -0x98(%rbp)
movl 0x10(%rbp), %esi
movl $0x40, %edi
callq 0x57160
movq %rax, -0x68(%rbp)
movq -0x88(%rbp), %rax
shlq %rax
movslq 0x10(%rbp), %rcx
addq %rcx, %rax
addq $0x2, %rax
cqto
idivq -0x68(%rbp)
addq $0x1, %rax
imulq -0x68(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movl $0x40, %ecx
cqto
idivq %rcx
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movl -0xd4(%rbp), %esi
movl $0x28e, %ecx            # imm = 0x28E
movl $0x23a, %edx            # imm = 0x23A
cmpl $0x0, %esi
cmovnel %edx, %ecx
movslq %ecx, %rcx
cmpq %rcx, %rax
jl 0x56ded
jmp 0x56d82
movq -0x80(%rbp), %rdi
movl -0xd4(%rbp), %esi
callq 0x56ab0
movl %eax, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0xf0(%rbp)
movq -0x80(%rbp), %rax
movq -0xf0(%rbp), %rcx
subq $0x1, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x56dbe
jmp 0x56deb
movq -0x80(%rbp), %rax
addq -0xf0(%rbp), %rax
subq $0x1, %rax
xorl %ecx, %ecx
subq -0xf0(%rbp), %rcx
andq %rcx, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
shlq $0x6, %rax
movq %rax, -0x78(%rbp)
jmp 0x56d82
jmp 0x56ded
jmp 0x56def
movq -0x80(%rbp), %rax
cmpq -0x30(%rbp), %rax
setl %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x56e2c
leaq 0xd235(%rip), %rdi      # 0x64050
movl $0x36f, %esi            # imm = 0x36F
leaq 0xd256(%rip), %rdx      # 0x6407d
callq 0x562c0
jmp 0x56e2e
movq -0x80(%rbp), %rsi
addq $0x1, %rsi
shlq %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xb8(%rbp)
movq -0x78(%rbp), %rax
movl 0x10(%rbp), %ecx
sarq %cl, %rax
movq %rax, -0x90(%rbp)
movq -0x60(%rbp), %rsi
movq -0x80(%rbp), %rax
addq $0x1, %rax
imulq %rax, %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xb0(%rbp)
movq -0x60(%rbp), %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xa0(%rbp)
movq -0xb0(%rbp), %rdi
movq -0xa0(%rbp), %rsi
movq -0x60(%rbp), %rdx
movq -0x80(%rbp), %rcx
movq -0x38(%rbp), %r8
movq -0x40(%rbp), %r9
movq -0x98(%rbp), %r11
movq -0x90(%rbp), %r10
movq -0xb8(%rbp), %rax
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x571c0
cmpl $0x0, -0xd4(%rbp)
je 0x56f52
movq -0x98(%rbp), %rax
movq -0x60(%rbp), %rcx
subq $0x1, %rcx
imulq %rcx, %rax
addq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xc0(%rbp)
movq -0x60(%rbp), %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xa8(%rbp)
jmp 0x56fda
movq -0x60(%rbp), %rsi
movq -0x80(%rbp), %rax
addq $0x1, %rax
imulq %rax, %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xc0(%rbp)
movq -0x60(%rbp), %rsi
shlq $0x3, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x56430
movq %rax, -0xa8(%rbp)
movq -0xc0(%rbp), %rdi
movq -0xa8(%rbp), %rsi
movq -0x60(%rbp), %rdx
movq -0x80(%rbp), %rcx
movq -0x48(%rbp), %r8
movq -0x50(%rbp), %r9
movq -0x98(%rbp), %r11
movq -0x90(%rbp), %r10
movq -0xb8(%rbp), %rax
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x571c0
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
movl 0x10(%rbp), %edx
movq -0xa0(%rbp), %rcx
movq -0xa8(%rbp), %r8
movq -0xb0(%rbp), %r9
movq -0xc0(%rbp), %r12
movq -0x80(%rbp), %r15
movq -0x98(%rbp), %r14
movq -0x90(%rbp), %rbx
movq -0xc8(%rbp), %r11
movq -0xb8(%rbp), %r10
movl -0xd4(%rbp), %eax
movq %r12, (%rsp)
movq %r15, 0x8(%rsp)
movq %r14, 0x10(%rsp)
movq %rbx, 0x18(%rsp)
movq %r11, 0x20(%rsp)
movq %r10, 0x28(%rsp)
movl %eax, 0x30(%rsp)
callq 0x57650
movq %rax, -0xe0(%rbp)
cmpq $0x0, -0xe8(%rbp)
setne %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x57083
movq -0xe8(%rbp), %rdi
callq 0x564a0
jmp 0x57085
movq -0xe0(%rbp), %rax
addq $0x120, %rsp            # imm = 0x120
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)