1 1.1 mrg /* mpn_invertappr and helper functions. Compute I such that 2 1.1 mrg floor((B^{2n}-1)/U - 1 <= I + B^n <= floor((B^{2n}-1)/U. 3 1.1 mrg 4 1.1 mrg Contributed to the GNU project by Marco Bodrato. 5 1.1 mrg 6 1.1 mrg The algorithm used here was inspired by ApproximateReciprocal from "Modern 7 1.1 mrg Computer Arithmetic", by Richard P. Brent and Paul Zimmermann. Special 8 1.1 mrg thanks to Paul Zimmermann for his very valuable suggestions on all the 9 1.1 mrg theoretical aspects during the work on this code. 10 1.1 mrg 11 1.1 mrg THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES. IT IS ONLY 12 1.1 mrg SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST 13 1.1 mrg GUARANTEED THAT THEY WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE. 14 1.1 mrg 15 1.1.1.4 mrg Copyright (C) 2007, 2009, 2010, 2012, 2015, 2016 Free Software 16 1.1.1.4 mrg Foundation, Inc. 17 1.1 mrg 18 1.1 mrg This file is part of the GNU MP Library. 19 1.1 mrg 20 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 21 1.1.1.3 mrg it under the terms of either: 22 1.1.1.3 mrg 23 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free 24 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your 25 1.1.1.3 mrg option) any later version. 26 1.1.1.3 mrg 27 1.1.1.3 mrg or 28 1.1.1.3 mrg 29 1.1.1.3 mrg * the GNU General Public License as published by the Free Software 30 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any 31 1.1.1.3 mrg later version. 32 1.1.1.3 mrg 33 1.1.1.3 mrg or both in parallel, as here. 34 1.1 mrg 35 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 36 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 37 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 38 1.1.1.3 mrg for more details. 39 1.1 mrg 40 1.1.1.3 mrg You should have received copies of the GNU General Public License and the 41 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 42 1.1.1.3 mrg see https://www.gnu.org/licenses/. */ 43 1.1 mrg 44 1.1 mrg #include "gmp-impl.h" 45 1.1 mrg #include "longlong.h" 46 1.1 mrg 47 1.1.1.3 mrg /* FIXME: The iterative version splits the operand in two slightly unbalanced 48 1.1 mrg parts, the use of log_2 (or counting the bits) underestimate the maximum 49 1.1 mrg number of iterations. */ 50 1.1 mrg 51 1.1 mrg #if TUNE_PROGRAM_BUILD 52 1.1 mrg #define NPOWS \ 53 1.1 mrg ((sizeof(mp_size_t) > 6 ? 48 : 8*sizeof(mp_size_t))) 54 1.1 mrg #define MAYBE_dcpi1_divappr 1 55 1.1 mrg #else 56 1.1 mrg #define NPOWS \ 57 1.1 mrg ((sizeof(mp_size_t) > 6 ? 48 : 8*sizeof(mp_size_t)) - LOG2C (INV_NEWTON_THRESHOLD)) 58 1.1 mrg #define MAYBE_dcpi1_divappr \ 59 1.1 mrg (INV_NEWTON_THRESHOLD < DC_DIVAPPR_Q_THRESHOLD) 60 1.1 mrg #if (INV_NEWTON_THRESHOLD > INV_MULMOD_BNM1_THRESHOLD) && \ 61 1.1 mrg (INV_APPR_THRESHOLD > INV_MULMOD_BNM1_THRESHOLD) 62 1.1 mrg #undef INV_MULMOD_BNM1_THRESHOLD 63 1.1 mrg #define INV_MULMOD_BNM1_THRESHOLD 0 /* always when Newton */ 64 1.1 mrg #endif 65 1.1 mrg #endif 66 1.1 mrg 67 1.1 mrg /* All the three functions mpn{,_bc,_ni}_invertappr (ip, dp, n, scratch), take 68 1.1 mrg the strictly normalised value {dp,n} (i.e., most significant bit must be set) 69 1.1 mrg as an input, and compute {ip,n}: the approximate reciprocal of {dp,n}. 70 1.1 mrg 71 1.1 mrg Let e = mpn*_invertappr (ip, dp, n, scratch) be the returned value; the 72 1.1 mrg following conditions are satisfied by the output: 73 1.1 mrg 0 <= e <= 1; 74 1.1 mrg {dp,n}*(B^n+{ip,n}) < B^{2n} <= {dp,n}*(B^n+{ip,n}+1+e) . 75 1.1 mrg I.e. e=0 means that the result {ip,n} equals the one given by mpn_invert. 76 1.1 mrg e=1 means that the result _may_ be one less than expected. 77 1.1 mrg 78 1.1 mrg The _bc version returns e=1 most of the time. 79 1.1 mrg The _ni version should return e=0 most of the time; only about 1% of 80 1.1 mrg possible random input should give e=1. 81 1.1 mrg 82 1.1 mrg When the strict result is needed, i.e., e=0 in the relation above: 83 1.1 mrg {dp,n}*(B^n+{ip,n}) < B^{2n} <= {dp,n}*(B^n+{ip,n}+1) ; 84 1.1 mrg the function mpn_invert (ip, dp, n, scratch) should be used instead. */ 85 1.1 mrg 86 1.1.1.3 mrg /* Maximum scratch needed by this branch (at xp): 2*n */ 87 1.1 mrg static mp_limb_t 88 1.1.1.3 mrg mpn_bc_invertappr (mp_ptr ip, mp_srcptr dp, mp_size_t n, mp_ptr xp) 89 1.1 mrg { 90 1.1 mrg ASSERT (n > 0); 91 1.1 mrg ASSERT (dp[n-1] & GMP_NUMB_HIGHBIT); 92 1.1 mrg ASSERT (! MPN_OVERLAP_P (ip, n, dp, n)); 93 1.1.1.3 mrg ASSERT (! MPN_OVERLAP_P (ip, n, xp, mpn_invertappr_itch(n))); 94 1.1.1.3 mrg ASSERT (! MPN_OVERLAP_P (dp, n, xp, mpn_invertappr_itch(n))); 95 1.1 mrg 96 1.1 mrg /* Compute a base value of r limbs. */ 97 1.1 mrg if (n == 1) 98 1.1 mrg invert_limb (*ip, *dp); 99 1.1 mrg else { 100 1.1.1.3 mrg /* n > 1 here */ 101 1.1.1.4 mrg MPN_FILL (xp, n, GMP_NUMB_MAX); 102 1.1 mrg mpn_com (xp + n, dp, n); 103 1.1 mrg 104 1.1 mrg /* Now xp contains B^2n - {dp,n}*B^n - 1 */ 105 1.1 mrg 106 1.1 mrg /* FIXME: if mpn_*pi1_divappr_q handles n==2, use it! */ 107 1.1 mrg if (n == 2) { 108 1.1 mrg mpn_divrem_2 (ip, 0, xp, 4, dp); 109 1.1 mrg } else { 110 1.1 mrg gmp_pi1_t inv; 111 1.1 mrg invert_pi1 (inv, dp[n-1], dp[n-2]); 112 1.1 mrg if (! MAYBE_dcpi1_divappr 113 1.1 mrg || BELOW_THRESHOLD (n, DC_DIVAPPR_Q_THRESHOLD)) 114 1.1 mrg mpn_sbpi1_divappr_q (ip, xp, 2 * n, dp, n, inv.inv32); 115 1.1 mrg else 116 1.1 mrg mpn_dcpi1_divappr_q (ip, xp, 2 * n, dp, n, &inv); 117 1.1.1.3 mrg MPN_DECR_U(ip, n, CNST_LIMB (1)); 118 1.1 mrg return 1; 119 1.1 mrg } 120 1.1 mrg } 121 1.1 mrg return 0; 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg /* mpn_ni_invertappr: computes the approximate reciprocal using Newton's 125 1.1 mrg iterations (at least one). 126 1.1 mrg 127 1.1 mrg Inspired by Algorithm "ApproximateReciprocal", published in "Modern Computer 128 1.1 mrg Arithmetic" by Richard P. Brent and Paul Zimmermann, algorithm 3.5, page 121 129 1.1 mrg in version 0.4 of the book. 130 1.1 mrg 131 1.1 mrg Some adaptations were introduced, to allow product mod B^m-1 and return the 132 1.1 mrg value e. 133 1.1 mrg 134 1.1.1.3 mrg We introduced a correction in such a way that "the value of 135 1.1.1.3 mrg B^{n+h}-T computed at step 8 cannot exceed B^n-1" (the book reads 136 1.1.1.3 mrg "2B^n-1"). 137 1.1.1.3 mrg 138 1.1.1.3 mrg Maximum scratch needed by this branch <= 2*n, but have to fit 3*rn 139 1.1.1.3 mrg in the scratch, i.e. 3*rn <= 2*n: we require n>4. 140 1.1 mrg 141 1.1 mrg We use a wrapped product modulo B^m-1. NOTE: is there any normalisation 142 1.1 mrg problem for the [0] class? It shouldn't: we compute 2*|A*X_h - B^{n+h}| < 143 1.1 mrg B^m-1. We may get [0] if and only if we get AX_h = B^{n+h}. This can 144 1.1 mrg happen only if A=B^{n}/2, but this implies X_h = B^{h}*2-1 i.e., AX_h = 145 1.1 mrg B^{n+h} - A, then we get into the "negative" branch, where X_h is not 146 1.1 mrg incremented (because A < B^n). 147 1.1 mrg 148 1.1 mrg FIXME: the scratch for mulmod_bnm1 does not currently fit in the scratch, it 149 1.1.1.3 mrg is allocated apart. 150 1.1.1.3 mrg */ 151 1.1 mrg 152 1.1 mrg mp_limb_t 153 1.1 mrg mpn_ni_invertappr (mp_ptr ip, mp_srcptr dp, mp_size_t n, mp_ptr scratch) 154 1.1 mrg { 155 1.1 mrg mp_limb_t cy; 156 1.1 mrg mp_size_t rn, mn; 157 1.1 mrg mp_size_t sizes[NPOWS], *sizp; 158 1.1 mrg mp_ptr tp; 159 1.1 mrg TMP_DECL; 160 1.1.1.3 mrg #define xp scratch 161 1.1 mrg 162 1.1.1.3 mrg ASSERT (n > 4); 163 1.1 mrg ASSERT (dp[n-1] & GMP_NUMB_HIGHBIT); 164 1.1 mrg ASSERT (! MPN_OVERLAP_P (ip, n, dp, n)); 165 1.1 mrg ASSERT (! MPN_OVERLAP_P (ip, n, scratch, mpn_invertappr_itch(n))); 166 1.1 mrg ASSERT (! MPN_OVERLAP_P (dp, n, scratch, mpn_invertappr_itch(n))); 167 1.1 mrg 168 1.1 mrg /* Compute the computation precisions from highest to lowest, leaving the 169 1.1 mrg base case size in 'rn'. */ 170 1.1 mrg sizp = sizes; 171 1.1 mrg rn = n; 172 1.1 mrg do { 173 1.1 mrg *sizp = rn; 174 1.1.1.3 mrg rn = (rn >> 1) + 1; 175 1.1.1.3 mrg ++sizp; 176 1.1 mrg } while (ABOVE_THRESHOLD (rn, INV_NEWTON_THRESHOLD)); 177 1.1 mrg 178 1.1 mrg /* We search the inverse of 0.{dp,n}, we compute it as 1.{ip,n} */ 179 1.1 mrg dp += n; 180 1.1 mrg ip += n; 181 1.1 mrg 182 1.1 mrg /* Compute a base value of rn limbs. */ 183 1.1 mrg mpn_bc_invertappr (ip - rn, dp - rn, rn, scratch); 184 1.1 mrg 185 1.1 mrg TMP_MARK; 186 1.1 mrg 187 1.1 mrg if (ABOVE_THRESHOLD (n, INV_MULMOD_BNM1_THRESHOLD)) 188 1.1 mrg { 189 1.1 mrg mn = mpn_mulmod_bnm1_next_size (n + 1); 190 1.1 mrg tp = TMP_ALLOC_LIMBS (mpn_mulmod_bnm1_itch (mn, n, (n >> 1) + 1)); 191 1.1 mrg } 192 1.1 mrg /* Use Newton's iterations to get the desired precision.*/ 193 1.1 mrg 194 1.1 mrg while (1) { 195 1.1 mrg n = *--sizp; 196 1.1 mrg /* 197 1.1 mrg v n v 198 1.1 mrg +----+--+ 199 1.1 mrg ^ rn ^ 200 1.1 mrg */ 201 1.1 mrg 202 1.1 mrg /* Compute i_jd . */ 203 1.1 mrg if (BELOW_THRESHOLD (n, INV_MULMOD_BNM1_THRESHOLD) 204 1.1 mrg || ((mn = mpn_mulmod_bnm1_next_size (n + 1)) > (n + rn))) { 205 1.1 mrg /* FIXME: We do only need {xp,n+1}*/ 206 1.1 mrg mpn_mul (xp, dp - n, n, ip - rn, rn); 207 1.1 mrg mpn_add_n (xp + rn, xp + rn, dp - n, n - rn + 1); 208 1.1.1.3 mrg cy = CNST_LIMB(1); /* Remember we truncated, Mod B^(n+1) */ 209 1.1.1.3 mrg /* We computed (truncated) {xp,n+1} <- 1.{ip,rn} * 0.{dp,n} */ 210 1.1.1.3 mrg } else { /* Use B^mn-1 wraparound */ 211 1.1 mrg mpn_mulmod_bnm1 (xp, mn, dp - n, n, ip - rn, rn, tp); 212 1.1 mrg /* We computed {xp,mn} <- {ip,rn} * {dp,n} mod (B^mn-1) */ 213 1.1 mrg /* We know that 2*|ip*dp + dp*B^rn - B^{rn+n}| < B^mn-1 */ 214 1.1 mrg /* Add dp*B^rn mod (B^mn-1) */ 215 1.1 mrg ASSERT (n >= mn - rn); 216 1.1.1.3 mrg cy = mpn_add_n (xp + rn, xp + rn, dp - n, mn - rn); 217 1.1.1.3 mrg cy = mpn_add_nc (xp, xp, dp - (n - (mn - rn)), n - (mn - rn), cy); 218 1.1.1.3 mrg /* Subtract B^{rn+n}, maybe only compensate the carry*/ 219 1.1.1.3 mrg xp[mn] = CNST_LIMB (1); /* set a limit for DECR_U */ 220 1.1.1.3 mrg MPN_DECR_U (xp + rn + n - mn, 2 * mn + 1 - rn - n, CNST_LIMB (1) - cy); 221 1.1.1.3 mrg MPN_DECR_U (xp, mn, CNST_LIMB (1) - xp[mn]); /* if DECR_U eroded xp[mn] */ 222 1.1.1.3 mrg cy = CNST_LIMB(0); /* Remember we are working Mod B^mn-1 */ 223 1.1 mrg } 224 1.1 mrg 225 1.1.1.3 mrg if (xp[n] < CNST_LIMB (2)) { /* "positive" residue class */ 226 1.1.1.3 mrg cy = xp[n]; /* 0 <= cy <= 1 here. */ 227 1.1.1.3 mrg #if HAVE_NATIVE_mpn_sublsh1_n 228 1.1.1.3 mrg if (cy++) { 229 1.1.1.3 mrg if (mpn_cmp (xp, dp - n, n) > 0) { 230 1.1.1.3 mrg mp_limb_t chk; 231 1.1.1.3 mrg chk = mpn_sublsh1_n (xp, xp, dp - n, n); 232 1.1.1.3 mrg ASSERT (chk == xp[n]); 233 1.1.1.3 mrg ++ cy; 234 1.1.1.3 mrg } else 235 1.1.1.3 mrg ASSERT_CARRY (mpn_sub_n (xp, xp, dp - n, n)); 236 1.1 mrg } 237 1.1.1.3 mrg #else /* no mpn_sublsh1_n*/ 238 1.1.1.3 mrg if (cy++ && !mpn_sub_n (xp, xp, dp - n, n)) { 239 1.1 mrg ASSERT_CARRY (mpn_sub_n (xp, xp, dp - n, n)); 240 1.1.1.3 mrg ++cy; 241 1.1.1.3 mrg } 242 1.1.1.3 mrg #endif 243 1.1.1.3 mrg /* 1 <= cy <= 3 here. */ 244 1.1.1.3 mrg #if HAVE_NATIVE_mpn_rsblsh1_n 245 1.1.1.3 mrg if (mpn_cmp (xp, dp - n, n) > 0) { 246 1.1.1.3 mrg ASSERT_NOCARRY (mpn_rsblsh1_n (xp + n, xp, dp - n, n)); 247 1.1.1.3 mrg ++cy; 248 1.1.1.3 mrg } else 249 1.1.1.3 mrg ASSERT_NOCARRY (mpn_sub_nc (xp + 2 * n - rn, dp - rn, xp + n - rn, rn, mpn_cmp (xp, dp - n, n - rn) > 0)); 250 1.1.1.3 mrg #else /* no mpn_rsblsh1_n*/ 251 1.1.1.3 mrg if (mpn_cmp (xp, dp - n, n) > 0) { 252 1.1.1.3 mrg ASSERT_NOCARRY (mpn_sub_n (xp, xp, dp - n, n)); 253 1.1.1.3 mrg ++cy; 254 1.1 mrg } 255 1.1.1.3 mrg ASSERT_NOCARRY (mpn_sub_nc (xp + 2 * n - rn, dp - rn, xp + n - rn, rn, mpn_cmp (xp, dp - n, n - rn) > 0)); 256 1.1 mrg #endif 257 1.1.1.3 mrg MPN_DECR_U(ip - rn, rn, cy); /* 1 <= cy <= 4 here. */ 258 1.1.1.3 mrg } else { /* "negative" residue class */ 259 1.1.1.3 mrg ASSERT (xp[n] >= GMP_NUMB_MAX - CNST_LIMB(1)); 260 1.1.1.3 mrg MPN_DECR_U(xp, n + 1, cy); 261 1.1.1.3 mrg if (xp[n] != GMP_NUMB_MAX) { 262 1.1.1.3 mrg MPN_INCR_U(ip - rn, rn, CNST_LIMB (1)); 263 1.1.1.3 mrg ASSERT_CARRY (mpn_add_n (xp, xp, dp - n, n)); 264 1.1.1.3 mrg } 265 1.1.1.3 mrg mpn_com (xp + 2 * n - rn, xp + n - rn, rn); 266 1.1 mrg } 267 1.1 mrg 268 1.1.1.3 mrg /* Compute x_ju_j. FIXME:We need {xp+rn,rn}, mulhi? */ 269 1.1.1.3 mrg mpn_mul_n (xp, xp + 2 * n - rn, ip - rn, rn); 270 1.1.1.3 mrg cy = mpn_add_n (xp + rn, xp + rn, xp + 2 * n - rn, 2 * rn - n); 271 1.1.1.3 mrg cy = mpn_add_nc (ip - n, xp + 3 * rn - n, xp + n + rn, n - rn, cy); 272 1.1.1.3 mrg MPN_INCR_U (ip - rn, rn, cy); 273 1.1 mrg if (sizp == sizes) { /* Get out of the cycle */ 274 1.1 mrg /* Check for possible carry propagation from below. */ 275 1.1.1.3 mrg cy = xp[3 * rn - n - 1] > GMP_NUMB_MAX - CNST_LIMB (7); /* Be conservative. */ 276 1.1.1.3 mrg /* cy = mpn_add_1 (xp + rn, xp + rn, 2*rn - n, 4); */ 277 1.1 mrg break; 278 1.1 mrg } 279 1.1 mrg rn = n; 280 1.1 mrg } 281 1.1 mrg TMP_FREE; 282 1.1 mrg 283 1.1 mrg return cy; 284 1.1.1.3 mrg #undef xp 285 1.1 mrg } 286 1.1 mrg 287 1.1 mrg mp_limb_t 288 1.1 mrg mpn_invertappr (mp_ptr ip, mp_srcptr dp, mp_size_t n, mp_ptr scratch) 289 1.1 mrg { 290 1.1 mrg ASSERT (n > 0); 291 1.1 mrg ASSERT (dp[n-1] & GMP_NUMB_HIGHBIT); 292 1.1 mrg ASSERT (! MPN_OVERLAP_P (ip, n, dp, n)); 293 1.1 mrg ASSERT (! MPN_OVERLAP_P (ip, n, scratch, mpn_invertappr_itch(n))); 294 1.1 mrg ASSERT (! MPN_OVERLAP_P (dp, n, scratch, mpn_invertappr_itch(n))); 295 1.1 mrg 296 1.1 mrg if (BELOW_THRESHOLD (n, INV_NEWTON_THRESHOLD)) 297 1.1.1.3 mrg return mpn_bc_invertappr (ip, dp, n, scratch); 298 1.1 mrg else 299 1.1.1.3 mrg return mpn_ni_invertappr (ip, dp, n, scratch); 300 1.1 mrg } 301