// File: marxn[P]pupp/3rdparty/gmp/mpn/toom43_mul.c
// Function: _gmpn_toom43_mul
void
mpn_toom43_mul (mp_ptr pp,
		mp_srcptr ap, mp_size_t an,
		mp_srcptr bp, mp_size_t bn, mp_ptr scratch)
{
  mp_size_t n, s, t;
  enum toom6_flags flags;
  mp_limb_t cy;

#define a0  ap
#define a1  (ap + n)
#define a2  (ap + 2 * n)
#define a3  (ap + 3 * n)
#define b0  bp
#define b1  (bp + n)
#define b2  (bp + 2 * n)

  n = 1 + (3 * an >= 4 * bn ? (an - 1) >> 2 : (bn - 1) / (size_t) 3);

  s = an - 3 * n;
  t = bn - 2 * n;

  ASSERT (0 < s && s <= n);
  ASSERT (0 < t && t <= n);

  /* This is true whenever an >= 25 or bn >= 19, I think. It
     guarantees that we can fit 5 values of size n+1 in the product
     area. */
  ASSERT (s+t >= 5);

#define v0    pp				/* 2n */
#define vm1   (scratch)				/* 2n+1 */
#define v1    (pp + 2*n)			/* 2n+1 */
#define vm2   (scratch + 2 * n + 1)		/* 2n+1 */
#define v2    (scratch + 4 * n + 2)		/* 2n+1 */
#define vinf  (pp + 5 * n)			/* s+t */
#define bs1    pp				/* n+1 */
#define bsm1  (scratch + 2 * n + 2)		/* n+1 */
#define asm1  (scratch + 3 * n + 3)		/* n+1 */
#define asm2  (scratch + 4 * n + 4)		/* n+1 */
#define bsm2  (pp + n + 1)			/* n+1 */
#define bs2   (pp + 2 * n + 2)			/* n+1 */
#define as2   (pp + 3 * n + 3)			/* n+1 */
#define as1   (pp + 4 * n + 4)			/* n+1 */

  /* Total sccratch need is 6 * n + 3 + 1; we allocate one extra
     limb, because products will overwrite 2n+2 limbs. */

#define a0a2  scratch
#define b0b2  scratch
#define a1a3  asm1
#define b1d   bsm1

  /* Compute as2 and asm2.  */
  flags = (enum toom6_flags) (toom6_vm2_neg & mpn_toom_eval_dgr3_pm2 (as2, asm2, ap, n, s, a1a3));

  /* Compute bs2 and bsm2.  */
  b1d[n] = mpn_lshift (b1d, b1, n, 1);			/*       2b1      */
  cy  = mpn_lshift (b0b2, b2, t, 2);			/*  4b2           */
  cy += mpn_add_n (b0b2, b0b2, b0, t);			/*  4b2      + b0 */
  if (t != n)
    cy = mpn_add_1 (b0b2 + t, b0 + t, n - t, cy);
  b0b2[n] = cy;

#if HAVE_NATIVE_mpn_add_n_sub_n
  if (mpn_cmp (b0b2, b1d, n+1) < 0)
    {
      mpn_add_n_sub_n (bs2, bsm2, b1d, b0b2, n+1);
      flags = (enum toom6_flags) (flags ^ toom6_vm2_neg);
    }
  else
    {
      mpn_add_n_sub_n (bs2, bsm2, b0b2, b1d, n+1);
    }
#else
  mpn_add_n (bs2, b0b2, b1d, n+1);
  if (mpn_cmp (b0b2, b1d, n+1) < 0)
    {
      mpn_sub_n (bsm2, b1d, b0b2, n+1);
      flags = (enum toom6_flags) (flags ^ toom6_vm2_neg);
    }
  else
    {
      mpn_sub_n (bsm2, b0b2, b1d, n+1);
    }
#endif

  /* Compute as1 and asm1.  */
  flags = (enum toom6_flags) (flags ^ (toom6_vm1_neg & mpn_toom_eval_dgr3_pm1 (as1, asm1, ap, n, s, a0a2)));

  /* Compute bs1 and bsm1.  */
  bsm1[n] = mpn_add (bsm1, b0, n, b2, t);
#if HAVE_NATIVE_mpn_add_n_sub_n
  if (bsm1[n] == 0 && mpn_cmp (bsm1, b1, n) < 0)
    {
      cy = mpn_add_n_sub_n (bs1, bsm1, b1, bsm1, n);
      bs1[n] = cy >> 1;
      flags = (enum toom6_flags) (flags ^ toom6_vm1_neg);
    }
  else
    {
      cy = mpn_add_n_sub_n (bs1, bsm1, bsm1, b1, n);
      bs1[n] = bsm1[n] + (cy >> 1);
      bsm1[n]-= cy & 1;
    }
#else
  bs1[n] = bsm1[n] + mpn_add_n (bs1, bsm1, b1, n);
  if (bsm1[n] == 0 && mpn_cmp (bsm1, b1, n) < 0)
    {
      mpn_sub_n (bsm1, b1, bsm1, n);
      flags = (enum toom6_flags) (flags ^ toom6_vm1_neg);
    }
  else
    {
      bsm1[n] -= mpn_sub_n (bsm1, bsm1, b1, n);
    }
#endif

  ASSERT (as1[n] <= 3);
  ASSERT (bs1[n] <= 2);
  ASSERT (asm1[n] <= 1);
  ASSERT (bsm1[n] <= 1);
  ASSERT (as2[n] <=14);
  ASSERT (bs2[n] <= 6);
  ASSERT (asm2[n] <= 9);
  ASSERT (bsm2[n] <= 4);

  /* vm1, 2n+1 limbs */
  mpn_mul_n (vm1, asm1, bsm1, n+1);  /* W4 */

  /* vm2, 2n+1 limbs */
  mpn_mul_n (vm2, asm2, bsm2, n+1);  /* W2 */

  /* v2, 2n+1 limbs */
  mpn_mul_n (v2, as2, bs2, n+1);  /* W1 */

  /* v1, 2n+1 limbs */
  mpn_mul_n (v1, as1, bs1, n+1);  /* W3 */

  /* vinf, s+t limbs */   /* W0 */
  if (s > t)  mpn_mul (vinf, a3, s, b2, t);
  else        mpn_mul (vinf, b2, t, a3, s);

  /* v0, 2n limbs */
  mpn_mul_n (v0, ap, bp, n);  /* W5 */

  mpn_toom_interpolate_6pts (pp, n, flags, vm1, vm2, v2, t + s);

#undef v0
#undef vm1
#undef v1
#undef vm2
#undef v2
#undef vinf
#undef bs1
#undef bs2
#undef bsm1
#undef bsm2
#undef asm1
#undef asm2
/* #undef as1 */
/* #undef as2 */
#undef a0a2
#undef b0b2
#undef a1a3
#undef b1d
#undef a0
#undef a1
#undef a2
#undef a3
#undef b0
#undef b1
#undef b2
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
imulq $0x3, -0x18(%rbp), %rax
movq -0x28(%rbp), %rcx
shlq $0x2, %rcx
cmpq %rcx, %rax
jl 0x40be7
movq -0x18(%rbp), %rax
subq $0x1, %rax
sarq $0x2, %rax
movq %rax, -0x60(%rbp)
jmp 0x40bfd
movq -0x28(%rbp), %rax
subq $0x1, %rax
movl $0x3, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rax
imulq $0x3, -0x38(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
subq %rcx, %rax
movq %rax, -0x48(%rbp)
jmp 0x40c2d
jmp 0x40c2f
jmp 0x40c31
jmp 0x40c33
jmp 0x40c35
movq -0x8(%rbp), %rdi
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x18, %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x20, %rsi
movq -0x10(%rbp), %rdx
movq -0x38(%rbp), %rcx
movq -0x40(%rbp), %r8
movq -0x30(%rbp), %r9
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %r9
addq $0x18, %r9
callq 0x49be0
andl $0x2, %eax
movl %eax, -0x4c(%rbp)
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movl $0x1, %ecx
callq 0x37320
movq %rax, %rdx
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x38(%rbp), %rcx
movq %rdx, 0x10(%rax,%rcx,8)
movq -0x30(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x48(%rbp), %rdx
movl $0x2, %ecx
callq 0x37320
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x48(%rbp), %rcx
callq 0x36c80
addq -0x58(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x38(%rbp), %rax
je 0x40d5e
movq -0x30(%rbp), %rdi
movq -0x48(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x20(%rbp), %rsi
movq -0x48(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
subq -0x48(%rbp), %rdx
movq -0x58(%rbp), %rcx
callq 0x564f0
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdx
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x30(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x10, %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x36c80
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x38(%rbp), %rdx
addq $0x1, %rdx
callq 0x3b060
cmpl $0x0, %eax
jge 0x40e1c
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x8, %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x36fe0
movl -0x4c(%rbp), %eax
xorl $0x2, %eax
movl %eax, -0x4c(%rbp)
jmp 0x40e56
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x8, %rdi
movq -0x30(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x10, %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x36fe0
movl -0x4c(%rbp), %eax
movl %eax, -0x6c(%rbp)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x20, %rdi
movq -0x30(%rbp), %rsi
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x18, %rsi
movq -0x10(%rbp), %rdx
movq -0x38(%rbp), %rcx
movq -0x40(%rbp), %r8
movq -0x30(%rbp), %r9
callq 0x49ac0
movl %eax, %ecx
movl -0x6c(%rbp), %eax
andl $0x1, %ecx
xorl %ecx, %eax
movl %eax, -0x4c(%rbp)
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rcx
movq -0x48(%rbp), %r8
callq 0x36b60
movq %rax, %rdx
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x38(%rbp), %rcx
movq %rdx, 0x10(%rax,%rcx,8)
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rax
movq %rax, -0x68(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x38(%rbp), %rcx
callq 0x36c80
movq -0x68(%rbp), %rdx
addq %rax, %rdx
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x38(%rbp), %rcx
cmpq $0x0, 0x10(%rax,%rcx,8)
jne 0x41008
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
callq 0x3b060
cmpl $0x0, %eax
jge 0x41008
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x10, %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movl -0x4c(%rbp), %eax
xorl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x41072
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq %rax, %rsi
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x38(%rbp), %rcx
movq 0x10(%rax,%rcx,8), %rdx
subq %rsi, %rdx
movq %rdx, 0x10(%rax,%rcx,8)
jmp 0x41074
jmp 0x41076
jmp 0x41078
jmp 0x4107a
jmp 0x4107c
jmp 0x4107e
jmp 0x41080
jmp 0x41082
jmp 0x41084
jmp 0x41086
jmp 0x41088
jmp 0x4108a
jmp 0x4108c
jmp 0x4108e
jmp 0x41090
jmp 0x41092
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x18, %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x10, %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x39000
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x8, %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x20, %rsi
movq -0x8(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x8, %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x39000
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x8(%rbp), %rsi
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x18, %rsi
movq -0x8(%rbp), %rdx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
addq $0x10, %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x39000
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x20, %rsi
movq -0x8(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x1, %rcx
callq 0x39000
movq -0x40(%rbp), %rax
cmpq -0x48(%rbp), %rax
jle 0x411ed
movq -0x8(%rbp), %rdi
imulq $0x5, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x40(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rcx
movq -0x48(%rbp), %r8
callq 0x37f00
jmp 0x4122c
movq -0x8(%rbp), %rdi
imulq $0x5, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x48(%rbp), %rdx
movq -0x10(%rbp), %rcx
imulq $0x3, -0x38(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rcx
movq -0x40(%rbp), %r8
callq 0x37f00
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x39000
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
movl -0x4c(%rbp), %edx
movq -0x30(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x38(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %r8
addq $0x8, %r8
movq -0x30(%rbp), %r9
movq -0x38(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %r9
addq $0x10, %r9
movq -0x48(%rbp), %rax
addq -0x40(%rbp), %rax
movq %rax, (%rsp)
callq 0x4ab30
addq $0x80, %rsp
popq %rbp
retq
nopw (%rax,%rax)