source: trunk/libs/newlib/src/newlib/libc/machine/powerpc/strtosfix16.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 4.8 KB
Line 
1/*
2FUNCTION
3        <<strtosfix16>>, <<strtosfix32>>, <<strtosfix64>>---string to signed fixed point
4
5INDEX
6        strtosfix16
7INDEX
8        strtosfix32
9INDEX
10        strtosfix64
11INDEX
12        _strtosfix16_r
13INDEX
14        _strtosfix32_r
15INDEX
16        _strtosfix64_r
17
18SYNOPSIS
19        #include <stdlib.h>
20        __int16 strtosfix16 (const char *<[s]>, char **<[ptr]>);
21
22        __int32 strtosfix32 (const char *<[s]>, char **<[ptr]>);
23
24        __int64 strtosfix64 (const char *<[s]>, char **<[ptr]>);
25
26        __int16 _strtosfix16_r (void *<[reent]>,
27                       const char *<[s]>, char **<[ptr]>);
28
29        __int32 _strtosfix32_r (void *<[reent]>,
30                       const char *<[s]>, char **<[ptr]>);
31
32        __int64 _strtosfix64_r (void *<[reent]>,
33                       const char *<[s]>, char **<[ptr]>);
34
35DESCRIPTION
36        The function <<strtosfix16>> converts the string <<*<[s]>>> to
37        a fixed-point sign + 15-bits fraction representation.  The function
38        follows the same rules as <<strtod>>.
39
40        The substring converted is the longest initial
41        subsequence of <[s]>, beginning with the first
42        non-whitespace character, that has the format:
43        .[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
44        The substring contains no characters if <[s]> is empty, consists
45        entirely of whitespace, or if the first non-whitespace
46        character is something other than <<+>>, <<->>, <<.>>, or a
47        digit. If the substring is empty, no conversion is done, and
48        the value of <[s]> is stored in <<*<[ptr]>>>.  Otherwise,
49        the substring is converted, and a pointer to the final string
50        (which will contain at least the terminating null character of
51        <[s]>) is stored in <<*<[ptr]>>>.  If you want no
52        assignment to <<*<[ptr]>>>, pass a null pointer as <[ptr]>.
53
54        <<strtosfix32>> is identical to <<strtosfix16>> except that it
55        converts to fixed-point sign + 31-bits fraction representation.
56        <<strtosfix64>> is also similar, except that it converts
57        to fixed-point sign + 63-bit fraction format.
58
59        The alternate functions <<_strtosfix16_r>>, <<_strtosfix32_r>>,
60        and <<_strtosfix64_r>> are reentrant versions.
61        The extra argument <[reent]> is a pointer to a reentrancy structure.
62
63RETURNS
64        The functions return the converted substring value, if any.  If
65        no conversion can be performed, then 0 is returned.  If the converted
66        value is a NaN, 0 is returned and errno is set to <<EDOM>>.
67        If the converted value exceeds the maximum positive fixed-point value,
68        the output value is saturated to the maximum value and <<ERANGE>> is stored in
69        errno.  If the converted value is less than the minimum fixed-point negative
70        value, then the output is saturated to the minimum value  and <<ERANGE>> is stored
71        in errno.  Otherwise, the converted value is returned in the
72        specified fixed-point format.
73
74PORTABILITY
75        <<strtosfix16>>, <<strtosfix32>>, and <<strtosfix64>> are non-standard.
76
77        The OS subroutines of <<strtod>> are required.
78*/
79
80#ifdef __SPE__
81
82#include <_ansi.h>
83#include <limits.h>
84#include <errno.h>
85#include <stdlib.h>
86#include <reent.h>
87#include "vfieeefp.h"
88
89/*
90 * Convert a string to a fixed-point (sign + 15-bits) value.
91 *
92 * Ignores `locale' stuff.
93 */
94__int16_t
95_strtosfix16_r (struct _reent *rptr,
96        const char *nptr,
97        char **endptr)
98{
99  union double_union dbl;
100  unsigned long tmp, tmp2;
101  int exp, negexp, sign;
102  __int16_t result;
103
104  dbl.d = _strtod_r (rptr, nptr, endptr);
105
106  /* treat NAN as domain error, +/- infinity as saturation */
107  if (!finite(dbl.d))
108    {
109      if (isnan (dbl.d))
110        {
111          rptr->_errno = EDOM;
112          return 0;
113        }
114      rptr->_errno = ERANGE;
115      if (word0(dbl) & Sign_bit)
116        return SHRT_MIN;
117      return SHRT_MAX;
118    }
119
120  /* check for normal saturation */
121  if (dbl.d >= 1.0)
122    {
123      rptr->_errno = ERANGE;
124      return SHRT_MAX;
125    }
126  else if (dbl.d < -1.0)
127    {
128      rptr->_errno = ERANGE;
129      return SHRT_MIN;
130    }
131
132  /* otherwise we have normal number in range */
133
134  /* strip off sign and exponent */
135  sign = word0(dbl) & Sign_bit;
136  exp = ((word0(dbl) & Exp_mask) >> Exp_shift) - Bias;
137  negexp = -exp;
138  if (negexp > 15)
139    return 0;
140  /* add in implicit normalized bit */
141  tmp = word0(dbl) | Exp_msk1;
142  /* remove exponent and sign */
143  tmp <<= Ebits;
144  if (negexp != 0)
145    {
146      /* perform rounding */
147      tmp2 = tmp + (1 << (negexp - 1));
148      result = (short)(tmp2 >> (negexp + 16));
149      /* check if rounding caused carry bit which must be added into result */
150      if (tmp2 < tmp)
151        result |= (1 << (16 - negexp));
152      /* check if positive saturation has occurred because of rounding */
153      if (!sign && result < 0)
154        {
155          rptr->_errno = ERANGE;
156          return SHRT_MAX;
157        }
158    }
159  else
160    {
161      /* we have -1.0, no rounding necessary */
162      return SHRT_MIN;
163    }
164
165  return  sign ? -result : result;
166}
167
168#ifndef _REENT_ONLY
169
170__int16_t
171strtosfix16 (const char *s,
172        char **ptr)
173{
174  return _strtosfix16_r (_REENT, s, ptr);
175}
176
177#endif
178
179#endif /* __SPE__ */
Note: See TracBrowser for help on using the repository browser.