diff options
Diffstat (limited to 'newlib/libc/machine/powerpc/strtosfix16.c')
-rw-r--r-- | newlib/libc/machine/powerpc/strtosfix16.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/newlib/libc/machine/powerpc/strtosfix16.c b/newlib/libc/machine/powerpc/strtosfix16.c new file mode 100644 index 000000000..ad629978c --- /dev/null +++ b/newlib/libc/machine/powerpc/strtosfix16.c @@ -0,0 +1,206 @@ +/* +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. +*/ + +#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 |