strtod.c

来自「用于嵌入式Linux系统的标准C的库函数」· C语言 代码 · 共 732 行 · 第 1/2 页

C
732
字号
	      else		word0 (rv) += P * Exp_msk1;	    }	}    }  else if (e1 < 0)    {      e1 = -e1;      if ((i = e1 & 15) != 0)	rv.d /= tens[i];      if (e1 &= ~15)	{	  e1 >>= 4;	  if (e1 >= 1 << n_bigtens)            goto undfl;	  for (j = 0; e1 > 1; j++, e1 >>= 1)	    if (e1 & 1)	      rv.d *= tinytens[j];	  /* The last multiplication could underflow. */	  rv0.d = rv.d;	  rv.d *= tinytens[j];	  if (!rv.d)	    {	      rv.d = 2. * rv0.d;	      rv.d *= tinytens[j];	      if (!rv.d)		{		undfl:		  rv.d = 0.;		  ptr->_errno = ERANGE;		  if (bd0)		    goto retfree;		  goto ret;		}#ifndef _DOUBLE_IS_32BITS	      word0 (rv) = Tiny0;	      word1 (rv) = Tiny1;#else	      word0 (rv) = Tiny1;#endif	      /* The refinement below will clean	       * this approximation up.	       */	    }	}    }  /* Now the hard part -- adjusting rv to the correct value.*/  /* Put digits into bd: true value = bd * 10^e */  bd0 = s2b (ptr, s0, nd0, nd, y);  for (;;)    {      bd = Balloc (ptr, bd0->_k);      Bcopy (bd, bd0);      bb = d2b (ptr, rv.d, &bbe, &bbbits);	/* rv.d = bb * 2^bbe */      bs = i2b (ptr, 1);      if (e >= 0)	{	  bb2 = bb5 = 0;	  bd2 = bd5 = e;	}      else	{	  bb2 = bb5 = -e;	  bd2 = bd5 = 0;	}      if (bbe >= 0)	bb2 += bbe;      else	bd2 -= bbe;      bs2 = bb2;#ifdef Sudden_Underflow#ifdef IBM      j = 1 + 4 * P - 3 - bbbits + ((bbe + bbbits - 1) & 3);#else      j = P + 1 - bbbits;#endif#else      i = bbe + bbbits - 1;	/* logb(rv.d) */      if (i < Emin)		/* denormal */	j = bbe + (P - Emin);      else	j = P + 1 - bbbits;#endif      bb2 += j;      bd2 += j;      i = bb2 < bd2 ? bb2 : bd2;      if (i > bs2)	i = bs2;      if (i > 0)	{	  bb2 -= i;	  bd2 -= i;	  bs2 -= i;	}      if (bb5 > 0)	{	  bs = pow5mult (ptr, bs, bb5);	  bb1 = mult (ptr, bs, bb);	  Bfree (ptr, bb);	  bb = bb1;	}      if (bb2 > 0)	bb = lshift (ptr, bb, bb2);      if (bd5 > 0)	bd = pow5mult (ptr, bd, bd5);      if (bd2 > 0)	bd = lshift (ptr, bd, bd2);      if (bs2 > 0)	bs = lshift (ptr, bs, bs2);      delta = diff (ptr, bb, bd);      dsign = delta->_sign;      delta->_sign = 0;      i = cmp (delta, bs);      if (i < 0)	{	  /* Error is less than half an ulp -- check for	   * special case of mantissa a power of two.	   */	  if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)	    break;	  delta = lshift (ptr, delta, Log2P);	  if (cmp (delta, bs) > 0)	    goto drop_down;	  break;	}      if (i == 0)	{	  /* exactly half-way between */	  if (dsign)	    {	      if ((word0 (rv) & Bndry_mask1) == Bndry_mask1		  && word1 (rv) == 0xffffffff)		{		  /*boundary case -- increment exponent*/		  word0 (rv) = (word0 (rv) & Exp_mask)		    + Exp_msk1#ifdef IBM		    | Exp_msk1 >> 4#endif		    ;#ifndef _DOUBLE_IS_32BITS		  word1 (rv) = 0;#endif		  break;		}	    }	  else if (!(word0 (rv) & Bndry_mask) && !word1 (rv))	    {	    drop_down:	      /* boundary case -- decrement exponent */#ifdef Sudden_Underflow	      L = word0 (rv) & Exp_mask;#ifdef IBM	      if (L < Exp_msk1)#else	      if (L <= Exp_msk1)#endif		goto undfl;	      L -= Exp_msk1;#else	      L = (word0 (rv) & Exp_mask) - Exp_msk1;#endif	      word0 (rv) = L | Bndry_mask1;#ifndef _DOUBLE_IS_32BITS	      word1 (rv) = 0xffffffff;#endif#ifdef IBM	      goto cont;#else	      break;#endif	    }#ifndef ROUND_BIASED	  if (!(word1 (rv) & LSB))	    break;#endif	  if (dsign)	    rv.d += ulp (rv.d);#ifndef ROUND_BIASED	  else	    {	      rv.d -= ulp (rv.d);#ifndef Sudden_Underflow	      if (!rv.d)		goto undfl;#endif	    }#endif	  break;	}      if ((aadj = ratio (delta, bs)) <= 2.)	{	  if (dsign)	    aadj = aadj1 = 1.;	  else if (word1 (rv) || word0 (rv) & Bndry_mask)	    {#ifndef Sudden_Underflow	      if (word1 (rv) == Tiny1 && !word0 (rv))		goto undfl;#endif	      aadj = 1.;	      aadj1 = -1.;	    }	  else	    {	      /* special case -- power of FLT_RADIX to be */	      /* rounded down... */	      if (aadj < 2. / FLT_RADIX)		aadj = 1. / FLT_RADIX;	      else		aadj *= 0.5;	      aadj1 = -aadj;	    }	}      else	{	  aadj *= 0.5;	  aadj1 = dsign ? aadj : -aadj;#ifdef Check_FLT_ROUNDS	  switch (FLT_ROUNDS)	    {	    case 2:		/* towards +infinity */	      aadj1 -= 0.5;	      break;	    case 0:		/* towards 0 */	    case 3:		/* towards -infinity */	      aadj1 += 0.5;	    }#else	  if (FLT_ROUNDS == 0)	    aadj1 += 0.5;#endif	}      y = word0 (rv) & Exp_mask;      /* Check for overflow */      if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1))	{	  rv0.d = rv.d;	  word0 (rv) -= P * Exp_msk1;	  adj = aadj1 * ulp (rv.d);	  rv.d += adj;	  if ((word0 (rv) & Exp_mask) >=	      Exp_msk1 * (DBL_MAX_EXP + Bias - P))	    {	      if (word0 (rv0) == Big0 && word1 (rv0) == Big1)		goto ovfl;#ifdef _DOUBLE_IS_32BITS	      word0 (rv) = Big1;#else	      word0 (rv) = Big0;	      word1 (rv) = Big1;#endif	      goto cont;	    }	  else	    word0 (rv) += P * Exp_msk1;	}      else	{#ifdef Sudden_Underflow	  if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)	    {	      rv0.d = rv.d;	      word0 (rv) += P * Exp_msk1;	      adj = aadj1 * ulp (rv.d);	      rv.d += adj;#ifdef IBM	      if ((word0 (rv) & Exp_mask) < P * Exp_msk1)#else	      if ((word0 (rv) & Exp_mask) <= P * Exp_msk1)#endif		{		  if (word0 (rv0) == Tiny0		      && word1 (rv0) == Tiny1)		    goto undfl;		  word0 (rv) = Tiny0;		  word1 (rv) = Tiny1;		  goto cont;		}	      else		word0 (rv) -= P * Exp_msk1;	    }	  else	    {	      adj = aadj1 * ulp (rv.d);	      rv.d += adj;	    }#else	  /* Compute adj so that the IEEE rounding rules will	   * correctly round rv.d + adj in some half-way cases.	   * If rv.d * ulp(rv.d) is denormalized (i.e.,	   * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid	   * trouble from bits lost to denormalization;	   * example: 1.2e-307 .	   */	  if (y <= (P - 1) * Exp_msk1 && aadj >= 1.)	    {	      aadj1 = (double) (int) (aadj + 0.5);	      if (!dsign)		aadj1 = -aadj1;	    }	  adj = aadj1 * ulp (rv.d);	  rv.d += adj;#endif	}      z = word0 (rv) & Exp_mask;      if (y == z)	{	  /* Can we stop now? */	  L = aadj;	  aadj -= L;	  /* The tolerances below are conservative. */	  if (dsign || word1 (rv) || word0 (rv) & Bndry_mask)	    {	      if (aadj < .4999999 || aadj > .5000001)		break;	    }	  else if (aadj < .4999999 / FLT_RADIX)	    break;	}    cont:      Bfree (ptr, bb);      Bfree (ptr, bd);      Bfree (ptr, bs);      Bfree (ptr, delta);    }retfree:  Bfree (ptr, bb);  Bfree (ptr, bd);  Bfree (ptr, bs);  Bfree (ptr, bd0);  Bfree (ptr, delta);ret:  if (se)    *se = (char *) s;  return sign ? -rv.d : rv.d;}#ifndef NO_REENTdouble_DEFUN (strtod, (s00, se),	_CONST char *s00 _AND char **se){  return _strtod_r (_REENT, s00, se);}float_DEFUN (strtof, (s00, se),	_CONST char *s00 _AND	char **se){  return (float)_strtod_r (_REENT, s00, se);}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?