]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/libbid/bid128_to_string.c
re PR tree-optimization/33565 (spurious warning: assuming signed overflow does not...
[thirdparty/gcc.git] / libgcc / config / libbid / bid128_to_string.c
1 /* Copyright (C) 2007 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 2, or (at your option) any later
8 version.
9
10 In addition to the permissions in the GNU General Public License, the
11 Free Software Foundation gives you unlimited permission to link the
12 compiled version of this file into combinations with other programs,
13 and to distribute those combinations without any restriction coming
14 from the use of this file. (The General Public License restrictions
15 do apply in other respects; for example, they cover modification of
16 the file, and distribution when not linked into a combine
17 executable.)
18
19 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING. If not, write to the Free
26 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA. */
28
29 /*****************************************************************************
30 * BID128_to_string
31 ****************************************************************************/
32
33 #include <stdio.h>
34 #include "bid_internal.h"
35 #include "bid128_2_str.h"
36 #include "bid128_2_str_macros.h"
37
38 extern int __bid128_coeff_2_string (UINT64 X_hi, UINT64 X_lo,
39 char *char_ptr);
40
41 #if DECIMAL_CALL_BY_REFERENCE
42
43 void
44 __bid128_to_string (char *str,
45 UINT128 *
46 px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
47 _EXC_INFO_PARAM) {
48 UINT128 x;
49 #else
50
51 void
52 __bid128_to_string (char *str,
53 UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
54 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
55 #endif
56 UINT64 x_sign;
57 UINT64 x_exp;
58 int exp; // unbiased exponent
59 // Note: C1.w[1], C1.w[0] represent x_signif_hi, x_signif_lo (all are UINT64)
60 int ind;
61 UINT128 C1;
62 unsigned int k = 0; // pointer in the string
63 unsigned int d0, d123;
64 UINT64 HI_18Dig, LO_18Dig, Tmp;
65 UINT32 MiDi[12], *ptr;
66 char *c_ptr_start, *c_ptr;
67 int midi_ind, k_lcv, len;
68
69 #if DECIMAL_CALL_BY_REFERENCE
70 #if !DECIMAL_GLOBAL_ROUNDING
71 _IDEC_round rnd_mode = *prnd_mode;
72 #endif
73 x = *px;
74 #endif
75
76 // check for NaN or Infinity
77 if ((x.w[1] & MASK_SPECIAL) == MASK_SPECIAL) {
78 // x is special
79 if ((x.w[1] & MASK_NAN) == MASK_NAN) { // x is NAN
80 if ((x.w[1] & MASK_SNAN) == MASK_SNAN) { // x is SNAN
81 // set invalid flag
82 *pfpsf |= INVALID_EXCEPTION;
83 str[0] = 'S';
84 str[1] = 'N';
85 str[2] = 'a';
86 str[3] = 'N';
87 str[4] = '\0';
88 } else { // x is QNaN
89 str[0] = 'Q';
90 str[1] = 'N';
91 str[2] = 'a';
92 str[3] = 'N';
93 str[4] = '\0';
94 }
95 } else { // x is not a NaN, so it must be infinity
96 if ((x.w[1] & MASK_SIGN) == 0x0ull) { // x is +inf
97 str[0] = '+';
98 str[1] = 'I';
99 str[2] = 'n';
100 str[3] = 'f';
101 str[4] = '\0';
102 } else { // x is -inf
103 str[0] = '-';
104 str[1] = 'I';
105 str[2] = 'n';
106 str[3] = 'f';
107 str[4] = '\0';
108 }
109 }
110 return;
111 } else if (((x.w[1] & MASK_COEFF) == 0x0ull) && (x.w[0] == 0x0ull)) {
112 // x is 0
113 len = 0;
114
115 //determine if +/-
116 if (x.w[1] & MASK_SIGN)
117 str[len++] = '-';
118 else
119 str[len++] = '+';
120 str[len++] = '0';
121 str[len++] = 'E';
122
123 // extract the exponent and print
124 exp = (int) (((x.w[1] & MASK_EXP) >> 49) - 6176);
125 if (exp >= 0) {
126 str[len++] = '+';
127 len += sprintf (str + len, "%u", exp);// should not use sprintf (should
128 // use sophisticated algorithm, since we know range of exp is limited)
129 str[len++] = '\0';
130 } else {
131 len += sprintf (str + len, "%d", exp);// should not use sprintf (should
132 // use sophisticated algorithm, since we know range of exp is limited)
133 str[len++] = '\0';
134 }
135 return;
136 } else { // x is not special and is not zero
137 // unpack x
138 x_sign = x.w[1] & MASK_SIGN;// 0 for positive, MASK_SIGN for negative
139 x_exp = x.w[1] & MASK_EXP;// biased and shifted left 49 bit positions
140 C1.w[1] = x.w[1] & MASK_COEFF;
141 C1.w[0] = x.w[0];
142 exp = (x_exp >> 49) - 6176;
143
144 // determine sign's representation as a char
145 if (x_sign)
146 str[k++] = '-';// negative number
147 else
148 str[k++] = '+';// positive number
149
150 // determine coefficient's representation as a decimal string
151
152 // if zero or non-canonical, set coefficient to '0'
153 if ((C1.w[1] > 0x0001ed09bead87c0ull) ||
154 (C1.w[1] == 0x0001ed09bead87c0ull &&
155 (C1.w[0] > 0x378d8e63ffffffffull)) ||
156 ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) ||
157 ((C1.w[1] == 0) && (C1.w[0] == 0))) {
158 str[k++] = '0';
159 } else {
160 /* ****************************************************
161 This takes a bid coefficient in C1.w[1],C1.w[0]
162 and put the converted character sequence at location
163 starting at &(str[k]). The function returns the number
164 of MiDi returned. Note that the character sequence
165 does not have leading zeros EXCEPT when the input is of
166 zero value. It will then output 1 character '0'
167 The algorithm essentailly tries first to get a sequence of
168 Millenial Digits "MiDi" and then uses table lookup to get the
169 character strings of these MiDis.
170 **************************************************** */
171 /* Algorithm first decompose possibly 34 digits in hi and lo
172 18 digits. (The high can have at most 16 digits). It then
173 uses macro that handle 18 digit portions.
174 The first step is to get hi and lo such that
175 2^(64) C1.w[1] + C1.w[0] = hi * 10^18 + lo, 0 <= lo < 10^18.
176 We use a table lookup method to obtain the hi and lo 18 digits.
177 [C1.w[1],C1.w[0]] = c_8 2^(107) + c_7 2^(101) + ... + c_0 2^(59) + d
178 where 0 <= d < 2^59 and each c_j has 6 bits. Because d fits in
179 18 digits, we set hi = 0, and lo = d to begin with.
180 We then retrieve from a table, for j = 0, 1, ..., 8
181 that gives us A and B where c_j 2^(59+6j) = A * 10^18 + B.
182 hi += A ; lo += B; After each accumulation into lo, we normalize
183 immediately. So at the end, we have the decomposition as we need. */
184
185 Tmp = C1.w[0] >> 59;
186 LO_18Dig = (C1.w[0] << 5) >> 5;
187 Tmp += (C1.w[1] << 5);
188 HI_18Dig = 0;
189 k_lcv = 0;
190 // Tmp = {C1.w[1]{49:0}, C1.w[0]{63:59}}
191 // Lo_18Dig = {C1.w[0]{58:0}}
192
193 while (Tmp) {
194 midi_ind = (int) (Tmp & 0x000000000000003FLL);
195 midi_ind <<= 1;
196 Tmp >>= 6;
197 HI_18Dig += __bid_mod10_18_tbl[k_lcv][midi_ind++];
198 LO_18Dig += __bid_mod10_18_tbl[k_lcv++][midi_ind];
199 __L0_Normalize_10to18 (HI_18Dig, LO_18Dig);
200 }
201 ptr = MiDi;
202 if (HI_18Dig == 0LL) {
203 __L1_Split_MiDi_6_Lead (LO_18Dig, ptr);
204 } else {
205 __L1_Split_MiDi_6_Lead (HI_18Dig, ptr);
206 __L1_Split_MiDi_6 (LO_18Dig, ptr);
207 }
208 len = ptr - MiDi;
209 c_ptr_start = &(str[k]);
210 c_ptr = c_ptr_start;
211
212 /* now convert the MiDi into character strings */
213 __L0_MiDi2Str_Lead (MiDi[0], c_ptr);
214 for (k_lcv = 1; k_lcv < len; k_lcv++) {
215 __L0_MiDi2Str (MiDi[k_lcv], c_ptr);
216 }
217 k = k + (c_ptr - c_ptr_start);
218 }
219
220 // print E and sign of exponent
221 str[k++] = 'E';
222 if (exp < 0) {
223 exp = -exp;
224 str[k++] = '-';
225 } else {
226 str[k++] = '+';
227 }
228
229 // determine exponent's representation as a decimal string
230 // d0 = exp / 1000;
231 // Use Property 1
232 d0 = (exp * 0x418a) >> 24;// 0x418a * 2^-24 = (10^(-3))RP,15
233 d123 = exp - 1000 * d0;
234
235 if (d0) { // 1000 <= exp <= 6144 => 4 digits to return
236 str[k++] = d0 + 0x30;// ASCII for decimal digit d0
237 ind = 3 * d123;
238 str[k++] = __bid_char_table3[ind];
239 str[k++] = __bid_char_table3[ind + 1];
240 str[k++] = __bid_char_table3[ind + 2];
241 } else { // 0 <= exp <= 999 => d0 = 0
242 if (d123 < 10) { // 0 <= exp <= 9 => 1 digit to return
243 str[k++] = d123 + 0x30;// ASCII
244 } else if (d123 < 100) { // 10 <= exp <= 99 => 2 digits to return
245 ind = 2 * (d123 - 10);
246 str[k++] = __bid_char_table2[ind];
247 str[k++] = __bid_char_table2[ind + 1];
248 } else { // 100 <= exp <= 999 => 3 digits to return
249 ind = 3 * d123;
250 str[k++] = __bid_char_table3[ind];
251 str[k++] = __bid_char_table3[ind + 1];
252 str[k++] = __bid_char_table3[ind + 2];
253 }
254 }
255 str[k] = '\0';
256
257 }
258 return;
259
260 }