mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-04 16:50:57 +00:00
180 lines
4.8 KiB
C
180 lines
4.8 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
|
|
|
|
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]>);
|
|
|
|
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
|
|
_strtosfix16_r (struct _reent *rptr,
|
|
const char *nptr,
|
|
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
|
|
strtosfix16 (const char *s,
|
|
char **ptr)
|
|
{
|
|
return _strtosfix16_r (_REENT, s, ptr);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* __SPE__ */
|