OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [libbid/] [bid128_quantize.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* Copyright (C) 2007, 2009  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
<http://www.gnu.org/licenses/>.  */
23
 
24
#define BID_128RES
25
#include "bid_internal.h"
26
 
27
BID128_FUNCTION_ARG2 (bid128_quantize, x, y)
28
 
29
     UINT256 CT;
30
     UINT128 CX, CY, T, CX2, CR, Stemp, res, REM_H, C2N;
31
     UINT64 sign_x, sign_y, remainder_h, carry, CY64, valid_x;
32
     int_float tempx;
33
     int exponent_x, exponent_y, digits_x, extra_digits, amount;
34
     int expon_diff, total_digits, bin_expon_cx, rmode, status;
35
 
36
valid_x = unpack_BID128_value (&sign_x, &exponent_x, &CX, x);
37
 
38
  // unpack arguments, check for NaN or Infinity
39
if (!unpack_BID128_value (&sign_y, &exponent_y, &CY, y)) {
40
    // y is Inf. or NaN
41
#ifdef SET_STATUS_FLAGS
42
if ((x.w[1] & SNAN_MASK64) == SNAN_MASK64)      // y is sNaN
43
  __set_status_flags (pfpsf, INVALID_EXCEPTION);
44
#endif
45
 
46
    // test if y is NaN
47
if ((y.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
48
#ifdef SET_STATUS_FLAGS
49
  if ((y.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) {
50
    // set status flags
51
    __set_status_flags (pfpsf, INVALID_EXCEPTION);
52
  }
53
#endif
54
  if ((x.w[1] & 0x7c00000000000000ull) != 0x7c00000000000000ull) {
55
    res.w[1] = CY.w[1] & QUIET_MASK64;
56
    res.w[0] = CY.w[0];
57
  } else {
58
    res.w[1] = CX.w[1] & QUIET_MASK64;
59
    res.w[0] = CX.w[0];
60
  }
61
  BID_RETURN (res);
62
}
63
    // y is Infinity?
64
if ((y.w[1] & 0x7800000000000000ull) == 0x7800000000000000ull) {
65
  // check if x is not Inf.
66
  if (((x.w[1] & 0x7c00000000000000ull) < 0x7800000000000000ull)) {
67
    // return NaN 
68
#ifdef SET_STATUS_FLAGS
69
    // set status flags
70
    __set_status_flags (pfpsf, INVALID_EXCEPTION);
71
#endif
72
    res.w[1] = 0x7c00000000000000ull;
73
    res.w[0] = 0;
74
    BID_RETURN (res);
75
  } else
76
    if (((x.w[1] & 0x7c00000000000000ull) <= 0x7800000000000000ull)) {
77
    res.w[1] = CX.w[1] & QUIET_MASK64;
78
    res.w[0] = CX.w[0];
79
    BID_RETURN (res);
80
  }
81
}
82
 
83
}
84
 
85
if (!valid_x) {
86
  // test if x is NaN or Inf
87
  if ((x.w[1] & 0x7c00000000000000ull) == 0x7800000000000000ull) {
88
#ifdef SET_STATUS_FLAGS
89
    // set status flags
90
    __set_status_flags (pfpsf, INVALID_EXCEPTION);
91
#endif
92
    res.w[1] = 0x7c00000000000000ull;
93
    res.w[0] = 0;
94
    BID_RETURN (res);
95
  } else if ((x.w[1] & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
96
    if ((x.w[1] & 0x7e00000000000000ull) == 0x7e00000000000000ull) {
97
#ifdef SET_STATUS_FLAGS
98
      // set status flags
99
      __set_status_flags (pfpsf, INVALID_EXCEPTION);
100
#endif
101
    }
102
    res.w[1] = CX.w[1] & QUIET_MASK64;
103
    res.w[0] = CX.w[0];
104
    BID_RETURN (res);
105
  }
106
  if (!CX.w[1] && !CX.w[0]) {
107
    get_BID128_very_fast (&res, sign_x, exponent_y, CX);
108
    BID_RETURN (res);
109
  }
110
}
111
  // get number of decimal digits in coefficient_x
112
if (CX.w[1]) {
113
  tempx.d = (float) CX.w[1];
114
  bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f + 64;
115
} else {
116
  tempx.d = (float) CX.w[0];
117
  bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f;
118
}
119
 
120
digits_x = estimate_decimal_digits[bin_expon_cx];
121
if (CX.w[1] > power10_table_128[digits_x].w[1]
122
    || (CX.w[1] == power10_table_128[digits_x].w[1]
123
        && CX.w[0] >= power10_table_128[digits_x].w[0]))
124
  digits_x++;
125
 
126
expon_diff = exponent_x - exponent_y;
127
total_digits = digits_x + expon_diff;
128
 
129
if ((UINT32) total_digits <= 34) {
130
  if (expon_diff >= 0) {
131
    T = power10_table_128[expon_diff];
132
    __mul_128x128_low (CX2, T, CX);
133
    get_BID128_very_fast (&res, sign_x, exponent_y, CX2);
134
    BID_RETURN (res);
135
  }
136
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
137
#ifndef IEEE_ROUND_NEAREST
138
  rmode = rnd_mode;
139
  if (sign_x && (unsigned) (rmode - 1) < 2)
140
    rmode = 3 - rmode;
141
#else
142
  rmode = 0;
143
#endif
144
#else
145
  rmode = 0;
146
#endif
147
  // must round off -expon_diff digits
148
  extra_digits = -expon_diff;
149
  __add_128_128 (CX, CX, round_const_table_128[rmode][extra_digits]);
150
 
151
  // get P*(2^M[extra_digits])/10^extra_digits
152
  __mul_128x128_to_256 (CT, CX, reciprocals10_128[extra_digits]);
153
 
154
  // now get P/10^extra_digits: shift C64 right by M[extra_digits]-128
155
  amount = recip_scale[extra_digits];
156
  CX2.w[0] = CT.w[2];
157
  CX2.w[1] = CT.w[3];
158
  if (amount >= 64) {
159
    CR.w[1] = 0;
160
    CR.w[0] = CX2.w[1] >> (amount - 64);
161
  } else {
162
    __shr_128 (CR, CX2, amount);
163
  }
164
 
165
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
166
#ifndef IEEE_ROUND_NEAREST
167
  if (rnd_mode == 0)
168
#endif
169
    if (CR.w[0] & 1) {
170
      // check whether fractional part of initial_P/10^extra_digits is 
171
      // exactly .5 this is the same as fractional part of 
172
      // (initial_P + 0.5*10^extra_digits)/10^extra_digits is exactly zero
173
 
174
      // get remainder
175
      if (amount >= 64) {
176
        remainder_h = CX2.w[0] | (CX2.w[1] << (128 - amount));
177
      } else
178
        remainder_h = CX2.w[0] << (64 - amount);
179
 
180
      // test whether fractional part is 0
181
      if (!remainder_h
182
          && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
183
              || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
184
                  && CT.w[0] < reciprocals10_128[extra_digits].w[0]))) {
185
        CR.w[0]--;
186
      }
187
    }
188
#endif
189
 
190
#ifdef SET_STATUS_FLAGS
191
  status = INEXACT_EXCEPTION;
192
 
193
  // get remainder
194
  if (amount >= 64) {
195
    REM_H.w[1] = (CX2.w[1] << (128 - amount));
196
    REM_H.w[0] = CX2.w[0];
197
  } else {
198
    REM_H.w[1] = CX2.w[0] << (64 - amount);
199
    REM_H.w[0] = 0;
200
  }
201
 
202
  switch (rmode) {
203
  case ROUNDING_TO_NEAREST:
204
  case ROUNDING_TIES_AWAY:
205
    // test whether fractional part is 0
206
    if (REM_H.w[1] == 0x8000000000000000ull && !REM_H.w[0]
207
        && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
208
            || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
209
                && CT.w[0] < reciprocals10_128[extra_digits].w[0])))
210
      status = EXACT_STATUS;
211
    break;
212
  case ROUNDING_DOWN:
213
  case ROUNDING_TO_ZERO:
214
    if (!(REM_H.w[1] | REM_H.w[0])
215
        && (CT.w[1] < reciprocals10_128[extra_digits].w[1]
216
            || (CT.w[1] == reciprocals10_128[extra_digits].w[1]
217
                && CT.w[0] < reciprocals10_128[extra_digits].w[0])))
218
      status = EXACT_STATUS;
219
    break;
220
  default:
221
    // round up
222
    __add_carry_out (Stemp.w[0], CY64, CT.w[0],
223
                     reciprocals10_128[extra_digits].w[0]);
224
    __add_carry_in_out (Stemp.w[1], carry, CT.w[1],
225
                        reciprocals10_128[extra_digits].w[1], CY64);
226
    if (amount < 64) {
227
      C2N.w[1] = 0;
228
      C2N.w[0] = ((UINT64) 1) << amount;
229
      REM_H.w[0] = REM_H.w[1] >> (64 - amount);
230
      REM_H.w[1] = 0;
231
    } else {
232
      C2N.w[1] = ((UINT64) 1) << (amount - 64);
233
      C2N.w[0] = 0;
234
      REM_H.w[1] >>= (128 - amount);
235
    }
236
    REM_H.w[0] += carry;
237
    if (REM_H.w[0] < carry)
238
      REM_H.w[1]++;
239
    if (__unsigned_compare_ge_128 (REM_H, C2N))
240
      status = EXACT_STATUS;
241
  }
242
 
243
  __set_status_flags (pfpsf, status);
244
 
245
#endif
246
  get_BID128_very_fast (&res, sign_x, exponent_y, CR);
247
  BID_RETURN (res);
248
}
249
if (total_digits < 0) {
250
  CR.w[1] = CR.w[0] = 0;
251
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
252
#ifndef IEEE_ROUND_NEAREST
253
  rmode = rnd_mode;
254
  if (sign_x && (unsigned) (rmode - 1) < 2)
255
    rmode = 3 - rmode;
256
  if (rmode == ROUNDING_UP)
257
    CR.w[0] = 1;
258
#endif
259
#endif
260
#ifdef SET_STATUS_FLAGS
261
  __set_status_flags (pfpsf, INEXACT_EXCEPTION);
262
#endif
263
  get_BID128_very_fast (&res, sign_x, exponent_y, CR);
264
  BID_RETURN (res);
265
}
266
  // else  more than 34 digits in coefficient
267
#ifdef SET_STATUS_FLAGS
268
__set_status_flags (pfpsf, INVALID_EXCEPTION);
269
#endif
270
res.w[1] = 0x7c00000000000000ull;
271
res.w[0] = 0;
272
BID_RETURN (res);
273
 
274
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.