// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %r9, %rbp
movq %r8, 0x18(%rsp)
movq %rcx, %r13
movl %edx, %r12d
movq %rsi, %r14
movq %rdi, %r15
movq 0xa0(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x90(%rsp), %rdi
leaq (%rsi,%rsi), %rax
movq %rax, 0x10(%rsp)
leaq 0x1(%rsi,%rsi), %rbx
movq %rdi, 0x40(%rsp)
movq %rdi, %rsi
movq %r9, %rdx
movq %rbx, %rcx
callq 0x17cf0
movl %r12d, 0x8(%rsp)
movq %r13, %rdi
testb $0x1, %r12b
jne 0x234e3
movq %rbp, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x29630
jmp 0x234f1
movq %r13, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
callq 0x294f0
movq %rbp, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
movq %r15, %rcx
movq 0x10(%rsp), %r8
callq 0x17dc8
movq %rbp, %rdi
movq %rbp, %rsi
movq %r13, 0x48(%rsp)
movq %r13, %rdx
movq %rbx, %rcx
callq 0x17ed0
pushq $0x2
popq %rcx
movq %rbp, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x2a0a0
movq %r14, 0x50(%rsp)
movq %rbp, %r13
imulq $0x30, %r14, %rbp
addq %r15, %rbp
pushq $0x4
popq %rcx
movq 0x28(%rsp), %r12
movq %r12, %rdi
movq %rbp, %rsi
movq 0x20(%rsp), %r14
movq %r14, %rdx
callq 0x181a0
movq %rax, (%r12,%r14,8)
leaq 0x1(%r14), %r8
movq %r13, %rdi
movq %r13, 0x30(%rsp)
movq %r13, %rsi
movq %rbx, %rdx
movq %r12, %rcx
callq 0x17dc8
movq %r15, 0x38(%rsp)
movq 0x10(%rsp), %rax
leaq (%r15,%rax,8), %r15
testb $0x2, 0x8(%rsp)
jne 0x235a3
movq 0x18(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x29630
jmp 0x235b9
movq 0x18(%rsp), %r14
movq %r14, %rdi
movq %r14, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x294f0
movq %r15, %rdi
movq %r15, %rsi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x17ed0
pushq $0x41
popq %rcx
movq 0x40(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x29f90
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %rbp, %rcx
movq 0x20(%rsp), %r8
callq 0x17dc8
movq %r15, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq 0x38(%rsp), %rcx
movq 0x10(%rsp), %r8
callq 0x17dc8
pushq $0x2d
popq %rcx
movq %r12, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x29e80
pushq $0x1
popq %rcx
movq %r12, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x2a0a0
movq 0x30(%rsp), %r13
movq %r13, %rdi
movq %r13, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x17ed0
movabsq $0x5555555555555555, %rcx # imm = 0x5555555555555555
movq %r13, %rdi
movq %r13, %rsi
movq %rbx, %rdx
xorl %r8d, %r8d
callq 0x29020
movq %r15, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x17ed0
movq 0x48(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x17ed0
pushq $0x3
popq %rcx
movq %rbp, 0x8(%rsp)
movq 0x28(%rsp), %rbp
movq %rbp, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x181a0
movq %r12, %rdi
movq %r12, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
callq 0x17ed0
pushq $0x9
popq %rcx
movabsq $-0x71c71c71c71c71c7, %r8 # imm = 0x8E38E38E38E38E39
movq %r12, %rdi
movq %r12, %rsi
movq %rbx, %rdx
xorl %r9d, %r9d
callq 0x28f98
movq %r14, %rdi
movq %r14, %rsi
movq %r12, %rdx
movq %rbx, %rcx
callq 0x17ed0
movabsq $0x1111111111111111, %rcx # imm = 0x1111111111111111
movq %r13, %rdi
movq %r13, %rsi
movq %rbx, %rdx
xorl %r8d, %r8d
callq 0x29020
movq %r13, %rdi
movq %r13, %rsi
movq %r12, %rdx
movq %rbx, %rcx
callq 0x17cf0
movq %r13, %rdi
movq %r13, %rsi
movq %rbx, %rdx
pushq $0x1
popq %rcx
callq 0x2a0a0
movq %r12, %rdi
movq %r12, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x17ed0
movq 0x50(%rsp), %r14
movq 0x38(%rsp), %rbp
leaq (,%r14,8), %rdi
addq %rbp, %rdi
movq %rdi, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x17cf0
leaq (%r15,%r14,8), %rcx
addq $0x8, %rcx
addq %rax, (%rcx)
jae 0x2376c
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x23761
imulq $0x18, %r14, %rdi
movq %rbp, %rbx
addq %rbp, %rdi
movq %rdi, %rsi
movq 0x18(%rsp), %rbp
movq %rbp, %rdx
movq %r14, %rcx
callq 0x17cf0
movq 0x10(%rsp), %r13
addq (%r15,%r13,8), %rax
leaq (,%r14,8), %rsi
addq %rbp, %rsi
movq %rsi, %rcx
addq %rax, (%rcx)
jae 0x237b0
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x237a5
movq %r14, %rdi
shlq $0x5, %rdi
addq %rbx, %rdi
movq 0x30(%rsp), %r15
movq %r15, %rdx
movq %r14, %rcx
callq 0x17cf0
addq (%rbp,%r13,8), %rax
leaq (%r15,%r14,8), %rsi
movq %rsi, %rcx
addq %rax, (%rcx)
jae 0x237e6
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x237db
imulq $0x28, %r14, %rdi
addq %rbx, %rdi
movq %r12, %rdx
movq %r14, %rcx
callq 0x17cf0
movq 0x20(%rsp), %r8
addq (%r15,%r13,8), %rax
leaq (%r12,%r14,8), %rdx
movq %rdx, %rcx
addq %rax, (%rcx)
jae 0x23818
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2380d
leaq 0x1(%r14), %rcx
cmpq %r8, %rcx
jge 0x23858
movq 0x8(%rsp), %rdi
movq %rdi, %rsi
callq 0x17cf0
imulq $0x38, %r14, %rcx
addq %rbx, %rcx
addq $0x8, %rcx
addq %rax, (%rcx)
jae 0x23849
addq $0x1, 0x8(%rcx)
leaq 0x8(%rcx), %rcx
jb 0x2383e
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rdi
movq %rdi, %rsi
movq %r8, %rcx
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x17cf0
nop