1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#ifdef __SPE__
#include <_ansi.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
#include "fix64.h"
/*
* Convert a string to a fixed-point (sign + 63-bits) value.
*
* Ignores `locale' stuff.
*/
__int64_t
_DEFUN (_strtosfix64_r, (rptr, nptr, endptr),
struct _reent *rptr _AND
_CONST char *nptr _AND
char **endptr)
{
union long_double_union ldbl;
int exp, negexp, sign, ld_type;
__uint64_t tmp, tmp2;
__int64_t result = 0;
init(ldbl);
_simdstrtold ((char *)nptr, endptr, &ldbl);
/* treat NAN as domain error, +/- infinity as saturation */
ld_type = _simdldcheck (&ldbl.ld);
if (ld_type != 0)
{
if (ld_type == 1)
{
rptr->_errno = EDOM;
return 0;
}
rptr->_errno = ERANGE;
if (word0(ldbl) & Sign_bit)
return LONG_LONG_MIN;
return LONG_LONG_MAX;
}
/* strip off sign and exponent */
sign = word0(ldbl) & Sign_bit;
exp = ((word0(ldbl) & Exp_mask) >> Exp_shift) - Bias;
negexp = -exp;
if (negexp > 63)
return 0;
word0(ldbl) &= ~(Exp_mask | Sign_bit);
/* add in implicit normalized bit */
word0(ldbl) |= Exp_msk1;
/* shift so result is contained in single word */
tmp = word0(ldbl) << Ebits;
tmp |= ((unsigned long)word1(ldbl) >> (32 - Ebits));
tmp <<= 32;
if (Ebits < 32)
tmp |= ((unsigned long)word1(ldbl) << Ebits);
tmp |= ((unsigned long)word2(ldbl) >> (32 - Ebits));
/* check for saturation */
if (sign)
{
if (exp > 0 || (exp == 0 && tmp != 0x8000000000000000LL))
{
rptr->_errno = ERANGE;
return LONG_LONG_MIN;
}
}
else
{
if (exp >= 0)
{
rptr->_errno = ERANGE;
return LONG_LONG_MAX;
}
}
/* otherwise we have normal number in range */
if (negexp != 0)
{
/* perform rounding */
tmp2 = tmp + (1 << (negexp - 1));
result = (long long)(tmp2 >> negexp);
/* check if rounding caused carry bit which must be added into result */
if (tmp2 < tmp)
result |= (1 << (64 - negexp));
/* check if positive saturation has occurred because of rounding */
if (!sign && result < 0)
{
rptr->_errno = ERANGE;
return LONG_LONG_MAX;
}
}
else
{
/* we have -1.0, no rounding necessary */
return LONG_LONG_MIN;
}
return sign ? -result : result;
}
#ifndef _REENT_ONLY
__int64_t
_DEFUN (strtosfix64, (s, ptr, base),
_CONST char *s _AND
char **ptr)
{
return _strtosfix64_r (_REENT, s, ptr);
}
#endif
#endif /* __SPE__ */
|