1 /* mpn_set_str (mp_ptr res_ptr, const char *str, size_t str_len, int base) -- 2 Convert a STR_LEN long base BASE byte string pointed to by STR to a limb 3 vector pointed to by RES_PTR. Return the number of limbs in RES_PTR. 4 5 Contributed to the GNU project by Torbjorn Granlund. 6 7 THE FUNCTIONS IN THIS FILE, EXCEPT mpn_set_str, ARE INTERNAL WITH A MUTABLE 8 INTERFACE. IT IS ONLY SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES. IN 9 FACT, IT IS ALMOST GUARANTEED THAT THEY WILL CHANGE OR DISAPPEAR IN A FUTURE 10 GNU MP RELEASE. 11 12 Copyright 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002, 2004, 2006, 2007, 13 2008 Free Software Foundation, Inc. 14 15 This file is part of the GNU MP Library. 16 17 The GNU MP Library is free software; you can redistribute it and/or modify 18 it under the terms of the GNU Lesser General Public License as published by 19 the Free Software Foundation; either version 3 of the License, or (at your 20 option) any later version. 21 22 The GNU MP Library is distributed in the hope that it will be useful, but 23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 25 License for more details. 26 27 You should have received a copy of the GNU Lesser General Public License 28 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 29 30 31 /* TODO: 32 33 Perhaps do not compute the highest power? 34 Instead, multiply twice by the 2nd highest power: 35 36 _______ 37 |_______| hp 38 |_______| pow 39 _______________ 40 |_______________| final result 41 42 43 _______ 44 |_______| hp 45 |___| pow[-1] 46 ___________ 47 |___________| intermediate result 48 |___| pow[-1] 49 _______________ 50 |_______________| final result 51 52 Generalizing that idea, perhaps we should make powtab contain successive 53 cubes, not squares. 54 */ 55 56 #include "gmp.h" 57 #include "gmp-impl.h" 58 #include "longlong.h" 59 60 mp_size_t 61 mpn_set_str (mp_ptr rp, const unsigned char *str, size_t str_len, int base) 62 { 63 if (POW2_P (base)) 64 { 65 /* The base is a power of 2. Read the input string from least to most 66 significant character/digit. */ 67 68 const unsigned char *s; 69 int next_bitpos; 70 mp_limb_t res_digit; 71 mp_size_t size; 72 int bits_per_indigit = mp_bases[base].big_base; 73 74 size = 0; 75 res_digit = 0; 76 next_bitpos = 0; 77 78 for (s = str + str_len - 1; s >= str; s--) 79 { 80 int inp_digit = *s; 81 82 res_digit |= ((mp_limb_t) inp_digit << next_bitpos) & GMP_NUMB_MASK; 83 next_bitpos += bits_per_indigit; 84 if (next_bitpos >= GMP_NUMB_BITS) 85 { 86 rp[size++] = res_digit; 87 next_bitpos -= GMP_NUMB_BITS; 88 res_digit = inp_digit >> (bits_per_indigit - next_bitpos); 89 } 90 } 91 92 if (res_digit != 0) 93 rp[size++] = res_digit; 94 return size; 95 } 96 97 if (BELOW_THRESHOLD (str_len, SET_STR_PRECOMPUTE_THRESHOLD)) 98 return mpn_bc_set_str (rp, str, str_len, base); 99 else 100 { 101 mp_ptr powtab_mem, tp; 102 powers_t powtab[GMP_LIMB_BITS]; 103 int chars_per_limb; 104 mp_size_t size; 105 mp_size_t un; 106 TMP_DECL; 107 108 TMP_MARK; 109 110 chars_per_limb = mp_bases[base].chars_per_limb; 111 112 un = str_len / chars_per_limb + 1; 113 114 /* Allocate one large block for the powers of big_base. */ 115 powtab_mem = TMP_BALLOC_LIMBS (mpn_dc_set_str_powtab_alloc (un)); 116 117 mpn_set_str_compute_powtab (powtab, powtab_mem, un, base); 118 119 tp = TMP_BALLOC_LIMBS (mpn_dc_set_str_itch (un)); 120 size = mpn_dc_set_str (rp, str, str_len, powtab, tp); 121 122 TMP_FREE; 123 return size; 124 } 125 } 126 127 void 128 mpn_set_str_compute_powtab (powers_t *powtab, mp_ptr powtab_mem, mp_size_t un, int base) 129 { 130 mp_ptr powtab_mem_ptr; 131 long i, pi; 132 mp_size_t n; 133 mp_ptr p, t; 134 unsigned normalization_steps; 135 mp_limb_t big_base, big_base_inverted; 136 int chars_per_limb; 137 size_t digits_in_base; 138 mp_size_t shift; 139 140 powtab_mem_ptr = powtab_mem; 141 142 chars_per_limb = mp_bases[base].chars_per_limb; 143 big_base = mp_bases[base].big_base; 144 big_base_inverted = mp_bases[base].big_base_inverted; 145 count_leading_zeros (normalization_steps, big_base); 146 147 p = powtab_mem_ptr; 148 powtab_mem_ptr += 1; 149 150 digits_in_base = chars_per_limb; 151 152 p[0] = big_base; 153 n = 1; 154 155 count_leading_zeros (i, un - 1); 156 i = GMP_LIMB_BITS - 1 - i; 157 158 powtab[i].p = p; 159 powtab[i].n = n; 160 powtab[i].digits_in_base = digits_in_base; 161 powtab[i].base = base; 162 powtab[i].shift = 0; 163 164 shift = 0; 165 for (pi = i - 1; pi >= 0; pi--) 166 { 167 t = powtab_mem_ptr; 168 powtab_mem_ptr += 2 * n; 169 170 ASSERT_ALWAYS (powtab_mem_ptr < powtab_mem + mpn_dc_set_str_powtab_alloc (un)); 171 172 mpn_sqr (t, p, n); 173 n = 2 * n - 1; n += t[n] != 0; 174 digits_in_base *= 2; 175 #if 1 176 if ((((un - 1) >> pi) & 2) == 0) 177 { 178 mpn_divexact_1 (t, t, n, big_base); 179 n -= t[n - 1] == 0; 180 digits_in_base -= chars_per_limb; 181 } 182 #else 183 if (CLEVER_CONDITION_1 ()) 184 { 185 /* perform adjustment operation of previous */ 186 cy = mpn_mul_1 (p, p, n, big_base); 187 } 188 if (CLEVER_CONDITION_2 ()) 189 { 190 /* perform adjustment operation of new */ 191 cy = mpn_mul_1 (t, t, n, big_base); 192 } 193 #endif 194 shift *= 2; 195 /* Strip low zero limbs, but be careful to keep the result divisible by 196 big_base. */ 197 while (t[0] == 0 && (t[1] & ((big_base & -big_base) - 1)) == 0) 198 { 199 t++; 200 n--; 201 shift++; 202 } 203 p = t; 204 powtab[pi].p = p; 205 powtab[pi].n = n; 206 powtab[pi].digits_in_base = digits_in_base; 207 powtab[pi].base = base; 208 powtab[pi].shift = shift; 209 } 210 } 211 212 mp_size_t 213 mpn_dc_set_str (mp_ptr rp, const unsigned char *str, size_t str_len, 214 const powers_t *powtab, mp_ptr tp) 215 { 216 size_t len_lo, len_hi; 217 mp_limb_t cy; 218 mp_size_t ln, hn, n, sn; 219 220 len_lo = powtab->digits_in_base; 221 222 if (str_len <= len_lo) 223 { 224 if (BELOW_THRESHOLD (str_len, SET_STR_DC_THRESHOLD)) 225 return mpn_bc_set_str (rp, str, str_len, powtab->base); 226 else 227 return mpn_dc_set_str (rp, str, str_len, powtab + 1, tp); 228 } 229 230 len_hi = str_len - len_lo; 231 ASSERT (len_lo >= len_hi); 232 233 if (BELOW_THRESHOLD (len_hi, SET_STR_DC_THRESHOLD)) 234 hn = mpn_bc_set_str (tp, str, len_hi, powtab->base); 235 else 236 hn = mpn_dc_set_str (tp, str, len_hi, powtab + 1, rp); 237 238 sn = powtab->shift; 239 240 if (hn == 0) 241 { 242 MPN_ZERO (rp, powtab->n + sn); 243 } 244 else 245 { 246 if (powtab->n > hn) 247 mpn_mul (rp + sn, powtab->p, powtab->n, tp, hn); 248 else 249 mpn_mul (rp + sn, tp, hn, powtab->p, powtab->n); 250 MPN_ZERO (rp, sn); 251 } 252 253 str = str + str_len - len_lo; 254 if (BELOW_THRESHOLD (len_lo, SET_STR_DC_THRESHOLD)) 255 ln = mpn_bc_set_str (tp, str, len_lo, powtab->base); 256 else 257 ln = mpn_dc_set_str (tp, str, len_lo, powtab + 1, tp + powtab->n + sn + 1); 258 259 if (ln != 0) 260 { 261 cy = mpn_add_n (rp, rp, tp, ln); 262 mpn_incr_u (rp + ln, cy); 263 } 264 n = hn + powtab->n + sn; 265 return n - (rp[n - 1] == 0); 266 } 267 268 mp_size_t 269 mpn_bc_set_str (mp_ptr rp, const unsigned char *str, size_t str_len, int base) 270 { 271 mp_size_t size; 272 size_t i; 273 long j; 274 mp_limb_t cy_limb; 275 276 mp_limb_t big_base; 277 int chars_per_limb; 278 mp_limb_t res_digit; 279 280 ASSERT (base >= 2); 281 ASSERT (base < numberof (mp_bases)); 282 ASSERT (str_len >= 1); 283 284 big_base = mp_bases[base].big_base; 285 chars_per_limb = mp_bases[base].chars_per_limb; 286 287 size = 0; 288 for (i = chars_per_limb; i < str_len; i += chars_per_limb) 289 { 290 res_digit = *str++; 291 if (base == 10) 292 { /* This is a common case. 293 Help the compiler to avoid multiplication. */ 294 for (j = MP_BASES_CHARS_PER_LIMB_10 - 1; j != 0; j--) 295 res_digit = res_digit * 10 + *str++; 296 } 297 else 298 { 299 for (j = chars_per_limb - 1; j != 0; j--) 300 res_digit = res_digit * base + *str++; 301 } 302 303 if (size == 0) 304 { 305 if (res_digit != 0) 306 { 307 rp[0] = res_digit; 308 size = 1; 309 } 310 } 311 else 312 { 313 #if HAVE_NATIVE_mpn_mul_1c 314 cy_limb = mpn_mul_1c (rp, rp, size, big_base, res_digit); 315 #else 316 cy_limb = mpn_mul_1 (rp, rp, size, big_base); 317 cy_limb += mpn_add_1 (rp, rp, size, res_digit); 318 #endif 319 if (cy_limb != 0) 320 rp[size++] = cy_limb; 321 } 322 } 323 324 big_base = base; 325 res_digit = *str++; 326 if (base == 10) 327 { /* This is a common case. 328 Help the compiler to avoid multiplication. */ 329 for (j = str_len - (i - MP_BASES_CHARS_PER_LIMB_10) - 1; j > 0; j--) 330 { 331 res_digit = res_digit * 10 + *str++; 332 big_base *= 10; 333 } 334 } 335 else 336 { 337 for (j = str_len - (i - chars_per_limb) - 1; j > 0; j--) 338 { 339 res_digit = res_digit * base + *str++; 340 big_base *= base; 341 } 342 } 343 344 if (size == 0) 345 { 346 if (res_digit != 0) 347 { 348 rp[0] = res_digit; 349 size = 1; 350 } 351 } 352 else 353 { 354 #if HAVE_NATIVE_mpn_mul_1c 355 cy_limb = mpn_mul_1c (rp, rp, size, big_base, res_digit); 356 #else 357 cy_limb = mpn_mul_1 (rp, rp, size, big_base); 358 cy_limb += mpn_add_1 (rp, rp, size, res_digit); 359 #endif 360 if (cy_limb != 0) 361 rp[size++] = cy_limb; 362 } 363 return size; 364 } 365