atof-generic.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 635 行 · 第 1/2 页

C
635
字号
      unsigned int more_than_enough_bits_for_digits;      unsigned int more_than_enough_littlenums_for_digits;      unsigned int size_of_digits_in_littlenums;      unsigned int size_of_digits_in_chars;      FLONUM_TYPE power_of_10_flonum;      FLONUM_TYPE digits_flonum;      precision = (address_of_generic_floating_point_number->high		   - address_of_generic_floating_point_number->low		   + 1);	/* Number of destination littlenums.  */      /* Includes guard bits (two littlenums worth) */#if 0 /* The integer version below is very close, and it doesn't	 require floating point support (which is currently buggy on	 the Alpha).  */      maximum_useful_digits = (((double) (precision - 2))			       * ((double) (LITTLENUM_NUMBER_OF_BITS))			       / (LOG_TO_BASE_2_OF_10))	+ 2;			/* 2 :: guard digits.  */#else      maximum_useful_digits = (((precision - 2))			       * ( (LITTLENUM_NUMBER_OF_BITS))			       * 1000000 / 3321928)	+ 2;			/* 2 :: guard digits.  */#endif      if (number_of_digits_available > maximum_useful_digits)	{	  number_of_digits_to_use = maximum_useful_digits;	}      else	{	  number_of_digits_to_use = number_of_digits_available;	}      /* Cast these to SIGNED LONG first, otherwise, on systems with	 LONG wider than INT (such as Alpha OSF/1), unsignedness may	 cause unexpected results.  */      decimal_exponent += ((long) number_of_digits_before_decimal			   - (long) number_of_digits_to_use);#if 0      more_than_enough_bits_for_digits	= ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);#else      more_than_enough_bits_for_digits	= (number_of_digits_to_use * 3321928 / 1000000 + 1);#endif      more_than_enough_littlenums_for_digits	= (more_than_enough_bits_for_digits	   / LITTLENUM_NUMBER_OF_BITS)	+ 2;      /* Compute (digits) part. In "12.34E56" this is the "1234" part.	 Arithmetic is exact here. If no digits are supplied then this	 part is a 0 valued binary integer.  Allocate room to build up	 the binary number as littlenums.  We want this memory to	 disappear when we leave this function.  Assume no alignment	 problems => (room for n objects) == n * (room for 1	 object).  */      size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;      size_of_digits_in_chars = size_of_digits_in_littlenums	* sizeof (LITTLENUM_TYPE);      digits_binary_low = (LITTLENUM_TYPE *)	alloca (size_of_digits_in_chars);      memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);      /* Digits_binary_low[] is allocated and zeroed.  */      /*       * Parse the decimal digits as if * digits_low was in the units position.       * Emit a binary number into digits_binary_low[].       *       * Use a large-precision version of:       * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit       */      for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)	{	  c = *p;	  if (isdigit ((unsigned char) c))	    {	      /*	       * Multiply by 10. Assume can never overflow.	       * Add this digit to digits_binary_low[].	       */	      long carry;	      LITTLENUM_TYPE *littlenum_pointer;	      LITTLENUM_TYPE *littlenum_limit;	      littlenum_limit = digits_binary_low		+ more_than_enough_littlenums_for_digits		- 1;	      carry = c - '0';	/* char -> binary */	      for (littlenum_pointer = digits_binary_low;		   littlenum_pointer <= littlenum_limit;		   littlenum_pointer++)		{		  long work;		  work = carry + 10 * (long) (*littlenum_pointer);		  *littlenum_pointer = work & LITTLENUM_MASK;		  carry = work >> LITTLENUM_NUMBER_OF_BITS;		}	      if (carry != 0)		{		  /*		   * We have a GROSS internal error.		   * This should never happen.		   */		  as_fatal (_("failed sanity check."));		}	    }	  else	    {	      ++count;		/* '.' doesn't alter digits used count.  */	    }	}      /*       * Digits_binary_low[] properly encodes the value of the digits.       * Forget about any high-order littlenums that are 0.       */      while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0	     && size_of_digits_in_littlenums >= 2)	size_of_digits_in_littlenums--;      digits_flonum.low = digits_binary_low;      digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;      digits_flonum.leader = digits_flonum.high;      digits_flonum.exponent = 0;      /*       * The value of digits_flonum . sign should not be important.       * We have already decided the output's sign.       * We trust that the sign won't influence the other parts of the number!       * So we give it a value for these reasons:       * (1) courtesy to humans reading/debugging       *     these numbers so they don't get excited about strange values       * (2) in future there may be more meaning attached to sign,       *     and what was       *     harmless noise may become disruptive, ill-conditioned (or worse)       *     input.       */      digits_flonum.sign = '+';      {	/*	 * Compute the mantssa (& exponent) of the power of 10.	 * If sucessful, then multiply the power of 10 by the digits	 * giving return_binary_mantissa and return_binary_exponent.	 */	LITTLENUM_TYPE *power_binary_low;	int decimal_exponent_is_negative;	/* This refers to the "-56" in "12.34E-56".  */	/* FALSE: decimal_exponent is positive (or 0) */	/* TRUE:  decimal_exponent is negative */	FLONUM_TYPE temporary_flonum;	LITTLENUM_TYPE *temporary_binary_low;	unsigned int size_of_power_in_littlenums;	unsigned int size_of_power_in_chars;	size_of_power_in_littlenums = precision;	/* Precision has a built-in fudge factor so we get a few guard bits.  */	decimal_exponent_is_negative = decimal_exponent < 0;	if (decimal_exponent_is_negative)	  {	    decimal_exponent = -decimal_exponent;	  }	/* From now on: the decimal exponent is > 0. Its sign is separate.  */	size_of_power_in_chars = size_of_power_in_littlenums	  * sizeof (LITTLENUM_TYPE) + 2;	power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);	temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);	memset ((char *) power_binary_low, '\0', size_of_power_in_chars);	*power_binary_low = 1;	power_of_10_flonum.exponent = 0;	power_of_10_flonum.low = power_binary_low;	power_of_10_flonum.leader = power_binary_low;	power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;	power_of_10_flonum.sign = '+';	temporary_flonum.low = temporary_binary_low;	temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;	/*	 * (power) == 1.	 * Space for temporary_flonum allocated.	 */	/*	 * ...	 *	 * WHILE	more bits	 * DO	find next bit (with place value)	 *	multiply into power mantissa	 * OD	 */	{	  int place_number_limit;	  /* Any 10^(2^n) whose "n" exceeds this */	  /* value will fall off the end of */	  /* flonum_XXXX_powers_of_ten[].  */	  int place_number;	  const FLONUM_TYPE *multiplicand;	/* -> 10^(2^n) */	  place_number_limit = table_size_of_flonum_powers_of_ten;	  multiplicand = (decimal_exponent_is_negative			  ? flonum_negative_powers_of_ten			  : flonum_positive_powers_of_ten);	  for (place_number = 1;/* Place value of this bit of exponent.  */	       decimal_exponent;/* Quit when no more 1 bits in exponent.  */	       decimal_exponent >>= 1, place_number++)	    {	      if (decimal_exponent & 1)		{		  if (place_number > place_number_limit)		    {		      /* The decimal exponent has a magnitude so great			 that our tables can't help us fragment it.			 Although this routine is in error because it			 can't imagine a number that big, signal an			 error as if it is the user's fault for			 presenting such a big number.  */		      return_value = ERROR_EXPONENT_OVERFLOW;		      /* quit out of loop gracefully */		      decimal_exponent = 0;		    }		  else		    {#ifdef TRACE		      printf ("before multiply, place_number = %d., power_of_10_flonum:\n",			      place_number);		      flonum_print (&power_of_10_flonum);		      (void) putchar ('\n');#endif#ifdef TRACE		      printf ("multiplier:\n");		      flonum_print (multiplicand + place_number);		      (void) putchar ('\n');#endif		      flonum_multip (multiplicand + place_number,				     &power_of_10_flonum, &temporary_flonum);#ifdef TRACE		      printf ("after multiply:\n");		      flonum_print (&temporary_flonum);		      (void) putchar ('\n');#endif		      flonum_copy (&temporary_flonum, &power_of_10_flonum);#ifdef TRACE		      printf ("after copy:\n");		      flonum_print (&power_of_10_flonum);		      (void) putchar ('\n');#endif		    } /* If this bit of decimal_exponent was computable.*/		} /* If this bit of decimal_exponent was set.  */	    } /* For each bit of binary representation of exponent */#ifdef TRACE	  printf ("after computing power_of_10_flonum:\n");	  flonum_print (&power_of_10_flonum);	  (void) putchar ('\n');#endif	}      }      /*       * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).       * It may be the number 1, in which case we don't NEED to multiply.       *       * Multiply (decimal digits) by power_of_10_flonum.       */      flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);      /* Assert sign of the number we made is '+'.  */      address_of_generic_floating_point_number->sign = digits_sign_char;    }  return return_value;}#ifdef TRACEstatic voidflonum_print (f)     const FLONUM_TYPE *f;{  LITTLENUM_TYPE *lp;  char littlenum_format[10];  sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2);#define print_littlenum(LP)	(printf (littlenum_format, LP))  printf ("flonum @%p %c e%ld", f, f->sign, f->exponent);  if (f->low < f->high)    for (lp = f->high; lp >= f->low; lp--)      print_littlenum (*lp);  else    for (lp = f->low; lp <= f->high; lp++)      print_littlenum (*lp);  printf ("\n");  fflush (stdout);}#endif/* end of atof_generic.c */

⌨️ 快捷键说明

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