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