Annotation of OpenXM_contrib/gmp/mpn/generic/set_str.c, Revision 1.1.1.3
1.1.1.3 ! ohara 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.
1.1 maekawa 4:
1.1.1.3 ! ohara 5: Copyright 1991, 1992, 1993, 1994, 1996, 2000, 2001, 2002 Free Software
! 6: Foundation, Inc.
1.1 maekawa 7:
8: This file is part of the GNU MP Library.
9:
1.1.1.3 ! ohara 10: The GNU MP Library is free software; you can redistribute it and/or modify it
! 11: under the terms of the GNU Library General Public License as published by the
! 12: Free Software Foundation; either version 2 of the License, or (at your option)
! 13: any later version.
1.1 maekawa 14:
15: The GNU MP Library is distributed in the hope that it will be useful, but
1.1.1.3 ! ohara 16: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
! 17: FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
! 18: for more details.
! 19:
! 20: You should have received a copy of the GNU Library General Public License along
! 21: with the GNU MP Library; see the file COPYING.LIB. If not, write to the Free
! 22: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
! 23: USA. */
1.1 maekawa 24:
25: #include "gmp.h"
26: #include "gmp-impl.h"
27:
1.1.1.3 ! ohara 28: static mp_size_t convert_blocks __GMP_PROTO ((mp_ptr, const unsigned char *, size_t, int));
! 29:
! 30: /* When to switch to sub-quadratic code. This counts characters/digits in
! 31: the input string, not limbs as most other *_THRESHOLD. */
! 32: #ifndef SET_STR_THRESHOLD
! 33: #define SET_STR_THRESHOLD 4000
! 34: #endif
! 35:
! 36: /* Don't define this to anything but 1 for now. In order to make other values
! 37: work well, either the convert_blocks function should be generazed to handle
! 38: larger blocks than chars_per_limb, or the basecase code should be broken out
! 39: of the main function. Also note that this must be a power of 2. */
! 40: #ifndef SET_STR_BLOCK_SIZE
! 41: #define SET_STR_BLOCK_SIZE 1 /* Must be a power of 2. */
1.1.1.2 maekawa 42: #endif
1.1.1.3 ! ohara 43:
! 44:
! 45: /* This check interferes with expression based values of SET_STR_THRESHOLD
! 46: used for tuning and measuring.
! 47: #if SET_STR_BLOCK_SIZE >= SET_STR_THRESHOLD
! 48: These values are silly.
! 49: The sub-quadratic code would recurse to itself.
! 50: #endif
! 51: */
! 52:
! 53: mp_size_t
! 54: mpn_set_str (mp_ptr rp, const unsigned char *str, size_t str_len, int base)
1.1 maekawa 55: {
56: mp_size_t size;
57: mp_limb_t big_base;
1.1.1.3 ! ohara 58: int chars_per_limb;
1.1 maekawa 59: mp_limb_t res_digit;
60:
1.1.1.3 ! ohara 61: ASSERT (base >= 2);
! 62: ASSERT (base < numberof (__mp_bases));
! 63: ASSERT (str_len >= 1);
1.1 maekawa 64:
1.1.1.3 ! ohara 65: big_base = __mp_bases[base].big_base;
! 66: chars_per_limb = __mp_bases[base].chars_per_limb;
1.1 maekawa 67:
68: size = 0;
69:
1.1.1.3 ! ohara 70: if (POW2_P (base))
1.1 maekawa 71: {
1.1.1.3 ! ohara 72: /* The base is a power of 2. Read the input string from least to most
! 73: significant character/digit. */
1.1 maekawa 74:
75: const unsigned char *s;
76: int next_bitpos;
77: int bits_per_indigit = big_base;
78:
79: res_digit = 0;
80: next_bitpos = 0;
81:
82: for (s = str + str_len - 1; s >= str; s--)
83: {
84: int inp_digit = *s;
85:
1.1.1.3 ! ohara 86: res_digit |= ((mp_limb_t) inp_digit << next_bitpos) & GMP_NUMB_MASK;
1.1 maekawa 87: next_bitpos += bits_per_indigit;
1.1.1.3 ! ohara 88: if (next_bitpos >= GMP_NUMB_BITS)
1.1 maekawa 89: {
1.1.1.3 ! ohara 90: rp[size++] = res_digit;
! 91: next_bitpos -= GMP_NUMB_BITS;
1.1 maekawa 92: res_digit = inp_digit >> (bits_per_indigit - next_bitpos);
93: }
94: }
95:
96: if (res_digit != 0)
1.1.1.3 ! ohara 97: rp[size++] = res_digit;
! 98: return size;
1.1 maekawa 99: }
100: else
101: {
102: /* General case. The base is not a power of 2. */
103:
1.1.1.3 ! ohara 104: if (str_len < SET_STR_THRESHOLD)
1.1 maekawa 105: {
1.1.1.3 ! ohara 106: size_t i;
! 107: int j;
! 108: mp_limb_t cy_limb;
! 109:
! 110: for (i = chars_per_limb; i < str_len; i += chars_per_limb)
! 111: {
! 112: res_digit = *str++;
! 113: if (base == 10)
! 114: { /* This is a common case.
! 115: Help the compiler to avoid multiplication. */
! 116: for (j = MP_BASES_CHARS_PER_LIMB_10 - 1; j != 0; j--)
! 117: res_digit = res_digit * 10 + *str++;
! 118: }
! 119: else
! 120: {
! 121: for (j = chars_per_limb - 1; j != 0; j--)
! 122: res_digit = res_digit * base + *str++;
! 123: }
! 124:
! 125: if (size == 0)
! 126: {
! 127: if (res_digit != 0)
! 128: {
! 129: rp[0] = res_digit;
! 130: size = 1;
! 131: }
! 132: }
! 133: else
! 134: {
! 135: #if HAVE_NATIVE_mpn_mul_1c
! 136: cy_limb = mpn_mul_1c (rp, rp, size, big_base, res_digit);
! 137: #else
! 138: cy_limb = mpn_mul_1 (rp, rp, size, big_base);
! 139: cy_limb += mpn_add_1 (rp, rp, size, res_digit);
! 140: #endif
! 141: if (cy_limb != 0)
! 142: rp[size++] = cy_limb;
! 143: }
! 144: }
! 145:
! 146: big_base = base;
1.1 maekawa 147: res_digit = *str++;
148: if (base == 10)
149: { /* This is a common case.
150: Help the compiler to avoid multiplication. */
1.1.1.3 ! ohara 151: for (j = str_len - (i - MP_BASES_CHARS_PER_LIMB_10) - 1; j > 0; j--)
! 152: {
! 153: res_digit = res_digit * 10 + *str++;
! 154: big_base *= 10;
! 155: }
1.1 maekawa 156: }
157: else
158: {
1.1.1.3 ! ohara 159: for (j = str_len - (i - chars_per_limb) - 1; j > 0; j--)
! 160: {
! 161: res_digit = res_digit * base + *str++;
! 162: big_base *= base;
! 163: }
1.1 maekawa 164: }
165:
166: if (size == 0)
167: {
168: if (res_digit != 0)
169: {
1.1.1.3 ! ohara 170: rp[0] = res_digit;
1.1 maekawa 171: size = 1;
172: }
173: }
174: else
175: {
1.1.1.3 ! ohara 176: #if HAVE_NATIVE_mpn_mul_1c
! 177: cy_limb = mpn_mul_1c (rp, rp, size, big_base, res_digit);
! 178: #else
! 179: cy_limb = mpn_mul_1 (rp, rp, size, big_base);
! 180: cy_limb += mpn_add_1 (rp, rp, size, res_digit);
! 181: #endif
1.1 maekawa 182: if (cy_limb != 0)
1.1.1.3 ! ohara 183: rp[size++] = cy_limb;
1.1 maekawa 184: }
1.1.1.3 ! ohara 185: return size;
1.1 maekawa 186: }
1.1.1.3 ! ohara 187: else
! 188: {
! 189: /* Sub-quadratic code. */
1.1 maekawa 190:
1.1.1.3 ! ohara 191: mp_ptr dp;
! 192: mp_size_t dsize;
! 193: mp_ptr xp, tp;
! 194: mp_size_t step;
! 195: mp_size_t i;
! 196: size_t alloc;
! 197: mp_size_t n;
! 198: mp_ptr pow_mem;
! 199:
! 200: alloc = (str_len + chars_per_limb - 1) / chars_per_limb;
! 201: alloc = 2 * alloc;
! 202: dp = __GMP_ALLOCATE_FUNC_LIMBS (alloc);
! 203:
! 204: #if SET_STR_BLOCK_SIZE == 1
! 205: dsize = convert_blocks (dp, str, str_len, base);
! 206: #else
! 207: {
! 208: const unsigned char *s;
! 209: mp_ptr ddp = dp;
! 210:
! 211: s = str + str_len;
! 212: while (s - str > SET_STR_BLOCK_SIZE * chars_per_limb)
! 213: {
! 214: s -= SET_STR_BLOCK_SIZE * chars_per_limb;
! 215: mpn_set_str (ddp, s, SET_STR_BLOCK_SIZE * chars_per_limb, base);
! 216: ddp += SET_STR_BLOCK_SIZE;
! 217: }
! 218: ddp += mpn_set_str (ddp, str, s - str, base);
! 219: dsize = ddp - dp;
! 220: }
! 221: #endif
! 222:
! 223: /* Allocate space for powers of big_base. Could trim this in two
! 224: ways:
! 225: 1. Only really need 2^ceil(log2(dsize)) bits for the largest
! 226: power.
! 227: 2. Only the variable to get the largest power need that much
! 228: memory. The other variable needs half as much. Need just
! 229: figure out which of xp and tp will hold the last one.
! 230: Net space savings would be in the range 1/4 to 5/8 of current
! 231: allocation, depending on how close to the next power of 2 that
! 232: dsize is. */
! 233: pow_mem = __GMP_ALLOCATE_FUNC_LIMBS (2 * alloc);
! 234: xp = pow_mem;
! 235: tp = pow_mem + alloc;
! 236:
! 237: xp[0] = big_base;
! 238: n = 1;
! 239: step = 1;
! 240: #if SET_STR_BLOCK_SIZE != 1
! 241: for (i = SET_STR_BLOCK_SIZE; i > 1; i >>= 1)
1.1 maekawa 242: {
1.1.1.3 ! ohara 243: mpn_sqr_n (tp, xp, n);
! 244: n = 2 * n;
! 245: n -= tp[n - 1] == 0;
! 246:
! 247: step = 2 * step;
! 248: MP_PTR_SWAP (tp, xp);
1.1 maekawa 249: }
1.1.1.3 ! ohara 250: #endif
! 251:
! 252: /* Multiply every second limb block, each `step' limbs large by the
! 253: base power currently in xp[], then add this to the adjacent block.
! 254: We thereby convert from dsize blocks in base big_base, to dsize/2
! 255: blocks in base big_base^2, then to dsize/4 blocks in base
! 256: big_base^4, etc, etc. */
! 257:
! 258: if (step < dsize)
1.1 maekawa 259: {
1.1.1.3 ! ohara 260: for (;;)
! 261: {
! 262: for (i = 0; i < dsize - step; i += 2 * step)
! 263: {
! 264: mp_ptr bp = dp + i;
! 265: mp_size_t m = dsize - i - step;
! 266: mp_size_t hi;
! 267: if (n >= m)
! 268: {
! 269: mpn_mul (tp, xp, n, bp + step, m);
! 270: mpn_add (bp, tp, n + m, bp, n);
! 271: hi = i + n + m;
! 272: dsize = hi;
! 273: dsize -= dp[dsize - 1] == 0;
! 274: }
! 275: else
! 276: {
! 277: mpn_mul_n (tp, xp, bp + step, n);
! 278: mpn_add (bp, tp, n + n, bp, n);
! 279: }
! 280: }
! 281:
! 282: step = 2 * step;
! 283: if (! (step < dsize))
! 284: break;
! 285:
! 286: mpn_sqr_n (tp, xp, n);
! 287: n = 2 * n;
! 288: n -= tp[n - 1] == 0;
! 289: MP_PTR_SWAP (tp, xp);
! 290: }
1.1 maekawa 291: }
1.1.1.3 ! ohara 292:
! 293: MPN_NORMALIZE (dp, dsize);
! 294: MPN_COPY (rp, dp, dsize);
! 295: __GMP_FREE_FUNC_LIMBS (pow_mem, 2 * alloc);
! 296: __GMP_FREE_FUNC_LIMBS (dp, alloc);
! 297: return dsize;
1.1 maekawa 298: }
1.1.1.3 ! ohara 299: }
! 300: }
! 301:
! 302: static mp_size_t
! 303: convert_blocks (mp_ptr dp, const unsigned char *str, size_t str_len, int base)
! 304: {
! 305: int chars_per_limb;
! 306: mp_size_t i;
! 307: int j;
! 308: int ds;
! 309: mp_size_t dsize;
! 310: mp_limb_t res_digit;
! 311:
! 312: chars_per_limb = __mp_bases[base].chars_per_limb;
1.1 maekawa 313:
1.1.1.3 ! ohara 314: dsize = str_len / chars_per_limb;
! 315: ds = str_len % chars_per_limb;
! 316:
! 317: if (ds != 0)
! 318: {
! 319: res_digit = *str++;
! 320: for (j = ds - 1; j != 0; j--)
! 321: res_digit = res_digit * base + *str++;
! 322: dp[dsize] = res_digit;
! 323: }
! 324:
! 325: if (base == 10)
! 326: {
! 327: for (i = dsize - 1; i >= 0; i--)
1.1 maekawa 328: {
1.1.1.3 ! ohara 329: res_digit = *str++;
! 330: for (j = MP_BASES_CHARS_PER_LIMB_10 - 1; j != 0; j--)
! 331: res_digit = res_digit * 10 + *str++;
! 332: dp[i] = res_digit;
1.1 maekawa 333: }
1.1.1.3 ! ohara 334: }
! 335: else
! 336: {
! 337: for (i = dsize - 1; i >= 0; i--)
1.1 maekawa 338: {
1.1.1.3 ! ohara 339: res_digit = *str++;
! 340: for (j = chars_per_limb - 1; j != 0; j--)
! 341: res_digit = res_digit * base + *str++;
! 342: dp[i] = res_digit;
1.1 maekawa 343: }
344: }
345:
1.1.1.3 ! ohara 346: return dsize + (ds != 0);
1.1 maekawa 347: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>