Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 1
/* Copyright (C) 2007-2015 Free Software Foundation, Inc.
2
 
3
This file is part of GCC.
4
 
5
GCC is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free
7
Software Foundation; either version 3, or (at your option) any later
8
version.
9
 
10
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11
WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13
for more details.
14
 
15
Under Section 7 of GPL version 3, you are granted additional
16
permissions described in the GCC Runtime Library Exception, version
17
3.1, as published by the Free Software Foundation.
18
 
19
You should have received a copy of the GNU General Public License and
20
a copy of the GCC Runtime Library Exception along with this program;
21
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22
.  */
23
 
24
#include "bid_internal.h"
25
 
26
/*
27
 * Takes a BID32 as input and converts it to a BID64 and returns it.
28
 */
29
TYPE0_FUNCTION_ARGTYPE1_NORND (UINT64, bid32_to_bid64, UINT32, x)
30
 
31
     UINT64 res;
32
     UINT32 sign_x;
33
     int exponent_x;
34
     UINT32 coefficient_x;
35
 
36
if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) {
37
    // Inf, NaN, 0
38
if (((x) & 0x78000000) == 0x78000000) {
39
  if (((x) & 0x7e000000) == 0x7e000000) {	// sNaN
40
#ifdef SET_STATUS_FLAGS
41
    __set_status_flags (pfpsf, INVALID_EXCEPTION);
42
#endif
43
  }
44
  res = (coefficient_x & 0x000fffff);
45
  res *= 1000000000;
46
  res |= ((((UINT64) coefficient_x) << 32) & 0xfc00000000000000ull);
47
 
48
  BID_RETURN (res);
49
}
50
}
51
 
52
res =
53
very_fast_get_BID64_small_mantissa (((UINT64) sign_x) << 32,
54
				    exponent_x +
55
				    DECIMAL_EXPONENT_BIAS -
56
				    DECIMAL_EXPONENT_BIAS_32,
57
				    (UINT64) coefficient_x);
58
BID_RETURN (res);
59
}	// convert_bid32_to_bid64
60
 
61
 
62
/*
63
 * Takes a BID64 as input and converts it to a BID32 and returns it.
64
 */
65
#if DECIMAL_CALL_BY_REFERENCE
66
 
67
void
68
bid64_to_bid32 (UINT32 * pres,
69
		UINT64 *
70
		px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
71
		_EXC_INFO_PARAM) {
72
  UINT64 x;
73
#else
74
 
75
UINT32
76
bid64_to_bid32 (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
77
		_EXC_MASKS_PARAM _EXC_INFO_PARAM) {
78
#endif
79
  UINT128 Q;
80
  UINT64 sign_x, coefficient_x, remainder_h, carry, Stemp;
81
  UINT32 res;
82
  int_float tempx;
83
  int exponent_x, bin_expon_cx, extra_digits, rmode = 0, amount;
84
  unsigned status = 0;
85
 
86
#if DECIMAL_CALL_BY_REFERENCE
87
#if !DECIMAL_GLOBAL_ROUNDING
88
  _IDEC_round rnd_mode = *prnd_mode;
89
#endif
90
  x = *px;
91
#endif
92
 
93
  // unpack arguments, check for NaN or Infinity, 0
94
  if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) {
95
    if (((x) & 0x7800000000000000ull) == 0x7800000000000000ull) {
96
      res = (coefficient_x & 0x0003ffffffffffffull);
97
      res /= 1000000000ull;
98
      res |= ((coefficient_x >> 32) & 0xfc000000);
99
#ifdef SET_STATUS_FLAGS
100
      if ((x & SNAN_MASK64) == SNAN_MASK64)	// sNaN
101
	__set_status_flags (pfpsf, INVALID_EXCEPTION);
102
#endif
103
      BID_RETURN (res);
104
    }
105
    exponent_x =
106
      exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32;
107
    if (exponent_x < 0)
108
      exponent_x = 0;
109
    if (exponent_x > DECIMAL_MAX_EXPON_32)
110
      exponent_x = DECIMAL_MAX_EXPON_32;
111
    res = (sign_x >> 32) | (exponent_x << 23);
112
    BID_RETURN (res);
113
  }
114
 
115
  exponent_x =
116
    exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32;
117
 
118
  // check number of digits
119
  if (coefficient_x >= 10000000) {
120
    tempx.d = (float) coefficient_x;
121
    bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
122
    extra_digits = estimate_decimal_digits[bin_expon_cx] - 7;
123
    // add test for range
124
    if (coefficient_x >= power10_index_binexp[bin_expon_cx])
125
      extra_digits++;
126
 
127
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
128
#ifndef IEEE_ROUND_NEAREST
129
    rmode = rnd_mode;
130
    if (sign_x && (unsigned) (rmode - 1) < 2)
131
      rmode = 3 - rmode;
132
#else
133
    rmode = 0;
134
#endif
135
#else
136
    rmode = 0;
137
#endif
138
 
139
    exponent_x += extra_digits;
140
    if ((exponent_x < 0) && (exponent_x + MAX_FORMAT_DIGITS_32 >= 0)) {
141
      status = UNDERFLOW_EXCEPTION;
142
      if (exponent_x == -1)
143
	if (coefficient_x + round_const_table[rmode][extra_digits] >=
144
	    power10_table_128[extra_digits + 7].w[0])
145
	  status = 0;
146
      extra_digits -= exponent_x;
147
      exponent_x = 0;
148
    }
149
    coefficient_x += round_const_table[rmode][extra_digits];
150
    __mul_64x64_to_128 (Q, coefficient_x,
151
			reciprocals10_64[extra_digits]);
152
 
153
    // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
154
    amount = short_recip_scale[extra_digits];
155
 
156
    coefficient_x = Q.w[1] >> amount;
157
 
158
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
159
#ifndef IEEE_ROUND_NEAREST
160
    if (rmode == 0)	//ROUNDING_TO_NEAREST
161
#endif
162
      if (coefficient_x & 1) {
163
	// check whether fractional part of initial_P/10^extra_digits
164
	// is exactly .5
165
 
166
	// get remainder
167
	remainder_h = Q.w[1] << (64 - amount);
168
 
169
	if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
170
	  coefficient_x--;
171
      }
172
#endif
173
 
174
#ifdef SET_STATUS_FLAGS
175
 
176
    {
177
      status |= INEXACT_EXCEPTION;
178
      // get remainder
179
      remainder_h = Q.w[1] << (64 - amount);
180
 
181
      switch (rmode) {
182
      case ROUNDING_TO_NEAREST:
183
      case ROUNDING_TIES_AWAY:
184
	// test whether fractional part is 0
185
	if (remainder_h == 0x8000000000000000ull
186
	    && (Q.w[0] < reciprocals10_64[extra_digits]))
187
	  status = EXACT_STATUS;
188
	break;
189
      case ROUNDING_DOWN:
190
      case ROUNDING_TO_ZERO:
191
	if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
192
	  status = EXACT_STATUS;
193
	break;
194
      default:
195
	// round up
196
	__add_carry_out (Stemp, carry, Q.w[0],
197
			 reciprocals10_64[extra_digits]);
198
	if ((remainder_h >> (64 - amount)) + carry >=
199
	    (((UINT64) 1) << amount))
200
	  status = EXACT_STATUS;
201
      }
202
 
203
      if (status != EXACT_STATUS)
204
	__set_status_flags (pfpsf, status);
205
    }
206
 
207
#endif
208
 
209
  }
210
 
211
  res =
212
    get_BID32 ((UINT32) (sign_x >> 32),
213
	       exponent_x, coefficient_x, rnd_mode, pfpsf);
214
  BID_RETURN (res);
215
 
216
}