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

数学计算

开发平台:

Unix_Linux

  1. /* Implementation of the multiplication algorithm for Toom-Cook 6.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 < 21
  21. #error Not implemented.
  22. #endif
  23. #if TUNE_PROGRAM_BUILD
  24. #define MAYBE_mul_basecase 1
  25. #define MAYBE_mul_toom22   1
  26. #define MAYBE_mul_toom33   1
  27. #define MAYBE_mul_toom6h   1
  28. #else
  29. #define MAYBE_mul_basecase
  30.   (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM22_THRESHOLD)
  31. #define MAYBE_mul_toom22
  32.   (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM33_THRESHOLD)
  33. #define MAYBE_mul_toom33
  34.   (MUL_TOOM6H_THRESHOLD < 6 * MUL_TOOM44_THRESHOLD)
  35. #define MAYBE_mul_toom6h
  36.   (MUL_FFT_THRESHOLD >= 6 * MUL_TOOM6H_THRESHOLD)
  37. #endif
  38. #define TOOM6H_MUL_N_REC(p, a, b, n, ws)
  39.   do {
  40.     if (MAYBE_mul_basecase
  41. && BELOW_THRESHOLD (n, MUL_TOOM22_THRESHOLD))
  42.       mpn_mul_basecase (p, a, n, b, n);
  43.     else if (MAYBE_mul_toom22
  44.      && BELOW_THRESHOLD (n, MUL_TOOM33_THRESHOLD))
  45.       mpn_toom22_mul (p, a, n, b, n, ws);
  46.     else if (MAYBE_mul_toom33
  47.      && BELOW_THRESHOLD (n, MUL_TOOM44_THRESHOLD))
  48.       mpn_toom33_mul (p, a, n, b, n, ws);
  49.     else if (! MAYBE_mul_toom6h
  50.      || BELOW_THRESHOLD (n, MUL_TOOM6H_THRESHOLD))
  51.       mpn_toom44_mul (p, a, n, b, n, ws);
  52.     else
  53.       mpn_toom6h_mul (p, a, n, b, n, ws);
  54.   } while (0)
  55. #define TOOM6H_MUL_REC(p, a, na, b, nb, ws)
  56.   do { mpn_mul (p, a, na, b, nb);
  57.   } while (0)
  58. /* Toom-6.5 , compute the product {pp,an+bn} <- {ap,an} * {bp,bn}
  59.    With: an >= bn >= 46, an*6 <  bn * 17.
  60.    It _may_ work with bn<=46 and bn*17 < an*6 < bn*18
  61.    Evaluate in: infinity, +4, -4, +2, -2, +1, -1, +1/2, -1/2, +1/4, -1/4, 0.
  62. */
  63. /* Estimate on needed scratch:
  64.    S(n) <= (n+5)6*10+4+MAX(S((n+5)6),1+2*(n+5)6),
  65.    since n>42; S(n) <= ceil(log(n)/log(6))*(10+4)+n*126 < n*2 + lg2(n)*6
  66.  */
  67. void
  68. mpn_toom6h_mul   (mp_ptr pp,
  69.   mp_srcptr ap, mp_size_t an,
  70.   mp_srcptr bp, mp_size_t bn, mp_ptr scratch)
  71. {
  72.   mp_size_t n, s, t;
  73.   int p, q, half;
  74.   int sign;
  75.   /***************************** decomposition *******************************/
  76.   ASSERT( an >= bn);
  77.   /* Can not handle too much unbalancement */
  78.   ASSERT( bn >= 42 );
  79.   /* Can not handle too much unbalancement */
  80.   ASSERT((an*3 <  bn * 8) || ( bn >= 46 && an*6 <  bn * 17 ));
  81.   /* Limit num/den is a rational number between
  82.      (12/11)^(log(4)/log(2*4-1)) and (12/11)^(log(6)/log(2*6-1))             */
  83. #define LIMIT_numerator (18)
  84. #define LIMIT_denominat (17)
  85.   if( an * LIMIT_denominat < LIMIT_numerator * bn ) /* is 6*... < 6*... */
  86.     { p = q = 6; }
  87.   else if( an * 5 * LIMIT_numerator < LIMIT_denominat * 7 * bn )
  88.     { p = 7; q = 6; }
  89.   else if( an * 5 * LIMIT_denominat < LIMIT_numerator * 7 * bn )
  90.     { p = 7; q = 5; }
  91.   else if( an * LIMIT_numerator < LIMIT_denominat * 2 * bn )  /* is 4*... < 8*... */
  92.     { p = 8; q = 5; }
  93.   else if( an * LIMIT_denominat < LIMIT_numerator * 2 * bn )  /* is 4*... < 8*... */
  94.     { p = 8; q = 4; }
  95.   else
  96.     { p = 9; q = 4; }
  97.   half = (p ^ q) & 1;
  98.   n = 1 + (q * an >= p * bn ? (an - 1) / (size_t) p : (bn - 1) / (size_t) q);
  99.   p--; q--;
  100.   s = an - p * n;
  101.   t = bn - q * n;
  102.   /* With LIMIT = 16/15, the following recover is needed only if bn<=73*/
  103.   if (half) { /* Recover from badly chosen splitting */
  104.     if (s<1) {p--; s+=n; half=0;}
  105.     else if (t<1) {q--; t+=n; half=0;}
  106.   }
  107. #undef LIMIT_numerator
  108. #undef LIMIT_denominat
  109.   ASSERT (0 < s && s <= n);
  110.   ASSERT (0 < t && t <= n);
  111.   ASSERT (half || s + t > 3);
  112.   ASSERT (n > 2);
  113. #define   r4    (pp + 3 * n) /* 3n+1 */
  114. #define   r2    (pp + 7 * n) /* 3n+1 */
  115. #define   r0    (pp +11 * n) /* s+t <= 2*n */
  116. #define   r5    (scratch) /* 3n+1 */
  117. #define   r3    (scratch + 3 * n + 1) /* 3n+1 */
  118. #define   r1    (scratch + 6 * n + 2) /* 3n+1 */
  119. #define   v0    (pp + 7 * n) /* n+1 */
  120. #define   v1    (pp + 8 * n+1) /* n+1 */
  121. #define   v2    (pp + 9 * n+2) /* n+1 */
  122. #define   v3    (scratch + 9 * n + 3) /* n+1 */
  123. #define   wsi   (scratch + 9 * n + 3) /* 3n+1 */
  124. #define   wse   (scratch +10 * n + 4) /* 2n+1 */
  125.   /* Alloc also 3n+1 limbs for wsi... toom_interpolate_12pts may
  126.      need all of them  */
  127. /*   if (scratch == NULL) */
  128. /*     scratch = TMP_SALLOC_LIMBS(mpn_toom6_sqr_itch(n * 6)); */
  129.   ASSERT (12 * n + 6 <= mpn_toom6h_mul_itch(an,bn));
  130.   ASSERT (12 * n + 6 <= mpn_toom6_sqr_itch(n * 6));
  131.   /********************** evaluation and recursive calls *********************/
  132.   /* $pm1/2$ */
  133.   sign = mpn_toom_eval_pm2rexp (v2, v0, p, ap, n, s, 1, pp) ^
  134.  mpn_toom_eval_pm2rexp (v3, v1, q, bp, n, t, 1, pp);
  135.   TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1/2)*B(-1/2)*2^. */
  136.   TOOM6H_MUL_N_REC(r5, v2, v3, n + 1, wse); /* A(+1/2)*B(+1/2)*2^. */
  137.   mpn_toom_couple_handling (r5, 2 * n + 1, pp, sign, n, 1+half , half);
  138.   /* $pm1$ */
  139.   sign = mpn_toom_eval_pm1 (v2, v0, p, ap, n, s,    pp);
  140.   if (q == 3)
  141.     sign ^= mpn_toom_eval_dgr3_pm1 (v3, v1, bp, n, t,    pp);
  142.   else
  143.     sign ^= mpn_toom_eval_pm1 (v3, v1, q, bp, n, t,    pp);
  144.   TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1)*B(-1) */
  145.   TOOM6H_MUL_N_REC(r3, v2, v3, n + 1, wse); /* A(1)*B(1) */
  146.   mpn_toom_couple_handling (r3, 2 * n + 1, pp, sign, n, 0, 0);
  147.   /* $pm4$ */
  148.   sign = mpn_toom_eval_pm2exp (v2, v0, p, ap, n, s, 2, pp) ^
  149.  mpn_toom_eval_pm2exp (v3, v1, q, bp, n, t, 2, pp);
  150.   TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-4)*B(-4) */
  151.   TOOM6H_MUL_N_REC(r1, v2, v3, n + 1, wse); /* A(+4)*B(+4) */
  152.   mpn_toom_couple_handling (r1, 2 * n + 1, pp, sign, n, 2, 4);
  153.   /* $pm1/4$ */
  154.   sign = mpn_toom_eval_pm2rexp (v2, v0, p, ap, n, s, 2, pp) ^
  155.  mpn_toom_eval_pm2rexp (v3, v1, q, bp, n, t, 2, pp);
  156.   TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-1/4)*B(-1/4)*4^. */
  157.   TOOM6H_MUL_N_REC(r4, v2, v3, n + 1, wse); /* A(+1/4)*B(+1/4)*4^. */
  158.   mpn_toom_couple_handling (r4, 2 * n + 1, pp, sign, n, 2*(1+half), 2*(half));
  159.   /* $pm2$ */
  160.   sign = mpn_toom_eval_pm2 (v2, v0, p, ap, n, s, pp) ^
  161.  mpn_toom_eval_pm2 (v3, v1, q, bp, n, t, pp);
  162.   TOOM6H_MUL_N_REC(pp, v0, v1, n + 1, wse); /* A(-2)*B(-2) */
  163.   TOOM6H_MUL_N_REC(r2, v2, v3, n + 1, wse); /* A(+2)*B(+2) */
  164.   mpn_toom_couple_handling (r2, 2 * n + 1, pp, sign, n, 1, 2);
  165. #undef v0
  166. #undef v1
  167. #undef v2
  168. #undef v3
  169. #undef wse
  170.   /* A(0)*B(0) */
  171.   TOOM6H_MUL_N_REC(pp, ap, bp, n, wsi);
  172.   /* Infinity */
  173.   if( half != 0) {
  174.     if(s>t) {
  175.       TOOM6H_MUL_REC(r0, ap + p * n, s, bp + q * n, t, wsi);
  176.     } else {
  177.       TOOM6H_MUL_REC(r0, bp + q * n, t, ap + p * n, s, wsi);
  178.     };
  179.   };
  180.   mpn_toom_interpolate_12pts (pp, r1, r3, r5, n, s+t, half, wsi);
  181. #undef r0
  182. #undef r1
  183. #undef r2
  184. #undef r3
  185. #undef r4
  186. #undef r5
  187. #undef wsi
  188. }
  189. #undef TOOM6H_MUL_N_REC
  190. #undef TOOM6H_MUL_REC
  191. #undef MAYBE_mul_basecase
  192. #undef MAYBE_mul_toom22
  193. #undef MAYBE_mul_toom33
  194. #undef MAYBE_mul_toom6h