Home | History | Annotate | Line # | Download | only in generic
      1      1.1  mrg /* mpn_toom_eval_pm2 -- Evaluate a polynomial in +2 and -2
      2      1.1  mrg 
      3  1.1.1.3  mrg    Contributed to the GNU project by Niels Mller and Marco Bodrato
      4      1.1  mrg 
      5      1.1  mrg    THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE.  IT IS ONLY
      6      1.1  mrg    SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
      7      1.1  mrg    GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
      8      1.1  mrg 
      9      1.1  mrg Copyright 2009 Free Software Foundation, Inc.
     10      1.1  mrg 
     11      1.1  mrg This file is part of the GNU MP Library.
     12      1.1  mrg 
     13      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     14  1.1.1.3  mrg it under the terms of either:
     15  1.1.1.3  mrg 
     16  1.1.1.3  mrg   * the GNU Lesser General Public License as published by the Free
     17  1.1.1.3  mrg     Software Foundation; either version 3 of the License, or (at your
     18  1.1.1.3  mrg     option) any later version.
     19  1.1.1.3  mrg 
     20  1.1.1.3  mrg or
     21  1.1.1.3  mrg 
     22  1.1.1.3  mrg   * the GNU General Public License as published by the Free Software
     23  1.1.1.3  mrg     Foundation; either version 2 of the License, or (at your option) any
     24  1.1.1.3  mrg     later version.
     25  1.1.1.3  mrg 
     26  1.1.1.3  mrg or both in parallel, as here.
     27      1.1  mrg 
     28      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     29      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     30  1.1.1.3  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     31  1.1.1.3  mrg for more details.
     32      1.1  mrg 
     33  1.1.1.3  mrg You should have received copies of the GNU General Public License and the
     34  1.1.1.3  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     35  1.1.1.3  mrg see https://www.gnu.org/licenses/.  */
     36      1.1  mrg 
     37      1.1  mrg #include "gmp-impl.h"
     38      1.1  mrg 
     39      1.1  mrg /* DO_addlsh2(d,a,b,n,cy) computes cy,{d,n} <- {a,n} + 4*(cy,{b,n}), it
     40      1.1  mrg    can be used as DO_addlsh2(d,a,d,n,d[n]), for accumulation on {d,n+1}. */
     41      1.1  mrg #if HAVE_NATIVE_mpn_addlsh2_n
     42      1.1  mrg #define DO_addlsh2(d, a, b, n, cy)	\
     43      1.1  mrg do {					\
     44      1.1  mrg   (cy) <<= 2;				\
     45      1.1  mrg   (cy) += mpn_addlsh2_n(d, a, b, n);	\
     46      1.1  mrg } while (0)
     47      1.1  mrg #else
     48      1.1  mrg #if HAVE_NATIVE_mpn_addlsh_n
     49      1.1  mrg #define DO_addlsh2(d, a, b, n, cy)	\
     50      1.1  mrg do {					\
     51      1.1  mrg   (cy) <<= 2;				\
     52      1.1  mrg   (cy) += mpn_addlsh_n(d, a, b, n, 2);	\
     53      1.1  mrg } while (0)
     54      1.1  mrg #else
     55      1.1  mrg /* The following is not a general substitute for addlsh2.
     56  1.1.1.2  mrg    It is correct if d == b, but it is not if d == a.  */
     57      1.1  mrg #define DO_addlsh2(d, a, b, n, cy)	\
     58      1.1  mrg do {					\
     59      1.1  mrg   (cy) <<= 2;				\
     60      1.1  mrg   (cy) += mpn_lshift(d, b, n, 2);	\
     61      1.1  mrg   (cy) += mpn_add_n(d, d, a, n);	\
     62      1.1  mrg } while (0)
     63      1.1  mrg #endif
     64      1.1  mrg #endif
     65      1.1  mrg 
     66      1.1  mrg /* Evaluates a polynomial of degree 2 < k < GMP_NUMB_BITS, in the
     67      1.1  mrg    points +2 and -2. */
     68      1.1  mrg int
     69      1.1  mrg mpn_toom_eval_pm2 (mp_ptr xp2, mp_ptr xm2, unsigned k,
     70      1.1  mrg 		   mp_srcptr xp, mp_size_t n, mp_size_t hn, mp_ptr tp)
     71      1.1  mrg {
     72      1.1  mrg   int i;
     73      1.1  mrg   int neg;
     74      1.1  mrg   mp_limb_t cy;
     75      1.1  mrg 
     76      1.1  mrg   ASSERT (k >= 3);
     77      1.1  mrg   ASSERT (k < GMP_NUMB_BITS);
     78      1.1  mrg 
     79      1.1  mrg   ASSERT (hn > 0);
     80      1.1  mrg   ASSERT (hn <= n);
     81      1.1  mrg 
     82      1.1  mrg   /* The degree k is also the number of full-size coefficients, so
     83      1.1  mrg    * that last coefficient, of size hn, starts at xp + k*n. */
     84      1.1  mrg 
     85      1.1  mrg   cy = 0;
     86      1.1  mrg   DO_addlsh2 (xp2, xp + (k-2) * n, xp + k * n, hn, cy);
     87      1.1  mrg   if (hn != n)
     88      1.1  mrg     cy = mpn_add_1 (xp2 + hn, xp + (k-2) * n + hn, n - hn, cy);
     89      1.1  mrg   for (i = k - 4; i >= 0; i -= 2)
     90      1.1  mrg     DO_addlsh2 (xp2, xp + i * n, xp2, n, cy);
     91      1.1  mrg   xp2[n] = cy;
     92      1.1  mrg 
     93      1.1  mrg   k--;
     94      1.1  mrg 
     95      1.1  mrg   cy = 0;
     96      1.1  mrg   DO_addlsh2 (tp, xp + (k-2) * n, xp + k * n, n, cy);
     97      1.1  mrg   for (i = k - 4; i >= 0; i -= 2)
     98      1.1  mrg     DO_addlsh2 (tp, xp + i * n, tp, n, cy);
     99      1.1  mrg   tp[n] = cy;
    100      1.1  mrg 
    101      1.1  mrg   if (k & 1)
    102      1.1  mrg     ASSERT_NOCARRY(mpn_lshift (tp , tp , n + 1, 1));
    103      1.1  mrg   else
    104      1.1  mrg     ASSERT_NOCARRY(mpn_lshift (xp2, xp2, n + 1, 1));
    105      1.1  mrg 
    106      1.1  mrg   neg = (mpn_cmp (xp2, tp, n + 1) < 0) ? ~0 : 0;
    107      1.1  mrg 
    108      1.1  mrg #if HAVE_NATIVE_mpn_add_n_sub_n
    109      1.1  mrg   if (neg)
    110      1.1  mrg     mpn_add_n_sub_n (xp2, xm2, tp, xp2, n + 1);
    111      1.1  mrg   else
    112      1.1  mrg     mpn_add_n_sub_n (xp2, xm2, xp2, tp, n + 1);
    113      1.1  mrg #else /* !HAVE_NATIVE_mpn_add_n_sub_n */
    114      1.1  mrg   if (neg)
    115      1.1  mrg     mpn_sub_n (xm2, tp, xp2, n + 1);
    116      1.1  mrg   else
    117      1.1  mrg     mpn_sub_n (xm2, xp2, tp, n + 1);
    118      1.1  mrg 
    119      1.1  mrg   mpn_add_n (xp2, xp2, tp, n + 1);
    120      1.1  mrg #endif /* !HAVE_NATIVE_mpn_add_n_sub_n */
    121      1.1  mrg 
    122      1.1  mrg   ASSERT (xp2[n] < (1<<(k+2))-1);
    123      1.1  mrg   ASSERT (xm2[n] < ((1<<(k+3))-1 - (1^k&1))/3);
    124      1.1  mrg 
    125      1.1  mrg   neg ^= ((k & 1) - 1);
    126      1.1  mrg 
    127      1.1  mrg   return neg;
    128      1.1  mrg }
    129      1.1  mrg 
    130      1.1  mrg #undef DO_addlsh2
    131