Welcome to mirror list, hosted at ThFree Co, Russian Federation.

strtosfix32.c « powerpc « machine « libc « newlib - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2e22c14581bbb50fc3b1248d0e4bac893662f431 (plain)
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
#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 + 31-bits) value.
 *
 * Ignores `locale' stuff.
 */
__int32_t
_DEFUN (_strtosfix32_r, (rptr, nptr, endptr),
	struct _reent *rptr _AND
	_CONST char *nptr _AND
	char **endptr)
{
  union double_union dbl;
  int exp, negexp, sign;
  unsigned long tmp, tmp2;
  long result = 0;

  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 LONG_MIN;
      return LONG_MAX;
    }

  /* check for normal saturation */
  if (dbl.d >= 1.0)
    {
      rptr->_errno = ERANGE;
      return LONG_MAX;
    }
  else if (dbl.d < -1.0)
    {
      rptr->_errno = ERANGE;
      return LONG_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 > 31)
    return 0;
  word0(dbl) &= ~(Exp_mask | Sign_bit);
  /* add in implicit normalized bit */
  word0(dbl) |= Exp_msk1;
  /* shift so result is contained in single word */
  tmp = word0(dbl) << Ebits;
  tmp |= ((unsigned long)word1(dbl) >> (32 - Ebits));
  if (negexp != 0)
    {
      /* perform rounding */
      tmp2 = tmp + (1 << (negexp - 1));
      result = (long)(tmp2 >> negexp);
      /* check if rounding caused carry bit which must be added into result */
      if (tmp2 < tmp)
	result |= (1 << (32 - negexp));
      /* check if positive saturation has occurred because of rounding */
      if (!sign && result < 0)
	{
	  rptr->_errno = ERANGE;
	  return LONG_MAX;
	}
    }
  else
    {
      /* we have -1.0, no rounding necessary */
      return LONG_MIN;
    }

  return sign ? -result : result;
}

#ifndef _REENT_ONLY

__int32_t
_DEFUN (strtosfix32, (s, ptr, base),
	_CONST char *s _AND
	char **ptr)
{
  return _strtosfix32_r (_REENT, s, ptr);
}

#endif

#endif /* __SPE__ */