On Tue, Jun 14, 2011 at 8:21 AM, Jakub Jelinek <ja...@redhat.com> wrote: > On Tue, Jun 14, 2011 at 05:59:47PM +0300, Dimitrios Apostolou wrote: >> >>static void puthexl (unsigned long value, FILE *f) >> >>{ >> >> static char hex_repr[16]= {'0', '1', '2', '3', '4', '5', '6', '7', >> >> '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; >> >> static char buf[2 + 2*sizeof(value)]= "0x"; >> >> int i; >> >> int j= 2; >> >> >> >> for (i = 8*sizeof(value)-4; i>=0; i-= 4) >> >> { >> >> char c= (value >> i) & 0xf; >> >> if (c!=0 || j>2) >> >> { >> >> buf[j]= hex_repr[(int)c]; >> > >> >Why not just "0123456789abcdef"[c] instead >> >> Code just looked more beautiful, that's all. :-) > > Well, I find that two lines hex_repr initializer much less readable. > > Anyway, what glibc does is: > static inline char * __attribute__ ((unused, always_inline)) > _itoa_word (unsigned long value, char *buflim, > unsigned int base, int upper_case) > { > const char *digits = (upper_case ? _itoa_upper_digits : _itoa_lower_digits); > > switch (base) > { > # define SPECIAL(Base) \ > case Base: \ > do \ > *--buflim = digits[value % Base]; \ > while ((value /= Base) != 0); \ > break > > SPECIAL (10); > SPECIAL (16); > SPECIAL (8); > default: > do > *--buflim = digits[value % base]; > while ((value /= base) != 0); > } > return buflim; > } > and as it is called with constant base and constant upper_case, the > switch/modulo/division is optimized. > > You'd use it as: > void > puthexl (unsigned long value, FILE *f) > { > char buf[2 + CHAR_BIT * sizeof (value) / 4]; > if (value == 0) > putc ('0', f); > else > { > char *p = buf + sizeof (buf); > do > *--p = "0123456789abcdef"[value % 16]; > while ((value /= 16) != 0); > *--p = 'x'; > *--p = '0'; > fwrite (p, 1, buf + sizeof (buf) - p, f); > } > } > > If the number is small, which is the common case, > this will iterate just small number of items > instead of always 16 times. > > Anyway, generally, I wonder if replacing lots of > fprintf calls won't lead to less readable and maintainable > code, if many of the fprintfs will need to be replaced > e.g. by two separate calls (one fwrite, one puthexl > or similar). > > Plus, what I said on IRC, regarding transformation > of fprintf calls to fwrite if there are no %s in > the format string, we should leave that to the host > compiler. It actually already does such transformations > for fprintf, but in this case we have fprintf_unlocked > due to system.h macros, and that isn't optimized by gcc > into fwrite_unlocked. That IMHO should be fixed on the > host gcc side though. >
We are working on a patch which will improve decimal itoa by up to 10X. It will take a while to finish it. -- H.J.