Annotation of OpenXM/src/kan96xx/gmp-2.0.2-ssh-2/mpf/get_str.c, Revision 1.1
1.1 ! takayama 1: /* mpf_get_str (digit_ptr, exp, base, n_digits, a) -- Convert the floating
! 2: point number A to a base BASE number and store N_DIGITS raw digits at
! 3: DIGIT_PTR, and the base BASE exponent in the word pointed to by EXP. For
! 4: example, the number 3.1416 would be returned as "31416" in DIGIT_PTR and
! 5: 1 in EXP.
! 6:
! 7: Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
! 8:
! 9: This file is part of the GNU MP Library.
! 10:
! 11: The GNU MP Library is free software; you can redistribute it and/or modify
! 12: it under the terms of the GNU Library General Public License as published by
! 13: the Free Software Foundation; either version 2 of the License, or (at your
! 14: option) any later version.
! 15:
! 16: The GNU MP Library is distributed in the hope that it will be useful, but
! 17: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 18: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
! 19: License for more details.
! 20:
! 21: You should have received a copy of the GNU Library General Public License
! 22: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
! 23: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
! 24: MA 02111-1307, USA. */
! 25:
! 26: #include "gmp.h"
! 27: #include "gmp-impl.h"
! 28: #include "longlong.h"
! 29:
! 30: /*
! 31: New algorithm for converting fractions (951019):
! 32: 0. Call the fraction to convert F.
! 33: 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e.,
! 34: [exp * BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is
! 35: the number of limbs between the limb point and the most significant
! 36: non-zero limb. Call this result n.
! 37: 2. Compute B^n.
! 38: 3. F*B^n will now be just below 1, which can be converted easily. (Just
! 39: multiply by B repeatedly, and see the digits fall out as integers.)
! 40: We should interrupt the conversion process of F*B^n as soon as the number
! 41: of digits requested have been generated.
! 42:
! 43: New algorithm for converting integers (951019):
! 44: 0. Call the integer to convert I.
! 45: 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e.,
! 46: [exp BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is
! 47: the number of limbs between the limb point and the least significant
! 48: non-zero limb. Call this result n.
! 49: 2. Compute B^n.
! 50: 3. I/B^n can be converted easily. (Just divide by B repeatedly. In GMP,
! 51: this is best done by calling mpn_get_str.)
! 52: Note that converting I/B^n could yield more digits than requested. For
! 53: efficiency, the variable n above should be set larger in such cases, to
! 54: kill all undesired digits in the division in step 3.
! 55: */
! 56:
! 57: char *
! 58: #if __STDC__
! 59: mpf_get_str (char *digit_ptr, mp_exp_t *exp, int base, size_t n_digits, mpf_srcptr u)
! 60: #else
! 61: mpf_get_str (digit_ptr, exp, base, n_digits, u)
! 62: char *digit_ptr;
! 63: mp_exp_t *exp;
! 64: int base;
! 65: size_t n_digits;
! 66: mpf_srcptr u;
! 67: #endif
! 68: {
! 69: mp_size_t usize;
! 70: mp_exp_t uexp;
! 71: unsigned char *str;
! 72: size_t str_size;
! 73: char *num_to_text;
! 74: long i; /* should be size_t */
! 75: mp_ptr rp;
! 76: mp_limb_t big_base;
! 77: size_t digits_computed_so_far;
! 78: int dig_per_u;
! 79: mp_srcptr up;
! 80: unsigned char *tstr;
! 81: mp_exp_t exp_in_base;
! 82: TMP_DECL (marker);
! 83:
! 84: TMP_MARK (marker);
! 85: usize = u->_mp_size;
! 86: uexp = u->_mp_exp;
! 87:
! 88: if (base >= 0)
! 89: {
! 90: if (base == 0)
! 91: base = 10;
! 92: num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
! 93: }
! 94: else
! 95: {
! 96: base = -base;
! 97: num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
! 98: }
! 99:
! 100: /* Don't compute more digits than U can accurately represent.
! 101: Also, if 0 digits were requested, give *exactly* as many digits
! 102: as can be accurately represented. */
! 103: {
! 104: size_t max_digits = (((u->_mp_prec - 1) * BITS_PER_MP_LIMB)
! 105: * __mp_bases[base].chars_per_bit_exactly);
! 106: if (n_digits == 0 || n_digits > max_digits)
! 107: n_digits = max_digits;
! 108: }
! 109:
! 110: if (digit_ptr == 0)
! 111: {
! 112: /* We didn't get a string from the user. Allocate one (and return
! 113: a pointer to it) with space for `-' and terminating null. */
! 114: digit_ptr = (char *) (*_mp_allocate_func) (n_digits + 2);
! 115: }
! 116:
! 117: if (usize == 0)
! 118: {
! 119: *exp = 0;
! 120: *digit_ptr = 0;
! 121: return digit_ptr;
! 122: }
! 123:
! 124: str = (unsigned char *) digit_ptr;
! 125:
! 126: /* Allocate temporary digit space. We can't put digits directly in the user
! 127: area, since we almost always generate more digits than requested. */
! 128: tstr = (unsigned char *) TMP_ALLOC (n_digits + 3 * BITS_PER_MP_LIMB);
! 129:
! 130: if (usize < 0)
! 131: {
! 132: *digit_ptr = '-';
! 133: str++;
! 134: usize = -usize;
! 135: }
! 136:
! 137: digits_computed_so_far = 0;
! 138:
! 139: if (uexp > usize)
! 140: {
! 141: /* The number has just an integral part. */
! 142: mp_size_t rsize;
! 143: mp_size_t exp_in_limbs;
! 144: mp_size_t msize;
! 145: mp_ptr tp, xp, mp;
! 146: int cnt;
! 147: mp_limb_t cy;
! 148: mp_size_t start_str;
! 149: mp_size_t n_limbs;
! 150:
! 151: n_limbs = 2 + ((mp_size_t) (n_digits / __mp_bases[base].chars_per_bit_exactly)
! 152: / BITS_PER_MP_LIMB);
! 153:
! 154: /* Compute n such that [u/B^n] contains (somewhat) more than n_digits
! 155: digits. (We compute less than that only if that is an exact number,
! 156: i.e., exp is small enough.) */
! 157:
! 158: exp_in_limbs = uexp;
! 159:
! 160: if (n_limbs >= exp_in_limbs)
! 161: {
! 162: /* The number is so small that we convert the entire number. */
! 163: exp_in_base = 0;
! 164: rp = (mp_ptr) TMP_ALLOC (exp_in_limbs * BYTES_PER_MP_LIMB);
! 165: MPN_ZERO (rp, exp_in_limbs - usize);
! 166: MPN_COPY (rp + (exp_in_limbs - usize), u->_mp_d, usize);
! 167: rsize = exp_in_limbs;
! 168: }
! 169: else
! 170: {
! 171: exp_in_limbs -= n_limbs;
! 172: exp_in_base = (((exp_in_limbs * BITS_PER_MP_LIMB - 1))
! 173: * __mp_bases[base].chars_per_bit_exactly);
! 174:
! 175: rsize = exp_in_limbs + 1;
! 176: rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
! 177: tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
! 178:
! 179: rp[0] = base;
! 180: rsize = 1;
! 181:
! 182: count_leading_zeros (cnt, exp_in_base);
! 183: for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
! 184: {
! 185: mpn_mul_n (tp, rp, rp, rsize);
! 186: rsize = 2 * rsize;
! 187: rsize -= tp[rsize - 1] == 0;
! 188: xp = tp; tp = rp; rp = xp;
! 189:
! 190: if (((exp_in_base >> i) & 1) != 0)
! 191: {
! 192: cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
! 193: rp[rsize] = cy;
! 194: rsize += cy != 0;
! 195: }
! 196: }
! 197:
! 198: mp = u->_mp_d;
! 199: msize = usize;
! 200:
! 201: {
! 202: mp_ptr qp;
! 203: mp_limb_t qflag;
! 204: mp_size_t xtra;
! 205: if (msize < rsize)
! 206: {
! 207: mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize+1)* BYTES_PER_MP_LIMB);
! 208: MPN_ZERO (tmp, rsize - msize);
! 209: MPN_COPY (tmp + rsize - msize, mp, msize);
! 210: mp = tmp;
! 211: msize = rsize;
! 212: }
! 213: else
! 214: {
! 215: mp_ptr tmp = (mp_ptr) TMP_ALLOC ((msize+1)* BYTES_PER_MP_LIMB);
! 216: MPN_COPY (tmp, mp, msize);
! 217: mp = tmp;
! 218: }
! 219: count_leading_zeros (cnt, rp[rsize - 1]);
! 220: cy = 0;
! 221: if (cnt != 0)
! 222: {
! 223: mpn_lshift (rp, rp, rsize, cnt);
! 224: cy = mpn_lshift (mp, mp, msize, cnt);
! 225: if (cy)
! 226: mp[msize++] = cy;
! 227: }
! 228:
! 229: {
! 230: mp_size_t qsize = n_limbs + (cy != 0);
! 231: qp = (mp_ptr) TMP_ALLOC ((qsize + 1) * BYTES_PER_MP_LIMB);
! 232: xtra = qsize - (msize - rsize);
! 233: qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize);
! 234: qp[qsize] = qflag;
! 235: rsize = qsize + qflag;
! 236: rp = qp;
! 237: }
! 238: }
! 239: }
! 240:
! 241: str_size = mpn_get_str (tstr, base, rp, rsize);
! 242:
! 243: if (str_size > n_digits + 3 * BITS_PER_MP_LIMB)
! 244: abort ();
! 245:
! 246: start_str = 0;
! 247: while (tstr[start_str] == 0)
! 248: start_str++;
! 249:
! 250: for (i = start_str; i < str_size; i++)
! 251: {
! 252: tstr[digits_computed_so_far++] = tstr[i];
! 253: if (digits_computed_so_far > n_digits)
! 254: break;
! 255: }
! 256: exp_in_base = exp_in_base + str_size - start_str;
! 257: goto finish_up;
! 258: }
! 259:
! 260: exp_in_base = 0;
! 261:
! 262: if (uexp > 0)
! 263: {
! 264: /* The number has an integral part, convert that first.
! 265: If there is a fractional part too, it will be handled later. */
! 266: mp_size_t start_str;
! 267:
! 268: rp = (mp_ptr) TMP_ALLOC (uexp * BYTES_PER_MP_LIMB);
! 269: up = u->_mp_d + usize - uexp;
! 270: MPN_COPY (rp, up, uexp);
! 271:
! 272: str_size = mpn_get_str (tstr, base, rp, uexp);
! 273:
! 274: start_str = 0;
! 275: while (tstr[start_str] == 0)
! 276: start_str++;
! 277:
! 278: for (i = start_str; i < str_size; i++)
! 279: {
! 280: tstr[digits_computed_so_far++] = tstr[i];
! 281: if (digits_computed_so_far > n_digits)
! 282: {
! 283: exp_in_base = str_size - start_str;
! 284: goto finish_up;
! 285: }
! 286: }
! 287:
! 288: exp_in_base = str_size - start_str;
! 289: /* Modify somewhat and fall out to convert fraction... */
! 290: usize -= uexp;
! 291: uexp = 0;
! 292: }
! 293:
! 294: if (usize <= 0)
! 295: goto finish_up;
! 296:
! 297: /* Convert the fraction. */
! 298: {
! 299: mp_size_t rsize, msize;
! 300: mp_ptr rp, tp, xp, mp;
! 301: int cnt;
! 302: mp_limb_t cy;
! 303: mp_exp_t nexp;
! 304:
! 305: big_base = __mp_bases[base].big_base;
! 306: dig_per_u = __mp_bases[base].chars_per_limb;
! 307:
! 308: /* Hack for correctly (although not efficiently) converting to bases that
! 309: are powers of 2. If we deem it important, we could handle powers of 2
! 310: by shifting and masking (just like mpn_get_str). */
! 311: if (big_base < 10) /* logarithm of base when power of two */
! 312: {
! 313: int logbase = big_base;
! 314: if (dig_per_u * logbase == BITS_PER_MP_LIMB)
! 315: dig_per_u--;
! 316: big_base = (mp_limb_t) 1 << (dig_per_u * logbase);
! 317: /* fall out to general code... */
! 318: }
! 319:
! 320: #if 0
! 321: if (0 && uexp == 0)
! 322: {
! 323: rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
! 324: up = u->_mp_d;
! 325: MPN_COPY (rp, up, usize);
! 326: rsize = usize;
! 327: nexp = 0;
! 328: }
! 329: else
! 330: {}
! 331: #endif
! 332: uexp = -uexp;
! 333: if (u->_mp_d[usize - 1] == 0)
! 334: cnt = 0;
! 335: else
! 336: count_leading_zeros (cnt, u->_mp_d[usize - 1]);
! 337:
! 338: nexp = ((uexp * BITS_PER_MP_LIMB) + cnt)
! 339: * __mp_bases[base].chars_per_bit_exactly;
! 340:
! 341: if (nexp == 0)
! 342: {
! 343: rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB);
! 344: up = u->_mp_d;
! 345: MPN_COPY (rp, up, usize);
! 346: rsize = usize;
! 347: }
! 348: else
! 349: {
! 350: rsize = uexp + 2;
! 351: rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
! 352: tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
! 353:
! 354: rp[0] = base;
! 355: rsize = 1;
! 356:
! 357: count_leading_zeros (cnt, nexp);
! 358: for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
! 359: {
! 360: mpn_mul_n (tp, rp, rp, rsize);
! 361: rsize = 2 * rsize;
! 362: rsize -= tp[rsize - 1] == 0;
! 363: xp = tp; tp = rp; rp = xp;
! 364:
! 365: if (((nexp >> i) & 1) != 0)
! 366: {
! 367: cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
! 368: rp[rsize] = cy;
! 369: rsize += cy != 0;
! 370: }
! 371: }
! 372:
! 373: /* Did our multiplier (base^nexp) cancel with uexp? */
! 374: #if 0
! 375: if (uexp != rsize)
! 376: {
! 377: do
! 378: {
! 379: cy = mpn_mul_1 (rp, rp, rsize, big_base);
! 380: nexp += dig_per_u;
! 381: }
! 382: while (cy == 0);
! 383: rp[rsize++] = cy;
! 384: }
! 385: #endif
! 386: mp = u->_mp_d;
! 387: msize = usize;
! 388:
! 389: tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
! 390: if (rsize > msize)
! 391: cy = mpn_mul (tp, rp, rsize, mp, msize);
! 392: else
! 393: cy = mpn_mul (tp, mp, msize, rp, rsize);
! 394: rsize += msize;
! 395: rsize -= cy == 0;
! 396: rp = tp;
! 397:
! 398: /* If we already output digits (for an integral part) pad
! 399: leading zeros. */
! 400: if (digits_computed_so_far != 0)
! 401: for (i = 0; i < nexp; i++)
! 402: tstr[digits_computed_so_far++] = 0;
! 403: }
! 404:
! 405: while (digits_computed_so_far <= n_digits)
! 406: {
! 407: /* For speed: skip trailing zeroes. */
! 408: if (rp[0] == 0)
! 409: {
! 410: rp++;
! 411: rsize--;
! 412: if (rsize == 0)
! 413: {
! 414: n_digits = digits_computed_so_far;
! 415: break;
! 416: }
! 417: }
! 418:
! 419: cy = mpn_mul_1 (rp, rp, rsize, big_base);
! 420: if (digits_computed_so_far == 0 && cy == 0)
! 421: {
! 422: abort ();
! 423: nexp += dig_per_u;
! 424: continue;
! 425: }
! 426: /* Convert N1 from BIG_BASE to a string of digits in BASE
! 427: using single precision operations. */
! 428: {
! 429: unsigned char *s = tstr + digits_computed_so_far + dig_per_u;
! 430: for (i = dig_per_u - 1; i >= 0; i--)
! 431: {
! 432: *--s = cy % base;
! 433: cy /= base;
! 434: }
! 435: }
! 436: digits_computed_so_far += dig_per_u;
! 437: }
! 438: if (exp_in_base == 0)
! 439: exp_in_base = -nexp;
! 440: }
! 441:
! 442: finish_up:
! 443:
! 444: /* We can have at most one leading 0. Remove it. */
! 445: if (tstr[0] == 0)
! 446: {
! 447: tstr++;
! 448: digits_computed_so_far--;
! 449: exp_in_base--;
! 450: }
! 451:
! 452: /* We should normally have computed too many digits. Round the result
! 453: at the point indicated by n_digits. */
! 454: if (digits_computed_so_far > n_digits)
! 455: {
! 456: /* Round the result. */
! 457: if (tstr[n_digits] * 2 >= base)
! 458: {
! 459: digits_computed_so_far = n_digits;
! 460: for (i = n_digits - 1; i >= 0; i--)
! 461: {
! 462: unsigned int x;
! 463: x = ++(tstr[i]);
! 464: if (x < base)
! 465: goto rounded_ok;
! 466: digits_computed_so_far--;
! 467: }
! 468: tstr[0] = 1;
! 469: digits_computed_so_far = 1;
! 470: exp_in_base++;
! 471: rounded_ok:;
! 472: }
! 473: }
! 474:
! 475: /* We might have fewer digits than requested as a result of rounding above,
! 476: (i.e. 0.999999 => 1.0) or because we have a number that simply doesn't
! 477: need many digits in this base (i.e., 0.125 in base 10). */
! 478: if (n_digits > digits_computed_so_far)
! 479: n_digits = digits_computed_so_far;
! 480:
! 481: /* Remove trailing 0. There can be many zeros. */
! 482: while (n_digits != 0 && tstr[n_digits - 1] == 0)
! 483: n_digits--;
! 484:
! 485: /* Translate to ascii and null-terminate. */
! 486: for (i = 0; i < n_digits; i++)
! 487: *str++ = num_to_text[tstr[i]];
! 488: *str = 0;
! 489: *exp = exp_in_base;
! 490: TMP_FREE (marker);
! 491: return digit_ptr;
! 492: }
! 493:
! 494: #if COPY_THIS_TO_OTHER_PLACES
! 495: /* Use this expression in lots of places in the library instead of the
! 496: count_leading_zeros+expression that is used currently. This expression
! 497: is much more accurate and will save odles of memory. */
! 498: rsize = ((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly)
! 499: + BITS_PER_MP_LIMB) / BITS_PER_MP_LIMB;
! 500: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>