newlib-cygwin/newlib/libc/machine/powerpc/strtoufix16.c

198 lines
5.2 KiB
C

/*
FUNCTION
<<strtoufix16>>, <<strtoufix32>>, <<strtoufix64>>---string to signed fixed point
INDEX
strtoufix16
INDEX
strtoufix32
INDEX
strtoufix64
INDEX
_strtoufix16_r
INDEX
_strtoufix32_r
INDEX
_strtoufix64_r
ANSI_SYNOPSIS
#include <stdlib.h>
__uint16_t strtoufix16 (const char *<[s]>, char **<[ptr]>);
__uint32_t strtoufix32 (const char *<[s]>, char **<[ptr]>);
__uint64_t strtoufix64 (const char *<[s]>, char **<[ptr]>);
__uint16_t _strtoufix16_r (void *<[reent]>,
const char *<[s]>, char **<[ptr]>);
__uint32_t _strtoufix32_r (void *<[reent]>,
const char *<[s]>, char **<[ptr]>);
__uint64_t _strtoufix64_r (void *<[reent]>,
const char *<[s]>, char **<[ptr]>);
TRAD_SYNOPSIS
#include <stdlib.h>
__uint16_t strtoufix16 (<[s]>, <[ptr]>)
char *<[s]>;
char **<[ptr]>;
__uint32_t strtoufix32 (<[s]>, <[ptr]>)
char *<[s]>;
char **<[ptr]>;
__uint64_t strtoufix64 (<[s]>, <[ptr]>)
char *<[s]>;
char **<[ptr]>;
__uint16_t _strtoufix16_r (<[reent]>, <[s]>, <[ptr]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
__uint32_t _strtoufix32_r (<[reent]>, <[s]>, <[ptr]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
__uint64_t _strtoufix64_r (<[reent]>, <[s]>, <[ptr]>)
char *<[reent]>;
char *<[s]>;
char **<[ptr]>;
DESCRIPTION
The function <<strtoufix16>> converts the string <<*<[s]>>> to
a fixed-point 16-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]>.
<<strtoufix32>> is identical to <<strtoufix16>> except that it
converts to fixed-point 32-bit fraction representation.
<<strtoufix64>> is also similar, except that it converts
to fixed-point 64-bit fraction.
The alternate functions <<_strtoufix16_r>>, <<_strtoufix32_r>>,
and <<_strtoufix64_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 unsigned 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 0, then the output is saturated to 0
and <<ERANGE>> is stored in errno. Otherwise, the converted value is returned in the
specified fixed-point format.
PORTABILITY
<<strtoufix16>>, <<strtoufix32>>, and <<strtoufix64>> 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 16-bit value.
*
* Ignores `locale' stuff.
*/
__uint16_t
_DEFUN (_strtoufix16_r, (rptr, nptr, endptr),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr)
{
union double_union dbl;
unsigned long tmp, tmp2, result;
int exp, negexp;
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 0;
return USHRT_MAX;
}
/* check for normal saturation */
if (dbl.d >= 1.0)
{
rptr->_errno = ERANGE;
return USHRT_MAX;
}
else if (dbl.d < 0)
{
rptr->_errno = ERANGE;
return 0;
}
/* otherwise we have normal postive number in range */
/* strip off exponent */
exp = ((word0(dbl) & Exp_mask) >> Exp_shift) - Bias;
negexp = -exp;
if (negexp > 16)
return 0;
/* add in implicit normalized bit */
tmp = word0(dbl) | Exp_msk1;
/* remove exponent and sign */
tmp <<= Ebits;
/* perform rounding */
tmp2 = tmp + (1 << (negexp + 14));
result = tmp2 >> (negexp + 15);
/* if rounding causes carry, must add carry bit in */
if (tmp2 < tmp)
{
if (negexp == 0)
{
/* we have overflow which means saturation */
rptr->_errno = ERANGE;
return USHRT_MAX;
}
result |= (1 << (16 - negexp));
}
return (__uint16_t)result;
}
#ifndef _REENT_ONLY
__uint16_t
_DEFUN (strtoufix16, (s, ptr, base),
_CONST char *s _AND
char **ptr)
{
return _strtoufix16_r (_REENT, s, ptr);
}
#endif