toom_interpolate_16pts.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:17k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. /* Interpolaton for the algorithm Toom-Cook 8.5-way.
  2.    Contributed to the GNU project by Marco Bodrato.
  3.    THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
  4.    SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
  5.    GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
  6. Copyright 2009, 2010 Free Software Foundation, Inc.
  7. This file is part of the GNU MP Library.
  8. The GNU MP Library is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU Lesser General Public License as published by
  10. the Free Software Foundation; either version 3 of the License, or (at your
  11. option) any later version.
  12. The GNU MP Library is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14. or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  15. License for more details.
  16. You should have received a copy of the GNU Lesser General Public License
  17. along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
  18. #include "gmp.h"
  19. #include "gmp-impl.h"
  20. #if GMP_NUMB_BITS < 29
  21. #error Not implemented: Both sublsh_n(,,,28) should be corrected; r2 and r5 need one more LIMB.
  22. #endif
  23. #if GMP_NUMB_BITS < 28
  24. #error Not implemented: divexact_by188513325 and _by182712915 will not work.
  25. #endif
  26. #if HAVE_NATIVE_mpn_sublsh_n
  27. #define DO_mpn_sublsh_n(dst,src,n,s,ws) mpn_sublsh_n(dst,dst,src,n,s)
  28. #else
  29. static mp_limb_t
  30. DO_mpn_sublsh_n(mp_ptr dst, mp_srcptr src, mp_size_t n, unsigned int s, mp_ptr ws)
  31. {
  32. #if USE_MUL_1 && 0
  33.   return mpn_submul_1(dst,src,n,CNST_LIMB(1) <<(s));
  34. #else
  35.   mp_limb_t __cy;
  36.   __cy = mpn_lshift(ws,src,n,s);
  37.   return    __cy + mpn_sub_n(dst,dst,ws,n);
  38. #endif
  39. }
  40. #endif
  41. #if HAVE_NATIVE_mpn_addlsh_n
  42. #define DO_mpn_addlsh_n(dst,src,n,s,ws) mpn_addlsh_n(dst,dst,src,n,s)
  43. #else
  44. static mp_limb_t
  45. DO_mpn_addlsh_n(mp_ptr dst, mp_srcptr src, mp_size_t n, unsigned int s, mp_ptr ws)
  46. {
  47. #if USE_MUL_1 && 0
  48.   return mpn_addmul_1(dst,src,n,CNST_LIMB(1) <<(s));
  49. #else
  50.   mp_limb_t __cy;
  51.   __cy = mpn_lshift(ws,src,n,s);
  52.   return    __cy + mpn_add_n(dst,dst,ws,n);
  53. #endif
  54. }
  55. #endif
  56. #if HAVE_NATIVE_mpn_subrsh
  57. #define DO_mpn_subrsh(dst,nd,src,ns,s,ws) mpn_subrsh(dst,nd,src,ns,s)
  58. #else
  59. /* FIXME: This is not a correct definition, it assumes no carry */
  60. #define DO_mpn_subrsh(dst,nd,src,ns,s,ws)
  61. do {
  62.   mp_limb_t __cy;
  63.   MPN_DECR_U (dst, nd, src[0] >> s);
  64.   __cy = DO_mpn_sublsh_n (dst, src + 1, ns - 1, GMP_NUMB_BITS - s, ws);
  65.   MPN_DECR_U (dst + ns - 1, nd - ns + 1, __cy);
  66. } while (0)
  67. #endif
  68. /* FIXME: tuneup should decide the best variant */
  69. #ifndef AORSMUL_FASTER_AORS_AORSLSH
  70. #define AORSMUL_FASTER_AORS_AORSLSH 1
  71. #endif
  72. #ifndef AORSMUL_FASTER_AORS_2AORSLSH
  73. #define AORSMUL_FASTER_AORS_2AORSLSH 1
  74. #endif
  75. #ifndef AORSMUL_FASTER_2AORSLSH
  76. #define AORSMUL_FASTER_2AORSLSH 1
  77. #endif
  78. #ifndef AORSMUL_FASTER_3AORSLSH
  79. #define AORSMUL_FASTER_3AORSLSH 1
  80. #endif
  81. #if GMP_NUMB_BITS < 43
  82. #define BIT_CORRECTION 1
  83. #define CORRECTION_BITS GMP_NUMB_BITS
  84. #else
  85. #define BIT_CORRECTION 0
  86. #define CORRECTION_BITS 0
  87. #endif
  88. #define BINVERT_9 
  89.   ((((GMP_NUMB_MAX / 9) << (6 - GMP_NUMB_BITS % 6)) * 8 & GMP_NUMB_MAX) | 0x39)
  90. #define BINVERT_255 
  91.   (GMP_NUMB_MAX - ((GMP_NUMB_MAX / 255) << (8 - GMP_NUMB_BITS % 8)))
  92.   /* FIXME: find some more general expressions for inverses */
  93. #if GMP_LIMB_BITS == 32
  94. #define BINVERT_2835  (GMP_NUMB_MASK & CNST_LIMB(0x53E3771B))
  95. #define BINVERT_42525 (GMP_NUMB_MASK & CNST_LIMB(0x9F314C35))
  96. #define BINVERT_182712915 (GMP_NUMB_MASK & CNST_LIMB(0x550659DB))
  97. #define BINVERT_188513325 (GMP_NUMB_MASK & CNST_LIMB(0xFBC333A5))
  98. #define BINVERT_255x182712915L (GMP_NUMB_MASK & CNST_LIMB(0x6FC4CB25))
  99. #define BINVERT_255x188513325L (GMP_NUMB_MASK & CNST_LIMB(0x6864275B))
  100. #if GMP_NAIL_BITS == 0
  101. #define BINVERT_255x182712915H CNST_LIMB(0x1B649A07)
  102. #define BINVERT_255x188513325H CNST_LIMB(0x06DB993A)
  103. #else /* GMP_NAIL_BITS != 0 */
  104. #define BINVERT_255x182712915H 
  105.   (GMP_NUMB_MASK & CNST_LIMB((0x1B649A07<<GMP_NAIL_BITS) | (0x6FC4CB25>>GMP_NUMB_BITS)))
  106. #define BINVERT_255x188513325H 
  107.   (GMP_NUMB_MASK & CNST_LIMB((0x06DB993A<<GMP_NAIL_BITS) | (0x6864275B>>GMP_NUMB_BITS)))
  108. #endif
  109. #else
  110. #if GMP_LIMB_BITS == 64
  111. #define BINVERT_2835  (GMP_NUMB_MASK & CNST_LIMB(0x938CC70553E3771B))
  112. #define BINVERT_42525 (GMP_NUMB_MASK & CNST_LIMB(0xE7B40D449F314C35))
  113. #define BINVERT_255x182712915  (GMP_NUMB_MASK & CNST_LIMB(0x1B649A076FC4CB25))
  114. #define BINVERT_255x188513325  (GMP_NUMB_MASK & CNST_LIMB(0x06DB993A6864275B))
  115. #endif
  116. #endif
  117. #ifndef mpn_divexact_by255
  118. #if GMP_NUMB_BITS % 8 == 0
  119. #define mpn_divexact_by255(dst,src,size) 
  120.   (255 & 1 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 255)))
  121. #else
  122. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1
  123. #define mpn_divexact_by255(dst,src,size) mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(255),BINVERT_255,0)
  124. #else
  125. #define mpn_divexact_by255(dst,src,size) mpn_divexact_1(dst,src,size,CNST_LIMB(255))
  126. #endif
  127. #endif
  128. #endif
  129. #ifndef mpn_divexact_by255x4
  130. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1
  131. #define mpn_divexact_by255x4(dst,src,size) mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(255),BINVERT_255,2)
  132. #else
  133. #define mpn_divexact_by255x4(dst,src,size) mpn_divexact_1(dst,src,size,CNST_LIMB(255)<<2)
  134. #endif
  135. #endif
  136. #ifndef mpn_divexact_by9x16
  137. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1
  138. #define mpn_divexact_by9x16(dst,src,size) mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(9),BINVERT_9,4)
  139. #else
  140. #define mpn_divexact_by9x16(dst,src,size) mpn_divexact_1(dst,src,size,CNST_LIMB(9)<<4)
  141. #endif
  142. #endif
  143. #ifndef mpn_divexact_by42525x16
  144. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_42525)
  145. #define mpn_divexact_by42525x16(dst,src,size) mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(42525),BINVERT_42525,4)
  146. #else
  147. #define mpn_divexact_by42525x16(dst,src,size) mpn_divexact_1(dst,src,size,CNST_LIMB(42525)<<4)
  148. #endif
  149. #endif
  150. #ifndef mpn_divexact_by2835x64
  151. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_2835)
  152. #define mpn_divexact_by2835x64(dst,src,size) mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(2835),BINVERT_2835,6)
  153. #else
  154. #define mpn_divexact_by2835x64(dst,src,size) mpn_divexact_1(dst,src,size,CNST_LIMB(2835)<<6)
  155. #endif
  156. #endif
  157. #ifndef  mpn_divexact_by255x182712915
  158. #if GMP_NUMB_BITS < 36
  159. #if HAVE_NATIVE_mpn_bdiv_q_2_pi2 && defined(BINVERT_255x182712915H)
  160. /* FIXME: use mpn_bdiv_q_2_pi2 */
  161. #endif
  162. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_182712915)
  163. #define mpn_divexact_by255x182712915(dst,src,size)
  164.   do {
  165.     mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(182712915),BINVERT_182712915,0);
  166.     mpn_divexact_by255(dst,dst,size);
  167.   } while(0)
  168. #else
  169. #define mpn_divexact_by255x182712915(dst,src,size)
  170.   do {
  171.     mpn_divexact_1(dst,src,size,CNST_LIMB(182712915));
  172.     mpn_divexact_by255(dst,dst,size);
  173.   } while(0)
  174. #endif
  175. #else /* GMP_NUMB_BITS > 35 */
  176. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_255x182712915)
  177. #define mpn_divexact_by255x182712915(dst,src,size) 
  178.   mpn_pi1_bdiv_q_1(dst,src,size,255*CNST_LIMB(182712915),BINVERT_255x182712915,0)
  179. #else
  180. #define mpn_divexact_by255x182712915(dst,src,size) mpn_divexact_1(dst,src,size,255*CNST_LIMB(182712915))
  181. #endif
  182. #endif /* GMP_NUMB_BITS >?< 36 */
  183. #endif
  184. #ifndef  mpn_divexact_by255x188513325
  185. #if GMP_NUMB_BITS < 36
  186. #if HAVE_NATIVE_mpn_bdiv_q_1_pi2 && defined(BINVERT_255x188513325H)
  187. /* FIXME: use mpn_bdiv_q_1_pi2 */
  188. #endif
  189. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_188513325)
  190. #define mpn_divexact_by255x188513325(dst,src,size)
  191.   do {
  192.     mpn_pi1_bdiv_q_1(dst,src,size,CNST_LIMB(188513325),BINVERT_188513325,0);
  193.     mpn_divexact_by255(dst,dst,size);
  194.   } while(0)
  195. #else
  196. #define mpn_divexact_by255x188513325(dst,src,size)
  197.   do {
  198.     mpn_divexact_1(dst,src,size,CNST_LIMB(188513325));
  199.     mpn_divexact_by255(dst,dst,size);
  200.   } while(0)
  201. #endif
  202. #else /* GMP_NUMB_BITS > 35 */
  203. #if HAVE_NATIVE_mpn_pi1_bdiv_q_1 && defined(BINVERT_255x188513325)
  204. #define mpn_divexact_by255x188513325(dst,src,size) 
  205.   mpn_pi1_bdiv_q_1(dst,src,size,255*CNST_LIMB(188513325),BINVERT_255x188513325,0)
  206. #else
  207. #define mpn_divexact_by255x188513325(dst,src,size) mpn_divexact_1(dst,src,size,255*CNST_LIMB(188513325))
  208. #endif
  209. #endif /* GMP_NUMB_BITS >?< 36 */
  210. #endif
  211. /* Interpolation for Toom-8.5 (or Toom-8), using the evaluation
  212.    points: infinity(8.5 only), +-8, +-4, +-2, +-1, +-1/4, +-1/2,
  213.    +-1/8, 0. More precisely, we want to compute
  214.    f(2^(GMP_NUMB_BITS * n)) for a polynomial f of degree 15 (or
  215.    14), given the 16 (rsp. 15) values:
  216.      r0 = limit at infinity of f(x) / x^7,
  217.      r1 = f(8),f(-8),
  218.      r2 = f(4),f(-4),
  219.      r3 = f(2),f(-2),
  220.      r4 = f(1),f(-1),
  221.      r5 = f(1/4),f(-1/4),
  222.      r6 = f(1/2),f(-1/2),
  223.      r7 = f(1/8),f(-1/8),
  224.      r8 = f(0).
  225.    All couples of the form f(n),f(-n) must be already mixed with
  226.    toom_couple_handling(f(n),...,f(-n),...)
  227.    The result is stored in {pp, spt + 7*n (or 8*n)}.
  228.    At entry, r8 is stored at {pp, 2n},
  229.    r6 is stored at {pp + 3n, 3n + 1}.
  230.    r4 is stored at {pp + 7n, 3n + 1}.
  231.    r2 is stored at {pp +11n, 3n + 1}.
  232.    r0 is stored at {pp +15n, spt}.
  233.    The other values are 3n+1 limbs each (with most significant limbs small).
  234.    Negative intermediate results are stored two-complemented.
  235.    Inputs are destroyed.
  236. */
  237. void
  238. mpn_toom_interpolate_16pts (mp_ptr pp, mp_ptr r1, mp_ptr r3, mp_ptr r5, mp_ptr r7,
  239. mp_size_t n, mp_size_t spt, int half, mp_ptr wsi)
  240. {
  241.   mp_limb_t cy;
  242.   mp_size_t n3;
  243.   mp_size_t n3p1;
  244.   n3 = 3 * n;
  245.   n3p1 = n3 + 1;
  246. #define   r6    (pp + n3) /* 3n+1 */
  247. #define   r4    (pp + 7 * n) /* 3n+1 */
  248. #define   r2    (pp +11 * n) /* 3n+1 */
  249. #define   r0    (pp +15 * n) /* s+t <= 2*n */
  250.   ASSERT( spt <= 2 * n );
  251.   /******************************* interpolation *****************************/
  252.   if( half != 0) {
  253.     cy = mpn_sub_n (r4, r4, r0, spt);
  254.     MPN_DECR_U (r4 + spt, n3p1 - spt, cy);
  255.     cy = DO_mpn_sublsh_n (r3, r0, spt, 14, wsi);
  256.     MPN_DECR_U (r3 + spt, n3p1 - spt, cy);
  257.     DO_mpn_subrsh(r6, n3p1, r0, spt, 2, wsi);
  258.     cy = DO_mpn_sublsh_n (r2, r0, spt, 28, wsi);
  259.     MPN_DECR_U (r2 + spt, n3p1 - spt, cy);
  260.     DO_mpn_subrsh(r5, n3p1, r0, spt, 4, wsi);
  261.     cy = DO_mpn_sublsh_n (r1 + BIT_CORRECTION, r0, spt, 42 - CORRECTION_BITS, wsi);
  262.     MPN_DECR_U (r1 + spt + BIT_CORRECTION, n3p1 - spt - BIT_CORRECTION, cy);
  263. #if BIT_CORRECTION
  264.     /* FIXME: assumes r7[n3p1] is writable (it is if r5 follows). */
  265.     cy = r7[n3p1];
  266.     r7[n3p1] = 0x80;
  267. #endif
  268.     DO_mpn_subrsh(r7, n3p1 + BIT_CORRECTION, r0, spt, 6, wsi);
  269. #if BIT_CORRECTION
  270.     /* FIXME: assumes r7[n3p1] is writable. */
  271.     ASSERT ( BIT_CORRECTION > 0 || r7[n3p1] == 0x80 );
  272.     r7[n3p1] = cy;
  273. #endif
  274.   };
  275.   r5[n3] -= DO_mpn_sublsh_n (r5 + n, pp, 2 * n, 28, wsi);
  276.   DO_mpn_subrsh(r2 + n, 2 * n + 1, pp, 2 * n, 4, wsi);
  277. #if HAVE_NATIVE_mpn_add_n_sub_n
  278.   mpn_add_n_sub_n (r2, r5, r5, r2, n3p1);
  279. #else
  280.   mpn_sub_n (wsi, r5, r2, n3p1); /* can be negative */
  281.   ASSERT_NOCARRY(mpn_add_n (r2, r2, r5, n3p1));
  282.   MP_PTR_SWAP(r5, wsi);
  283. #endif
  284.   r6[n3] -= DO_mpn_sublsh_n (r6 + n, pp, 2 * n, 14, wsi);
  285.   DO_mpn_subrsh(r3 + n, 2 * n + 1, pp, 2 * n, 2, wsi);
  286. #if HAVE_NATIVE_mpn_add_n_sub_n
  287.   mpn_add_n_sub_n (r3, r6, r6, r3, n3p1);
  288. #else
  289.   ASSERT_NOCARRY(mpn_add_n (wsi, r3, r6, n3p1));
  290.   mpn_sub_n (r6, r6, r3, n3p1); /* can be negative */
  291.   MP_PTR_SWAP(r3, wsi);
  292. #endif
  293.   r7[n3] -= DO_mpn_sublsh_n (r7 + n + BIT_CORRECTION, pp, 2 * n, 42 - CORRECTION_BITS, wsi)
  294.     * (1-BIT_CORRECTION); /* if BIT_CORRECTION != 0, discard the carry. */
  295. #if BIT_CORRECTION
  296.   MPN_DECR_U (r1 + n, 2 * n + 1, pp[0] >> 6);
  297.   cy = DO_mpn_sublsh_n (r1 + n, pp + 1, 2 * n - 1, GMP_NUMB_BITS - 6, wsi);
  298.   cy = mpn_sub_1(r1 + 3 * n - 1, r1 + 3 * n - 1, 2, cy);
  299.   ASSERT ( BIT_CORRECTION > 0 || cy != 0 );
  300. #else
  301.   DO_mpn_subrsh(r1 + n, 2 * n + 1, pp, 2 * n, 6, wsi);
  302. #endif
  303. #if HAVE_NATIVE_mpn_add_n_sub_n
  304.   mpn_add_n_sub_n (r1, r7, r7, r1, n3p1);
  305. #else
  306.   mpn_sub_n (wsi, r7, r1, n3p1); /* can be negative */
  307.   mpn_add_n (r1, r1, r7, n3p1);  /* if BIT_CORRECTION != 0, can give a carry. */
  308.   MP_PTR_SWAP(r7, wsi);
  309. #endif
  310.   r4[n3] -= mpn_sub_n (r4+n, r4+n, pp, 2 * n);
  311. #if AORSMUL_FASTER_2AORSLSH
  312.   mpn_submul_1 (r5, r6, n3p1, 1028); /* can be negative */
  313. #else
  314.   DO_mpn_sublsh_n (r5, r6, n3p1, 2, wsi); /* can be negative */
  315.   DO_mpn_sublsh_n (r5, r6, n3p1,10, wsi); /* can be negative */
  316. #endif
  317.   mpn_submul_1 (r7, r5, n3p1, 1300); /* can be negative */
  318. #if AORSMUL_FASTER_3AORSLSH
  319.   mpn_submul_1 (r7, r6, n3p1, 1052688); /* can be negative */
  320. #else
  321.   DO_mpn_sublsh_n (r7, r6, n3p1, 4, wsi); /* can be negative */
  322.   DO_mpn_sublsh_n (r7, r6, n3p1,12, wsi); /* can be negative */
  323.   DO_mpn_sublsh_n (r7, r6, n3p1,20, wsi); /* can be negative */
  324. #endif
  325.   mpn_divexact_by255x188513325(r7, r7, n3p1);
  326.   mpn_submul_1 (r5, r7, n3p1, 12567555); /* can be negative */
  327.   /* A division by 2835x64 followsi. Warning: the operand can be negative! */
  328.   mpn_divexact_by2835x64(r5, r5, n3p1);
  329.   if ((r5[n3] & (GMP_NUMB_MAX << (GMP_NUMB_BITS-7))) != 0)
  330.     r5[n3] |= (GMP_NUMB_MAX << (GMP_NUMB_BITS-6));
  331. #if AORSMUL_FASTER_AORS_AORSLSH
  332.   mpn_submul_1 (r6, r7, n3p1, 4095); /* can be negative */
  333. #else
  334.   mpn_add_n (r6, r6, r7, n3p1); /* can give a carry */
  335.   DO_mpn_sublsh_n (r6, r7, n3p1, 12, wsi); /* can be negative */
  336. #endif
  337. #if AORSMUL_FASTER_2AORSLSH
  338.   mpn_addmul_1 (r6, r5, n3p1, 240); /* can be negative */
  339. #else
  340.   DO_mpn_addlsh_n (r6, r5, n3p1, 8, wsi); /* can give a carry */
  341.   DO_mpn_sublsh_n (r6, r5, n3p1, 4, wsi); /* can be negative */
  342. #endif
  343.   /* A division by 255x4 followsi. Warning: the operand can be negative! */
  344.   mpn_divexact_by255x4(r6, r6, n3p1);
  345.   if ((r6[n3] & (GMP_NUMB_MAX << (GMP_NUMB_BITS-3))) != 0)
  346.     r6[n3] |= (GMP_NUMB_MAX << (GMP_NUMB_BITS-2));
  347.   ASSERT_NOCARRY(DO_mpn_sublsh_n (r3, r4, n3p1, 7, wsi));
  348.   ASSERT_NOCARRY(DO_mpn_sublsh_n (r2, r4, n3p1, 13, wsi));
  349.   ASSERT_NOCARRY(mpn_submul_1 (r2, r3, n3p1, 400));
  350.   /* If GMP_NUMB_BITS < 42 next operations on r1 can give a carry!*/
  351.   DO_mpn_sublsh_n (r1, r4, n3p1, 19, wsi);
  352.   mpn_submul_1 (r1, r2, n3p1, 1428);
  353.   mpn_submul_1 (r1, r3, n3p1, 112896);
  354.   mpn_divexact_by255x182712915(r1, r1, n3p1);
  355.   ASSERT_NOCARRY(mpn_submul_1 (r2, r1, n3p1, 15181425));
  356.   mpn_divexact_by42525x16(r2, r2, n3p1);
  357. #if AORSMUL_FASTER_AORS_2AORSLSH
  358.   ASSERT_NOCARRY(mpn_submul_1 (r3, r1, n3p1, 3969));
  359. #else
  360.   ASSERT_NOCARRY(mpn_sub_n (r3, r3, r1, n3p1));
  361.   ASSERT_NOCARRY(DO_mpn_addlsh_n (r3, r1, n3p1, 7, wsi));
  362.   ASSERT_NOCARRY(DO_mpn_sublsh_n (r3, r1, n3p1, 12, wsi));
  363. #endif
  364.   ASSERT_NOCARRY(mpn_submul_1 (r3, r2, n3p1, 900));
  365.   mpn_divexact_by9x16(r3, r3, n3p1);
  366.   ASSERT_NOCARRY(mpn_sub_n (r4, r4, r1, n3p1));
  367.   ASSERT_NOCARRY(mpn_sub_n (r4, r4, r3, n3p1));
  368.   ASSERT_NOCARRY(mpn_sub_n (r4, r4, r2, n3p1));
  369.   mpn_add_n (r6, r2, r6, n3p1);
  370.   ASSERT_NOCARRY(mpn_rshift(r6, r6, n3p1, 1));
  371.   ASSERT_NOCARRY(mpn_sub_n (r2, r2, r6, n3p1));
  372.   mpn_sub_n (r5, r3, r5, n3p1);
  373.   ASSERT_NOCARRY(mpn_rshift(r5, r5, n3p1, 1));
  374.   ASSERT_NOCARRY(mpn_sub_n (r3, r3, r5, n3p1));
  375.   mpn_add_n (r7, r1, r7, n3p1);
  376.   ASSERT_NOCARRY(mpn_rshift(r7, r7, n3p1, 1));
  377.   ASSERT_NOCARRY(mpn_sub_n (r1, r1, r7, n3p1));
  378.   /* last interpolation steps... */
  379.   /* ... could be mixed with recomposition
  380. ||H-r7|M-r7|L-r7|   ||H-r5|M-r5|L-r5|
  381.   */
  382.   /***************************** recomposition *******************************/
  383.   /*
  384.     pp[] prior to operations:
  385.     |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|___||H r6|M r6|L r6|____|H_r8|L r8|pp
  386.     summation scheme for remaining operations:
  387.     |__16|n_15|n_14|n_13|n_12|n_11|n_10|n__9|n__8|n__7|n__6|n__5|n__4|n__3|n__2|n___|n___|pp
  388.     |M r0|L r0|___||H r2|M r2|L r2|___||H r4|M r4|L r4|___||H r6|M r6|L r6|____|H_r8|L r8|pp
  389. ||H r1|M r1|L r1|   ||H r3|M r3|L r3|   ||H_r5|M_r5|L_r5|   ||H r7|M r7|L r7|
  390.   */
  391.   cy = mpn_add_n (pp + n, pp + n, r7, n);
  392.   cy = mpn_add_1 (pp + 2 * n, r7 + n, n, cy);
  393. #if HAVE_NATIVE_mpn_add_nc
  394.   cy = r7[n3] + mpn_add_nc(pp + n3, pp + n3, r7 + 2 * n, n, cy);
  395. #else
  396.   MPN_INCR_U (r7 + 2 * n, n + 1, cy);
  397.   cy = r7[n3] + mpn_add_n (pp + n3, pp + n3, r7 + 2 * n, n);
  398. #endif
  399.   MPN_INCR_U (pp + 4 * n, 2 * n + 1, cy);
  400.   pp[2 * n3]+= mpn_add_n (pp + 5 * n, pp + 5 * n, r5, n);
  401.   cy = mpn_add_1 (pp + 2 * n3, r5 + n, n, pp[2 * n3]);
  402. #if HAVE_NATIVE_mpn_add_nc
  403.   cy = r5[n3] + mpn_add_nc(pp + 7 * n, pp + 7 * n, r5 + 2 * n, n, cy);
  404. #else
  405.   MPN_INCR_U (r5 + 2 * n, n + 1, cy);
  406.   cy = r5[n3] + mpn_add_n (pp + 7 * n, pp + 7 * n, r5 + 2 * n, n);
  407. #endif
  408.   MPN_INCR_U (pp + 8 * n, 2 * n + 1, cy);
  409.   pp[10 * n]+= mpn_add_n (pp + 9 * n, pp + 9 * n, r3, n);
  410.   cy = mpn_add_1 (pp + 10 * n, r3 + n, n, pp[10 * n]);
  411. #if HAVE_NATIVE_mpn_add_nc
  412.   cy = r3[n3] + mpn_add_nc(pp +11 * n, pp +11 * n, r3 + 2 * n, n, cy);
  413. #else
  414.   MPN_INCR_U (r3 + 2 * n, n + 1, cy);
  415.   cy = r3[n3] + mpn_add_n (pp +11 * n, pp +11 * n, r3 + 2 * n, n);
  416. #endif
  417.   MPN_INCR_U (pp +12 * n, 2 * n + 1, cy);
  418.   pp[14 * n]+=mpn_add_n (pp +13 * n, pp +13 * n, r1, n);
  419.   if ( half ) {
  420.     cy = mpn_add_1 (pp + 14 * n, r1 + n, n, pp[14 * n]);
  421. #if HAVE_NATIVE_mpn_add_nc
  422.     if(LIKELY(spt > n)) {
  423.       cy = r1[n3] + mpn_add_nc(pp + 15 * n, pp + 15 * n, r1 + 2 * n, n, cy);
  424.       MPN_INCR_U (pp + 16 * n, spt - n, cy);
  425.     } else {
  426.       ASSERT_NOCARRY(mpn_add_nc(pp + 15 * n, pp + 15 * n, r1 + 2 * n, spt, cy));
  427.     }
  428. #else
  429.     MPN_INCR_U (r1 + 2 * n, n + 1, cy);
  430.     if(LIKELY(spt > n)) {
  431.       cy = r1[n3] + mpn_add_n (pp + 15 * n, pp + 15 * n, r1 + 2 * n, n);
  432.       MPN_INCR_U (pp + 16 * n, spt - n, cy);
  433.     } else {
  434.       ASSERT_NOCARRY(mpn_add_n (pp + 15 * n, pp + 15 * n, r1 + 2 * n, spt));
  435.     }
  436. #endif
  437.   } else {
  438.     ASSERT_NOCARRY(mpn_add_1 (pp + 14 * n, r1 + n, spt, pp[14 * n]));
  439.   }
  440. #undef   r0
  441. #undef   r2
  442. #undef   r4
  443. #undef   r6
  444. }