211 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
| FUNCTION
 | |
|         <<strtosfix16>>, <<strtosfix32>>, <<strtosfix64>>---string to signed fixed point
 | |
| 
 | |
| INDEX
 | |
| 	strtosfix16
 | |
| INDEX
 | |
| 	strtosfix32
 | |
| INDEX
 | |
| 	strtosfix64
 | |
| INDEX
 | |
| 	_strtosfix16_r
 | |
| INDEX
 | |
| 	_strtosfix32_r
 | |
| INDEX
 | |
| 	_strtosfix64_r
 | |
| 
 | |
| ANSI_SYNOPSIS
 | |
| 	#include <stdlib.h>
 | |
|         __int16 strtosfix16 (const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
|         __int32 strtosfix32 (const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
|         __int64 strtosfix64 (const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
|         __int16 _strtosfix16_r (void *<[reent]>, 
 | |
|                        const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
|         __int32 _strtosfix32_r (void *<[reent]>, 
 | |
|                        const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
|         __int64 _strtosfix64_r (void *<[reent]>, 
 | |
|                        const char *<[s]>, char **<[ptr]>);
 | |
| 
 | |
| TRAD_SYNOPSIS
 | |
| 	#include <stdlib.h>
 | |
| 	__int16 strtosfix16 (<[s]>, <[ptr]>)
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| 	__int32 strtosfix32 (<[s]>, <[ptr]>)
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| 	__int64 strtosfix64 (<[s]>, <[ptr]>)
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| 	__int16 _strtosfix16_r (<[reent]>, <[s]>, <[ptr]>)
 | |
| 	char *<[reent]>;
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| 	__int32 _strtosfix32_r (<[reent]>, <[s]>, <[ptr]>)
 | |
| 	char *<[reent]>;
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| 	__int64 _strtosfix64_r (<[reent]>, <[s]>, <[ptr]>)
 | |
| 	char *<[reent]>;
 | |
|         char *<[s]>;
 | |
|         char **<[ptr]>;
 | |
| 
 | |
| DESCRIPTION
 | |
|         The function <<strtosfix16>> converts the string <<*<[s]>>> to
 | |
| 	a fixed-point sign + 15-bits fraction representation.  The function 
 | |
| 	follows the same rules as <<strtod>>.
 | |
| 
 | |
| 	The substring converted is the longest initial
 | |
| 	subsequence of <[s]>, beginning with the first
 | |
| 	non-whitespace character, that has the format:
 | |
| 	.[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>] 
 | |
| 	The substring contains no characters if <[s]> is empty, consists
 | |
| 	entirely of whitespace, or if the first non-whitespace
 | |
| 	character is something other than <<+>>, <<->>, <<.>>, or a
 | |
| 	digit. If the substring is empty, no conversion is done, and
 | |
| 	the value of <[s]> is stored in <<*<[ptr]>>>.  Otherwise,
 | |
| 	the substring is converted, and a pointer to the final string
 | |
| 	(which will contain at least the terminating null character of
 | |
| 	<[s]>) is stored in <<*<[ptr]>>>.  If you want no
 | |
| 	assignment to <<*<[ptr]>>>, pass a null pointer as <[ptr]>.
 | |
| 
 | |
| 	<<strtosfix32>> is identical to <<strtosfix16>> except that it 
 | |
| 	converts to fixed-point sign + 31-bits fraction representation.
 | |
| 	<<strtosfix64>> is also similar, except that it converts
 | |
| 	to fixed-point sign + 63-bit fraction format.
 | |
| 
 | |
| 	The alternate functions <<_strtosfix16_r>>, <<_strtosfix32_r>>,
 | |
| 	and <<_strtosfix64_r>> are reentrant versions.
 | |
| 	The extra argument <[reent]> is a pointer to a reentrancy structure.
 | |
| 
 | |
| RETURNS
 | |
| 	The functions return the converted substring value, if any.  If
 | |
| 	no conversion can be performed, then 0 is returned.  If the converted
 | |
| 	value is a NaN, 0 is returned and errno is set to <<EDOM>>.
 | |
| 	If the converted value exceeds the maximum positive fixed-point value, 
 | |
| 	the output value is saturated to the maximum value and <<ERANGE>> is stored in 
 | |
| 	errno.  If the converted value is less than the minimum fixed-point negative
 | |
| 	value, then the output is saturated to the minimum value  and <<ERANGE>> is stored
 | |
| 	in errno.  Otherwise, the converted value is returned in the
 | |
| 	specified fixed-point format.
 | |
| 
 | |
| PORTABILITY
 | |
|         <<strtosfix16>>, <<strtosfix32>>, and <<strtosfix64>> are non-standard.
 | |
| 
 | |
|         The OS subroutines of <<strtod>> are required.
 | |
| */
 | |
| 
 | |
| #ifdef __SPE__ 
 | |
| 
 | |
| #include <_ansi.h>
 | |
| #include <limits.h>
 | |
| #include <errno.h>
 | |
| #include <stdlib.h>
 | |
| #include <reent.h>
 | |
| #include "vfieeefp.h"
 | |
| 
 | |
| /*
 | |
|  * Convert a string to a fixed-point (sign + 15-bits) value.
 | |
|  *
 | |
|  * Ignores `locale' stuff.
 | |
|  */
 | |
| __int16_t
 | |
| _DEFUN (_strtosfix16_r, (rptr, nptr, endptr),
 | |
| 	struct _reent *rptr _AND
 | |
| 	_CONST char *nptr _AND
 | |
| 	char **endptr)
 | |
| {
 | |
|   union double_union dbl;
 | |
|   unsigned long tmp, tmp2;
 | |
|   int exp, negexp, sign;
 | |
|   __int16_t result;
 | |
| 
 | |
|   dbl.d = _strtod_r (rptr, nptr, endptr);
 | |
| 
 | |
|   /* treat NAN as domain error, +/- infinity as saturation */
 | |
|   if (!finite(dbl.d))
 | |
|     {
 | |
|       if (isnan (dbl.d))
 | |
| 	{
 | |
| 	  rptr->_errno = EDOM;
 | |
| 	  return 0;
 | |
| 	}
 | |
|       rptr->_errno = ERANGE;
 | |
|       if (word0(dbl) & Sign_bit)
 | |
| 	return SHRT_MIN;
 | |
|       return SHRT_MAX;
 | |
|     }
 | |
| 
 | |
|   /* check for normal saturation */
 | |
|   if (dbl.d >= 1.0)
 | |
|     {
 | |
|       rptr->_errno = ERANGE;
 | |
|       return SHRT_MAX;
 | |
|     }
 | |
|   else if (dbl.d < -1.0)
 | |
|     {
 | |
|       rptr->_errno = ERANGE;
 | |
|       return SHRT_MIN;
 | |
|     }
 | |
| 
 | |
|   /* otherwise we have normal number in range */
 | |
| 
 | |
|   /* strip off sign and exponent */
 | |
|   sign = word0(dbl) & Sign_bit;
 | |
|   exp = ((word0(dbl) & Exp_mask) >> Exp_shift) - Bias;
 | |
|   negexp = -exp;
 | |
|   if (negexp > 15)
 | |
|     return 0;
 | |
|   /* add in implicit normalized bit */
 | |
|   tmp = word0(dbl) | Exp_msk1;
 | |
|   /* remove exponent and sign */
 | |
|   tmp <<= Ebits;
 | |
|   if (negexp != 0)
 | |
|     {
 | |
|       /* perform rounding */
 | |
|       tmp2 = tmp + (1 << (negexp - 1));
 | |
|       result = (short)(tmp2 >> (negexp + 16));
 | |
|       /* check if rounding caused carry bit which must be added into result */
 | |
|       if (tmp2 < tmp)
 | |
| 	result |= (1 << (16 - negexp));
 | |
|       /* check if positive saturation has occurred because of rounding */
 | |
|       if (!sign && result < 0)
 | |
| 	{
 | |
| 	  rptr->_errno = ERANGE;
 | |
| 	  return SHRT_MAX;
 | |
| 	}
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       /* we have -1.0, no rounding necessary */
 | |
|       return SHRT_MIN;
 | |
|     }
 | |
| 
 | |
|   return  sign ? -result : result;
 | |
| }
 | |
| 
 | |
| #ifndef _REENT_ONLY
 | |
| 
 | |
| __int16_t
 | |
| _DEFUN (strtosfix16, (s, ptr, base),
 | |
| 	_CONST char *s _AND
 | |
| 	char **ptr)
 | |
| {
 | |
|   return _strtosfix16_r (_REENT, s, ptr);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #endif /* __SPE__ */
 |