[BACK]Return to set_str.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpf

Diff for /OpenXM_contrib/gmp/mpf/Attic/set_str.c between version 1.1.1.1 and 1.1.1.3

version 1.1.1.1, 2000/01/10 15:35:22 version 1.1.1.3, 2003/08/25 16:06:34
Line 2 
Line 2 
    in base BASE to a float in dest.  If BASE is zero, the leading characters     in base BASE to a float in dest.  If BASE is zero, the leading characters
    of STRING is used to figure out the base.     of STRING is used to figure out the base.
   
 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.  Copyright 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002 Free Software
   Foundation, Inc.
   
 This file is part of the GNU MP Library.  This file is part of the GNU MP Library.
   
 The GNU MP Library is free software; you can redistribute it and/or modify  The GNU MP Library is free software; you can redistribute it and/or modify
 it under the terms of the GNU Library General Public License as published by  it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your  the Free Software Foundation; either version 2.1 of the License, or (at your
 option) any later version.  option) any later version.
   
 The GNU MP Library is distributed in the hope that it will be useful, but  The GNU MP Library is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.  License for more details.
   
 You should have received a copy of the GNU Library General Public License  You should have received a copy of the GNU Lesser General Public License
 along with the GNU MP Library; see the file COPYING.LIB.  If not, write to  along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,  the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */  MA 02111-1307, USA. */
   
   #include "config.h"
   
   #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <ctype.h>  #include <ctype.h>
   
   #if HAVE_LOCALE_H
   #include <locale.h>    /* for localeconv */
   #endif
   
 #include "gmp.h"  #include "gmp.h"
 #include "gmp-impl.h"  #include "gmp-impl.h"
 #include "longlong.h"  #include "longlong.h"
   
 long int strtol _PROTO ((const char *, char **ptr, int));  
   
 static int  static int
 digit_value_in_base (c, base)  digit_value_in_base (int c, int base)
      int c;  
      int base;  
 {  {
   int digit;    int digit;
   
Line 50  digit_value_in_base (c, base)
Line 55  digit_value_in_base (c, base)
   return -1;    return -1;
 }  }
   
 int  #if HAVE_LOCALECONV
 #if __STDC__  /* Avoid memcmp for the usual case that point is one character.  Don't
 mpf_set_str (mpf_ptr x, const char *str, int base)     bother with str+1,point+1,pointlen-1 since those offsets would add to the
      code size.  */
   #define POINTCMP_FAST(c, str)                                           \
     ((c) == point0                                                        \
      && (pointlen == 1 || memcmp (str, point, pointlen) == 0))
   #define POINTCMP_SMALL(c, str)   (memcmp (str, point, pointlen) == 0)
   #define POINTLEN                 (pointlen)
 #else  #else
 mpf_set_str (x, str, base)  #define POINTCMP_FAST(c, str)    ((c) == '.')
      mpf_ptr x;  #define POINTCMP_SMALL(c, str)   ((c) == '.')
      char *str;  #define POINTLEN                 1
      int base;  
 #endif  #endif
   
   int
   mpf_set_str (mpf_ptr x, const char *str, int base)
 {  {
   size_t str_size;    size_t str_size;
   char *s, *begs;    char *s, *begs;
Line 69  mpf_set_str (x, str, base)
Line 82  mpf_set_str (x, str, base)
   char *dotpos = 0;    char *dotpos = 0;
   int expflag;    int expflag;
   int decimal_exponent_flag;    int decimal_exponent_flag;
   #if HAVE_LOCALECONV
     const char  *point = localeconv()->decimal_point;
     size_t      pointlen = strlen (point);
     int         point0 = point[0];
   #endif
   TMP_DECL (marker);    TMP_DECL (marker);
   
   TMP_MARK (marker);    TMP_MARK (marker);
Line 89  mpf_set_str (x, str, base)
Line 107  mpf_set_str (x, str, base)
   decimal_exponent_flag = base < 0;    decimal_exponent_flag = base < 0;
   base = ABS (base);    base = ABS (base);
   
     /* require at least one digit, possibly after an initial decimal point */
   if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)    if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
     return -1;                  /* error if no digits */      {
         if (! POINTCMP_SMALL (c, str))
           return -1;
         if (digit_value_in_base (str[POINTLEN], base == 0 ? 10 : base) < 0)
           return -1;
       }
   
   /* If BASE is 0, try to find out the base by looking at the initial    /* If BASE is 0, try to find out the base by looking at the initial
      characters.  */       characters.  */
Line 101  mpf_set_str (x, str, base)
Line 125  mpf_set_str (x, str, base)
       if (c == '0')        if (c == '0')
         {          {
           base = 8;            base = 8;
           c = *++str;            if (str[1] == 'x' || str[1] == 'X')
           if (c == 'x' || c == 'X')              {
             base = 16;                base = 16;
                 str += 2;
                 c = *str;
               }
         }          }
 #endif  #endif
     }      }
Line 131  mpf_set_str (x, str, base)
Line 158  mpf_set_str (x, str, base)
         {          {
           int dig;            int dig;
   
           if (c == '.')            if (POINTCMP_FAST (c, str))
             {              {
               if (dotpos != 0)                if (dotpos != 0)
                 {                  {
                   TMP_FREE (marker);                    TMP_FREE (marker);
                   return -1;                    return -1;
                 }                  }
               dotpos = s;                dotpos = s;
                 str += POINTLEN - 1;
                 i += POINTLEN - 1;
             }              }
           else            else
             {              {
Line 159  mpf_set_str (x, str, base)
Line 188  mpf_set_str (x, str, base)
   xsize = str_size / __mp_bases[base].chars_per_limb + 2;    xsize = str_size / __mp_bases[base].chars_per_limb + 2;
   {    {
     long exp_in_base;      long exp_in_base;
     mp_size_t rsize, msize;      mp_size_t ralloc, rsize, msize;
     int cnt, i;      int cnt, i;
     mp_ptr mp, xp, tp, rp;      mp_ptr mp, tp, rp;
     mp_limb_t cy;  
     mp_exp_t exp_in_limbs;      mp_exp_t exp_in_limbs;
     mp_size_t prec = x->_mp_prec;      mp_size_t prec = x->_mp_prec + 1;
     int divflag;      int divflag;
     mp_size_t xxx = 0;      mp_size_t madj, radj;
   
     mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);      mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
     msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);      msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
Line 179  mpf_set_str (x, str, base)
Line 207  mpf_set_str (x, str, base)
         return 0;          return 0;
       }        }
   
       madj = 0;
       /* Ignore excess limbs in MP,MSIZE.  */
       if (msize > prec)
         {
           madj = msize - prec;
           mp += msize - prec;
           msize = prec;
         }
   
     if (expflag != 0)      if (expflag != 0)
       exp_in_base = strtol (str + 1, (char **) 0,        exp_in_base = strtol (str + 1, (char **) 0,
                             decimal_exponent_flag ? 10 : base);                              decimal_exponent_flag ? 10 : base);
Line 193  mpf_set_str (x, str, base)
Line 230  mpf_set_str (x, str, base)
       {        {
         MPN_COPY (x->_mp_d, mp, msize);          MPN_COPY (x->_mp_d, mp, msize);
         x->_mp_size = negative ? -msize : msize;          x->_mp_size = negative ? -msize : msize;
         x->_mp_exp = msize;          x->_mp_exp = msize + madj;
         TMP_FREE (marker);          TMP_FREE (marker);
         return 0;          return 0;
       }        }
   
 #if 1      radj = 0;                   /* counts number of ignored low limbs in r */
     rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly))  
              / BITS_PER_MP_LIMB + 3);  
 #else  
     count_leading_zeros (cnt, (mp_limb_t) base);  
     rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1;  
 #endif  
     rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);  
     tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);  
   
       ralloc = 2 * (prec + 1);
       rp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);
       tp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);
   
     rp[0] = base;      rp[0] = base;
     rsize = 1;      rsize = 1;
   
     count_leading_zeros (cnt, exp_in_base);      count_leading_zeros (cnt, exp_in_base);
       for (i = GMP_LIMB_BITS - cnt - 2; i >= 0; i--)
     for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)  
       {        {
         mpn_mul_n (tp, rp, rp, rsize);          mpn_sqr_n (tp, rp, rsize);
         rsize = 2 * rsize;          rsize = 2 * rsize;
         rsize -= tp[rsize - 1] == 0;          rsize -= tp[rsize - 1] == 0;
         xp = tp; tp = rp; rp = xp;          radj <<= 1;
   
           if (rsize > prec)
             {
               radj += rsize - prec;
               MPN_COPY_INCR (rp, tp + rsize - prec, prec);
               rsize = prec;
             }
           else
             MP_PTR_SWAP (rp, tp);
   
         if (((exp_in_base >> i) & 1) != 0)          if (((exp_in_base >> i) & 1) != 0)
           {            {
               mp_limb_t cy;
             cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);              cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
             rp[rsize] = cy;              rp[rsize] = cy;
             rsize += cy != 0;              rsize += cy != 0;
Line 230  mpf_set_str (x, str, base)
Line 271  mpf_set_str (x, str, base)
   
     if (rsize > prec)      if (rsize > prec)
       {        {
         xxx += rsize - prec;          radj += rsize - prec;
         rp += rsize - prec;          rp += rsize - prec;
         rsize = prec;          rsize = prec;
       }        }
 #if 0  
     if (msize > prec)  
       {  
         xxx -= msize - prec;  
         mp += msize - prec;  
         msize = prec;  
       }  
 #endif  
     if (divflag)      if (divflag)
       {        {
         mp_ptr qp;          mp_ptr qp;
         mp_limb_t qflag;          mp_limb_t qlimb;
         mp_size_t xtra;          if (msize < rsize)
         if (msize <= rsize)  
           {            {
             /* Allocate extra limb for current divrem sematics. */              /* Pad out MP,MSIZE for current divrem semantics.  */
             mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);              mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
             MPN_ZERO (tmp, rsize - msize);              MPN_ZERO (tmp, rsize - msize);
             MPN_COPY (tmp + rsize - msize, mp, msize);              MPN_COPY (tmp + rsize - msize, mp, msize);
             mp = tmp;              mp = tmp;
             xxx += rsize - msize;              madj -= rsize - msize;
             msize = rsize;              msize = rsize;
           }            }
         count_leading_zeros (cnt, rp[rsize - 1]);          if ((rp[rsize - 1] & GMP_NUMB_HIGHBIT) == 0)
         if (cnt != 0)  
           {            {
               mp_limb_t cy;
               count_leading_zeros (cnt, rp[rsize - 1]);
               cnt -= GMP_NAIL_BITS;
             mpn_lshift (rp, rp, rsize, cnt);              mpn_lshift (rp, rp, rsize, cnt);
             cy = mpn_lshift (mp, mp, msize, cnt);              cy = mpn_lshift (mp, mp, msize, cnt);
             if (cy)              if (cy)
               mp[msize++] = cy;                mp[msize++] = cy;
           }            }
   
         qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB);          qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB);
         xtra = prec - (msize - rsize);          qlimb = mpn_divrem (qp, prec - (msize - rsize), mp, msize, rp, rsize);
         qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize);  
         qp[prec] = qflag;  
         tp = qp;          tp = qp;
         rsize = prec + qflag;          exp_in_limbs = qlimb + (msize - rsize) + (madj - radj);
         exp_in_limbs = rsize - xtra - xxx;          rsize = prec;
           if (qlimb != 0)
             {
               tp[prec] = qlimb;
               /* Skip the least significant limb not to overrun the destination
                  variable.  */
               tp++;
             }
       }        }
     else      else
       {        {
Line 282  mpf_set_str (x, str, base)
Line 323  mpf_set_str (x, str, base)
           mpn_mul (tp, mp, msize, rp, rsize);            mpn_mul (tp, mp, msize, rp, rsize);
         rsize += msize;          rsize += msize;
         rsize -= tp[rsize - 1] == 0;          rsize -= tp[rsize - 1] == 0;
         exp_in_limbs = rsize + xxx;          exp_in_limbs = rsize + madj + radj;
   
         if (rsize > prec)          if (rsize > prec)
           {            {
             xxx = rsize - prec;  
             tp += rsize - prec;              tp += rsize - prec;
             rsize = prec;              rsize = prec;
             exp_in_limbs += 0;              exp_in_limbs += 0;

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.3

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>