// File: marxn[P]pupp/3rdparty/gmp/mpn/toom_interpolate_7pts.c
// Function: _gmpn_toom_interpolate_7pts
void
mpn_toom_interpolate_7pts (mp_ptr rp, mp_size_t n, enum toom7_flags flags,
			   mp_ptr w1, mp_ptr w3, mp_ptr w4, mp_ptr w5,
			   mp_size_t w6n, mp_ptr tp)
{
  mp_size_t m;
  mp_limb_t cy;

  m = 2*n + 1;
#define w0 rp
#define w2 (rp + 2*n)
#define w6 (rp + 6*n)

  ASSERT (w6n > 0);
  ASSERT (w6n <= 2*n);

  /* Using formulas similar to Marco Bodrato's

     W5 = W5 + W4
     W1 =(W4 - W1)/2
     W4 = W4 - W0
     W4 =(W4 - W1)/4 - W6*16
     W3 =(W2 - W3)/2
     W2 = W2 - W3

     W5 = W5 - W2*65      May be negative.
     W2 = W2 - W6 - W0
     W5 =(W5 + W2*45)/2   Now >= 0 again.
     W4 =(W4 - W2)/3
     W2 = W2 - W4

     W1 = W5 - W1         May be negative.
     W5 =(W5 - W3*8)/9
     W3 = W3 - W5
     W1 =(W1/15 + W5)/2   Now >= 0 again.
     W5 = W5 - W1

     where W0 = f(0), W1 = f(-2), W2 = f(1), W3 = f(-1),
	   W4 = f(2), W5 = f(1/2), W6 = f(oo),

     Note that most intermediate results are positive; the ones that
     may be negative are represented in two's complement. We must
     never shift right a value that may be negative, since that would
     invalidate the sign bit. On the other hand, divexact by odd
     numbers work fine with two's complement.
  */

  mpn_add_n (w5, w5, w4, m);
  if (flags & toom7_w1_neg)
    {
#ifdef HAVE_NATIVE_mpn_rsh1add_n
      mpn_rsh1add_n (w1, w1, w4, m);
#else
      mpn_add_n (w1, w1, w4, m);  ASSERT (!(w1[0] & 1));
      mpn_rshift (w1, w1, m, 1);
#endif
    }
  else
    {
#ifdef HAVE_NATIVE_mpn_rsh1sub_n
      mpn_rsh1sub_n (w1, w4, w1, m);
#else
      mpn_sub_n (w1, w4, w1, m);  ASSERT (!(w1[0] & 1));
      mpn_rshift (w1, w1, m, 1);
#endif
    }
  mpn_sub (w4, w4, m, w0, 2*n);
  mpn_sub_n (w4, w4, w1, m);  ASSERT (!(w4[0] & 3));
  mpn_rshift (w4, w4, m, 2); /* w4>=0 */

  tp[w6n] = mpn_lshift (tp, w6, w6n, 4);
  mpn_sub (w4, w4, m, tp, w6n+1);

  if (flags & toom7_w3_neg)
    {
#ifdef HAVE_NATIVE_mpn_rsh1add_n
      mpn_rsh1add_n (w3, w3, w2, m);
#else
      mpn_add_n (w3, w3, w2, m);  ASSERT (!(w3[0] & 1));
      mpn_rshift (w3, w3, m, 1);
#endif
    }
  else
    {
#ifdef HAVE_NATIVE_mpn_rsh1sub_n
      mpn_rsh1sub_n (w3, w2, w3, m);
#else
      mpn_sub_n (w3, w2, w3, m);  ASSERT (!(w3[0] & 1));
      mpn_rshift (w3, w3, m, 1);
#endif
    }

  mpn_sub_n (w2, w2, w3, m);

  mpn_submul_1 (w5, w2, m, 65);
  mpn_sub (w2, w2, m, w6, w6n);
  mpn_sub (w2, w2, m, w0, 2*n);

  mpn_addmul_1 (w5, w2, m, 45);  ASSERT (!(w5[0] & 1));
  mpn_rshift (w5, w5, m, 1);
  mpn_sub_n (w4, w4, w2, m);

  mpn_divexact_by3 (w4, w4, m);
  mpn_sub_n (w2, w2, w4, m);

  mpn_sub_n (w1, w5, w1, m);
  mpn_lshift (tp, w3, m, 3);
  mpn_sub_n (w5, w5, tp, m);
  mpn_divexact_by9 (w5, w5, m);
  mpn_sub_n (w3, w3, w5, m);

  mpn_divexact_by15 (w1, w1, m);
  mpn_add_n (w1, w1, w5, m);  ASSERT (!(w1[0] & 1));
  mpn_rshift (w1, w1, m, 1); /* w1>=0 now */
  mpn_sub_n (w5, w5, w1, m);

  /* These bounds are valid for the 4x4 polynomial product of toom44,
   * and they are conservative for toom53 and toom62. */
  ASSERT (w1[2*n] < 2);
  ASSERT (w2[2*n] < 3);
  ASSERT (w3[2*n] < 4);
  ASSERT (w4[2*n] < 3);
  ASSERT (w5[2*n] < 2);

  /* Addition chain. Note carries and the 2n'th limbs that need to be
   * added in.
   *
   * Special care is needed for w2[2n] and the corresponding carry,
   * since the "simple" way of adding it all together would overwrite
   * the limb at wp[2*n] and rp[4*n] (same location) with the sum of
   * the high half of w3 and the low half of w4.
   *
   *         7    6    5    4    3    2    1    0
   *    |    |    |    |    |    |    |    |    |
   *                  ||w3 (2n+1)|
   *             ||w4 (2n+1)|
   *        ||w5 (2n+1)|        ||w1 (2n+1)|
   *  + | w6 (w6n)|        ||w2 (2n+1)| w0 (2n) |  (share storage with r)
   *  -----------------------------------------------
   *  r |    |    |    |    |    |    |    |    |
   *        c7   c6   c5   c4   c3                 Carries to propagate
   */

  cy = mpn_add_n (rp + n, rp + n, w1, m);
  MPN_INCR_U (w2 + n + 1, n , cy);
  cy = mpn_add_n (rp + 3*n, rp + 3*n, w3, n);
  MPN_INCR_U (w3 + n, n + 1, w2[2*n] + cy);
  cy = mpn_add_n (rp + 4*n, w3 + n, w4, n);
  MPN_INCR_U (w4 + n, n + 1, w3[2*n] + cy);
  cy = mpn_add_n (rp + 5*n, w4 + n, w5, n);
  MPN_INCR_U (w5 + n, n + 1, w4[2*n] + cy);
  if (w6n > n + 1)
    {
      cy = mpn_add_n (rp + 6*n, rp + 6*n, w5 + n, n + 1);
      MPN_INCR_U (rp + 7*n + 1, w6n - n - 1, cy);
    }
  else
    {
      ASSERT_NOCARRY (mpn_add_n (rp + 6*n, rp + 6*n, w5 + n, w6n));
#if WANT_ASSERT
      {
	mp_size_t i;
	for (i = w6n; i <= n; i++)
	  ASSERT (w5[n + i] == 0);
      }
#endif
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rax
shlq %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x4b30c
jmp 0x4b30e
jmp 0x4b310
movq 0x10(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36c80
movl -0x14(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x4b347
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x558f0
jmp 0x4b35c
movq -0x20(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x55a30
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq -0x8(%rbp), %rcx
movq -0x10(%rbp), %r8
shlq %r8
callq 0x36d60
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
jmp 0x4b38f
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x2, %ecx
callq 0x56880
movq 0x20(%rbp), %rdi
movq -0x8(%rbp), %rsi
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x18(%rbp), %rdx
movl $0x4, %ecx
callq 0x37320
movq %rax, %rdx
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq 0x20(%rbp), %rcx
movq 0x18(%rbp), %r8
addq $0x1, %r8
callq 0x36d60
movl -0x14(%rbp), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x4b423
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x8(%rbp), %rdx
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x38(%rbp), %rcx
callq 0x558f0
jmp 0x4b446
movq -0x28(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x55a30
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq 0x10(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movl $0x41, %ecx
callq 0x56760
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movq -0x8(%rbp), %rcx
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rcx
movq 0x18(%rbp), %r8
callq 0x36d60
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movq -0x8(%rbp), %rcx
movq -0x10(%rbp), %r8
shlq %r8
callq 0x36d60
movq 0x10(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x38(%rbp), %rdx
movl $0x2d, %ecx
callq 0x56650
jmp 0x4b53a
movq 0x10(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x1, %ecx
callq 0x56880
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x8(%rbp), %rdx
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq -0x30(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdx
movabsq $0x5555555555555555, %rcx # imm = 0x5555555555555555
xorl %eax, %eax
movl %eax, %r8d
callq 0x55430
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq -0x20(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq 0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x3, %ecx
callq 0x37320
movq 0x10(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq 0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq 0x10(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x9, %ecx
movabsq $-0x71c71c71c71c71c7, %r8 # imm = 0x8E38E38E38E38E39
xorl %r9d, %r9d
callq 0x553a8
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq 0x10(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rdx
movabsq $0x1111111111111111, %rcx # imm = 0x1111111111111111
xorl %eax, %eax
movl %eax, %r8d
callq 0x55430
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq 0x10(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36c80
jmp 0x4b673
movq -0x20(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x38(%rbp), %rdx
movl $0x1, %ecx
callq 0x56880
movq 0x10(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36fe0
jmp 0x4b6a0
jmp 0x4b6a2
jmp 0x4b6a4
jmp 0x4b6a6
jmp 0x4b6a8
jmp 0x4b6aa
jmp 0x4b6ac
jmp 0x4b6ae
jmp 0x4b6b0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x20(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rax
movq -0x10(%rbp), %rcx
shlq %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x10(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
addq $0x8, %rax
movq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x4b714
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x4b709
movq %rax, -0x48(%rbp)
jmp 0x4b71a
jmp 0x4b71c
movq -0x8(%rbp), %rdi
imulq $0x3, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
imulq $0x3, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
movq -0x10(%rbp), %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movq -0x10(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x8(%rbp), %rcx
movq -0x10(%rbp), %rdx
shlq %rdx
shlq $0x3, %rdx
addq %rdx, %rcx
movq -0x10(%rbp), %rdx
shlq %rdx
movq (%rcx,%rdx,8), %rcx
addq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x4b78d
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x4b782
movq %rax, -0x50(%rbp)
jmp 0x4b793
jmp 0x4b795
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x28(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rdx
movq -0x10(%rbp), %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rdx
shlq %rdx
movq (%rcx,%rdx,8), %rcx
addq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x4b7fa
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x4b7ef
movq %rax, -0x58(%rbp)
jmp 0x4b800
jmp 0x4b802
movq -0x8(%rbp), %rdi
imulq $0x5, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x30(%rbp), %rsi
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x10(%rbp), %rdx
movq -0x10(%rbp), %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
movq 0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rdx
shlq %rdx
movq (%rcx,%rdx,8), %rcx
addq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x4b864
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x4b859
movq %rax, -0x60(%rbp)
jmp 0x4b86a
jmp 0x4b86c
movq 0x18(%rbp), %rax
movq -0x10(%rbp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jle 0x4b8ef
movq -0x8(%rbp), %rdi
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x10(%rbp), %rdx
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq -0x10(%rbp), %rcx
addq $0x1, %rcx
callq 0x36c80
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rax
imulq $0x7, -0x10(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
addq $0x8, %rax
movq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x4b8e5
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x4b8da
movq %rax, -0x68(%rbp)
jmp 0x4b8eb
jmp 0x4b8ed
jmp 0x4b927
movq -0x8(%rbp), %rdi
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
imulq $0x6, -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq 0x10(%rbp), %rdx
movq -0x10(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdx
movq 0x18(%rbp), %rcx
callq 0x36c80
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)