1 /* Copyright (C) 2007 Free Software Foundation, Inc.
3 This file is part of GCC.
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
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
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
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
29 /*****************************************************************************
31 ****************************************************************************/
34 #include "bid_internal.h"
35 #include "bid128_2_str.h"
36 #include "bid128_2_str_macros.h"
38 extern int __bid128_coeff_2_string (UINT64 X_hi
, UINT64 X_lo
,
41 #if DECIMAL_CALL_BY_REFERENCE
44 __bid128_to_string (char *str
,
46 px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
52 __bid128_to_string (char *str
,
53 UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
54 _EXC_MASKS_PARAM _EXC_INFO_PARAM
) {
58 int exp
; // unbiased exponent
59 // Note: C1.w[1], C1.w[0] represent x_signif_hi, x_signif_lo (all are UINT64)
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
;
69 #if DECIMAL_CALL_BY_REFERENCE
70 #if !DECIMAL_GLOBAL_ROUNDING
71 _IDEC_round rnd_mode
= *prnd_mode
;
76 // check for NaN or Infinity
77 if ((x
.w
[1] & MASK_SPECIAL
) == MASK_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
82 *pfpsf
|= INVALID_EXCEPTION
;
95 } else { // x is not a NaN, so it must be infinity
96 if ((x
.w
[1] & MASK_SIGN
) == 0x0ull
) { // x is +inf
102 } else { // x is -inf
111 } else if (((x
.w
[1] & MASK_COEFF
) == 0x0ull
) && (x
.w
[0] == 0x0ull
)) {
116 if (x
.w
[1] & MASK_SIGN
)
123 // extract the exponent and print
124 exp
= (int) (((x
.w
[1] & MASK_EXP
) >> 49) - 6176);
127 len
+= sprintf (str
+ len
, "%u", exp
);// should not use sprintf (should
128 // use sophisticated algorithm, since we know range of exp is limited)
131 len
+= sprintf (str
+ len
, "%d", exp
);// should not use sprintf (should
132 // use sophisticated algorithm, since we know range of exp is limited)
136 } else { // x is not special and is not zero
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
;
142 exp
= (x_exp
>> 49) - 6176;
144 // determine sign's representation as a char
146 str
[k
++] = '-';// negative number
148 str
[k
++] = '+';// positive number
150 // determine coefficient's representation as a decimal string
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))) {
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. */
186 LO_18Dig
= (C1
.w
[0] << 5) >> 5;
187 Tmp
+= (C1
.w
[1] << 5);
190 // Tmp = {C1.w[1]{49:0}, C1.w[0]{63:59}}
191 // Lo_18Dig = {C1.w[0]{58:0}}
194 midi_ind
= (int) (Tmp
& 0x000000000000003FLL
);
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
);
202 if (HI_18Dig
== 0LL) {
203 __L1_Split_MiDi_6_Lead (LO_18Dig
, ptr
);
205 __L1_Split_MiDi_6_Lead (HI_18Dig
, ptr
);
206 __L1_Split_MiDi_6 (LO_18Dig
, ptr
);
209 c_ptr_start
= &(str
[k
]);
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
);
217 k
= k
+ (c_ptr
- c_ptr_start
);
220 // print E and sign of exponent
229 // determine exponent's representation as a decimal string
232 d0
= (exp
* 0x418a) >> 24;// 0x418a * 2^-24 = (10^(-3))RP,15
233 d123
= exp
- 1000 * d0
;
235 if (d0
) { // 1000 <= exp <= 6144 => 4 digits to return
236 str
[k
++] = d0
+ 0x30;// ASCII for decimal digit d0
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
250 str
[k
++] = __bid_char_table3
[ind
];
251 str
[k
++] = __bid_char_table3
[ind
+ 1];
252 str
[k
++] = __bid_char_table3
[ind
+ 2];