1 /* Internal function for converting integers to string using locale
3 Copyright (C) 2000 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <gmp-mparam.h>
23 #include <stdlib/gmp.h>
24 #include <stdlib/gmp-impl.h>
25 #include <stdlib/longlong.h>
27 #include "_i18n_itoa.h"
30 /* Canonize environment. For some architectures not all values might
31 be defined in the GMP header files. */
39 /* Control memory layout. */
42 # define PACK __attribute__ ((packed))
48 /* Declare local types. */
51 #if (UDIV_TIME > 2 * UMUL_TIME)
52 mp_limb_t base_multiplier
;
56 #if BITS_PER_MP_LIMB == 32
59 char normalization_steps
;
62 #if UDIV_TIME > 2 * UMUL_TIME
63 mp_limb_t base_ninv PACK
;
70 /* Variable in other file. */
71 extern const struct base_table_t _itoa_base_table
[];
75 _i18n_itoa (value
, buflim
)
76 unsigned long long int value
;
79 const struct base_table_t
*brec
= &_itoa_base_table
[8];
81 #if BITS_PER_MP_LIMB == 64
82 mp_limb_t base_multiplier
= brec
->base_multiplier
;
83 if (brec
->flag
) while (value
!= 0)
85 mp_limb_t quo
, rem
, x
, dummy
;
87 umul_ppmm (x
, dummy
, value
, base_multiplier
);
88 quo
= (x
+ ((value
- x
) >> 1)) >> (brec
->post_shift
- 1);
89 rem
= value
- quo
* 10;
90 buflim
= outdigit_value (buflim
, rem
);
96 mp_limb_t quo
, rem
, x
, dummy
;
98 umul_ppmm (x
, dummy
, value
, base_multiplier
);
99 quo
= x
>> brec
->post_shift
;
100 rem
= value
- quo
* 10;
101 buflim
= outdigit_value (buflim
, rem
);
105 #if BITS_PER_MP_LIMB == 32
109 /* First convert x0 to 1-3 words in base s->big.base.
110 Optimize for frequent cases of 32 bit numbers. */
111 if ((mp_limb_t
) (value
>> 32) >= 1)
113 #if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
114 int big_normalization_steps
= brec
->big
.normalization_steps
;
115 mp_limb_t big_base_norm
116 = brec
->big
.base
<< big_normalization_steps
;
118 if ((mp_limb_t
) (value
>> 32) >= brec
->big
.base
)
120 mp_limb_t x1hi
, x1lo
, r
;
121 /* If you want to optimize this, take advantage of
122 that the quotient in the first udiv_qrnnd will
123 always be very small. It might be faster just to
124 subtract in a tight loop. */
126 #if UDIV_TIME > 2 * UMUL_TIME
129 if (big_normalization_steps
== 0)
132 xh
= (mp_limb_t
) (value
>> (64 - big_normalization_steps
));
133 xl
= (mp_limb_t
) (value
>> (32 - big_normalization_steps
));
134 udiv_qrnnd_preinv (x1hi
, r
, xh
, xl
, big_base_norm
,
135 brec
->big
.base_ninv
);
137 xl
= ((mp_limb_t
) value
) << big_normalization_steps
;
138 udiv_qrnnd_preinv (x1lo
, x
, r
, xl
, big_base_norm
,
139 brec
->big
.base_ninv
);
140 t
[2] = x
>> big_normalization_steps
;
142 if (big_normalization_steps
== 0)
145 xh
= ((x1hi
<< big_normalization_steps
)
146 | (x1lo
>> (32 - big_normalization_steps
)));
147 xl
= x1lo
<< big_normalization_steps
;
148 udiv_qrnnd_preinv (t
[0], x
, xh
, xl
, big_base_norm
,
149 brec
->big
.base_ninv
);
150 t
[1] = x
>> big_normalization_steps
;
151 #elif UDIV_NEEDS_NORMALIZATION
154 if (big_normalization_steps
== 0)
157 xh
= (mp_limb_t
) (value
>> 64 - big_normalization_steps
);
158 xl
= (mp_limb_t
) (value
>> 32 - big_normalization_steps
);
159 udiv_qrnnd (x1hi
, r
, xh
, xl
, big_base_norm
);
161 xl
= ((mp_limb_t
) value
) << big_normalization_steps
;
162 udiv_qrnnd (x1lo
, x
, r
, xl
, big_base_norm
);
163 t
[2] = x
>> big_normalization_steps
;
165 if (big_normalization_steps
== 0)
168 xh
= ((x1hi
<< big_normalization_steps
)
169 | (x1lo
>> 32 - big_normalization_steps
));
170 xl
= x1lo
<< big_normalization_steps
;
171 udiv_qrnnd (t
[0], x
, xh
, xl
, big_base_norm
);
172 t
[1] = x
>> big_normalization_steps
;
174 udiv_qrnnd (x1hi
, r
, 0, (mp_limb_t
) (value
>> 32),
176 udiv_qrnnd (x1lo
, t
[2], r
, (mp_limb_t
) value
, brec
->big
.base
);
177 udiv_qrnnd (t
[0], t
[1], x1hi
, x1lo
, brec
->big
.base
);
183 #if (UDIV_TIME > 2 * UMUL_TIME)
186 value
<<= brec
->big
.normalization_steps
;
187 udiv_qrnnd_preinv (t
[0], x
, (mp_limb_t
) (value
>> 32),
188 (mp_limb_t
) value
, big_base_norm
,
189 brec
->big
.base_ninv
);
190 t
[1] = x
>> brec
->big
.normalization_steps
;
191 #elif UDIV_NEEDS_NORMALIZATION
194 value
<<= big_normalization_steps
;
195 udiv_qrnnd (t
[0], x
, (mp_limb_t
) (value
>> 32),
196 (mp_limb_t
) value
, big_base_norm
);
197 t
[1] = x
>> big_normalization_steps
;
199 udiv_qrnnd (t
[0], t
[1], (mp_limb_t
) (value
>> 32),
200 (mp_limb_t
) value
, brec
->big
.base
);
211 /* Convert the 1-3 words in t[], word by word, to ASCII. */
214 mp_limb_t ti
= t
[--n
];
215 int ndig_for_this_limb
= 0;
217 #if UDIV_TIME > 2 * UMUL_TIME
218 mp_limb_t base_multiplier
= brec
->base_multiplier
;
222 mp_limb_t quo
, rem
, x
, dummy
;
224 umul_ppmm (x
, dummy
, ti
, base_multiplier
);
225 quo
= (x
+ ((ti
- x
) >> 1)) >> (brec
->post_shift
- 1);
227 buflim
= outdigit_value (buflim
, rem
);
229 ++ndig_for_this_limb
;
233 mp_limb_t quo
, rem
, x
, dummy
;
235 umul_ppmm (x
, dummy
, ti
, base_multiplier
);
236 quo
= x
>> brec
->post_shift
;
238 buflim
= outdigit_value (buflim
, rem
);
240 ++ndig_for_this_limb
;
249 buflim
= outdigit_value (buflim
, rem
);
251 ++ndig_for_this_limb
;
254 /* If this wasn't the most significant word, pad with zeros. */
256 while (ndig_for_this_limb
< brec
->big
.ndigits
)
259 ++ndig_for_this_limb
;