Advertisement
Guest User

Untitled

a guest
Aug 29th, 2011
1,675
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.79 KB | None | 0 0
  1. /*
  2. Quick attempt at extraction of fmt_fp for http://stackoverflow.com/questions/7228438/convert-double-float-to-string/7231988
  3.  
  4. Based on http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/stdio/vfprintf.c;h=4c990e5e54fa730c755206a9c5a6b4c597e8b2a3;hb=HEAD
  5.  
  6. Contents of http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob_plain;f=COPYRIGHT;hb=HEAD follows:
  7.  
  8. musl as a whole is licensed under the GNU LGPL version 2.1 or later.
  9. See the file COPYING for the text of this license.
  10.  
  11. See below for the copyright status on all code included in musl:
  12.  
  13. The TRE regular expression implementation (src/regex/reg* and
  14. src/regex/tre*) is Copyright © 2001-2006 Ville Laurikari and licensed
  15. under the terms of the GNU LGPL version 2.1 or later. The included
  16. version was heavily modified in Spring 2006 by Rich Felker in the
  17. interests of size, simplicity, and namespace cleanliness.
  18.  
  19. Most of the math library code (src/math/*) is Copyright © 1993 Sun
  20. Microsystems, Inc. Some files are Copyright © 2003 Steven G. Kargl and
  21. labelled as such. All have been licensed under extremely permissive
  22. terms which are compatible with the GNU LGPL. See the comments in the
  23. individual files for details.
  24.  
  25. The implementation of DES for crypt (src/misc/crypt.c) is Copyright ©
  26. 1994 David Burren. It is licensed under a BSD license compatible with
  27. the GNU LGPL.
  28.  
  29. The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
  30. Valentin Ochs and is licensed under an MIT-style license compatible
  31. with the GNU LGPL.
  32.  
  33. The BSD PRNG implementation (src/prng/random.c) and XSI search API
  34. (src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
  35. licensed under following terms: "Permission to use, copy, modify,
  36. and/or distribute this code for any purpose with or without fee is
  37. hereby granted. There is no warranty."
  38.  
  39. The x86_64 port was written by Nicholas J. Kain. See individual files
  40. for their copyright status.
  41.  
  42. All files which have no copyright comments are original works
  43. Copyright © 2005-2011 Rich Felker, the main author of this library.
  44. The decision to exclude such comments is intentional, as it should be
  45. possible to carry around the complete source code on tiny storage
  46. media. All public header files (include/*) should be treated as Public
  47. Domain as they intentionally contain no content which can be covered
  48. by copyright. Some source modules may fall in this category as well.
  49. If you believe that a file is so trivial that it should be in the
  50. Public Domain, please contact me and, if I agree, I will explicitly
  51. release it from copyright.
  52.  
  53. The following files are trivial, in my opinion not copyrightable in
  54. the first place, and hereby explicitly released to the Public Domain:
  55.  
  56. All public headers: include/*
  57. Startup files: crt/*
  58. */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <stddef.h>
  63. #include <stdint.h>
  64. #include <stdarg.h>
  65. #include <ctype.h>
  66. #include <string.h>
  67. #define __USE_POSIX
  68. #define __USE_XOPEN
  69. #include <limits.h>
  70. #include <float.h>
  71. #include <math.h>
  72. #include <errno.h>
  73.  
  74. /* Some useful macros */
  75.  
  76. #define MAX(a,b) ((a)>(b) ? (a) : (b))
  77. #define MIN(a,b) ((a)<(b) ? (a) : (b))
  78. #define CONCAT2(x,y) x ## y
  79. #define CONCAT(x,y) CONCAT2(x,y)
  80.  
  81. /* Convenient bit representation for modifier flags, which all fall
  82.  * within 31 codepoints of the space character. */
  83.  
  84. #define ALT_FORM   (1U<<('#'-' '))
  85. #define ZERO_PAD   (1U<<('0'-' '))
  86. #define LEFT_ADJ   (1U<<('-'-' '))
  87. #define PAD_POS    (1U<<(' '-' '))
  88. #define MARK_POS   (1U<<('+'-' '))
  89. #define GROUPED    (1U<<('\''-' '))
  90.  
  91. #define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
  92.  
  93. #if UINT_MAX == ULONG_MAX
  94. #define LONG_IS_INT
  95. #endif
  96.  
  97. #if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX
  98. #define ODD_TYPES
  99. #endif
  100.  
  101. static void out(char **sp, const char *s, size_t l)
  102. {
  103.     //__fwritex((void *)s, l, f);
  104.     //fwrite(s, l, 1, f);
  105.     while (l--) {
  106.         **sp = *s;
  107.         (*sp)++;
  108.         s++;
  109.     }
  110. }
  111.  
  112. static void pad(char **sp, char c, int w, int l, int fl)
  113. {
  114.     char pad[256];
  115.     if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
  116.     l = w - l;
  117.     memset(pad, c, l>sizeof pad ? sizeof pad : l);
  118.     for (; l >= sizeof pad; l -= sizeof pad)
  119.         out(sp, pad, sizeof pad);
  120.     out(sp, pad, l);
  121. }
  122.  
  123. static char *fmt_u(uintmax_t x, char *s)
  124. {
  125.     unsigned long y;
  126.     for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
  127.     for (y=x;           y; y/=10) *--s = '0' + y%10;
  128.     return s;
  129. }
  130.  
  131. static int fmt_fp(char *outstr, long double y, int w, int p, int fl, int t)
  132. {
  133.     char* sp = outstr;
  134.     uint32_t big[(LDBL_MAX_EXP+LDBL_MANT_DIG)/9+1];
  135.     uint32_t *a, *d, *r, *z;
  136.     int e2=0, e, i, j, l;
  137.     char buf[9+LDBL_MANT_DIG/4], *s;
  138.     const char *prefix="-0X+0X 0X-0x+0x 0x";
  139.     int pl;
  140.     char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
  141.  
  142.     pl=1;
  143.     if (y<0 || 1/y<0) {
  144.         y=-y;
  145.     } else if (fl & MARK_POS) {
  146.         prefix+=3;
  147.     } else if (fl & PAD_POS) {
  148.         prefix+=6;
  149.     } else prefix++, pl=0;
  150.  
  151.     if (!isfinite(y)) {
  152.         char *s = (t&32)?"inf":"INF";
  153.         if (y!=y) s=(t&32)?"nan":"NAN", pl=0;
  154.         pad(&sp, ' ', w, 3+pl, fl&~ZERO_PAD);
  155.         out(&sp, prefix, pl);
  156.         out(&sp, s, 3);
  157.         pad(&sp, ' ', w, 3+pl, fl^LEFT_ADJ);
  158.         return MAX(w, 3+pl);
  159.     }
  160.  
  161.     y = frexpl(y, &e2) * 2;
  162.     if (y) e2--;
  163.  
  164.     if (p<0) p=6;
  165.  
  166.     if (y) y *= 0x1p28, e2-=28;
  167.  
  168.     if (e2<0) a=r=z=big;
  169.     else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
  170.  
  171.     do {
  172.         *z = y;
  173.         y = 1000000000*(y-*z++);
  174.     } while (y);
  175.  
  176.     while (e2>0) {
  177.         uint32_t carry=0;
  178.         int sh=MIN(29,e2);
  179.         for (d=z-1; d>=a; d--) {
  180.             uint64_t x = ((uint64_t)*d<<sh)+carry;
  181.             *d = x % 1000000000;
  182.             carry = x / 1000000000;
  183.         }
  184.         if (!z[-1] && z>a) z--;
  185.         if (carry) *--a = carry;
  186.         e2-=sh;
  187.     }
  188.     while (e2<0) {
  189.         uint32_t carry=0, *z2;
  190.         int sh=MIN(9,-e2);
  191.         for (d=a; d<z; d++) {
  192.             uint32_t rm = *d & (1<<sh)-1;
  193.             *d = (*d>>sh) + carry;
  194.             carry = (1000000000>>sh) * rm;
  195.         }
  196.         if (!*a) a++;
  197.         if (carry) *z++ = carry;
  198.         /* Avoid (slow!) computation past requested precision */
  199.         z2 = ((t|32)=='f' ? r : a) + 2 + p/9;
  200.         z = MIN(z, z2);
  201.         e2+=sh;
  202.     }
  203.  
  204.     if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
  205.     else e=0;
  206.  
  207.     /* Perform rounding: j is precision after the radix (possibly neg) */
  208.     j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
  209.     if (j < 9*(z-r-1)) {
  210.         uint32_t x;
  211.         /* We avoid C's broken division of negative numbers */
  212.         d = r + 1 + (j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP;
  213.         j += 9*LDBL_MAX_EXP;
  214.         j %= 9;
  215.         for (i=10, j++; j<9; i*=10, j++);
  216.         x = *d % i;
  217.         /* Are there any significant digits past j? */
  218.         if (x || d+1!=z) {
  219.             long double round = CONCAT(0x1p,LDBL_MANT_DIG);
  220.             long double small;
  221.             if (*d/i & 1) round += 2;
  222.             if (x<i/2) small=0x0.8p0;
  223.             else if (x==i/2 && d+1==z) small=0x1.0p0;
  224.             else small=0x1.8p0;
  225.             if (pl && *prefix=='-') round*=-1, small*=-1;
  226.             *d -= x;
  227.             /* Decide whether to round by probing round+small */
  228.             if (round+small != round) {
  229.                 *d = *d + i;
  230.                 while (*d > 999999999) {
  231.                     *d--=0;
  232.                     (*d)++;
  233.                 }
  234.                 if (d<a) a=d;
  235.                 for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
  236.             }
  237.         }
  238.         if (z>d+1) z=d+1;
  239.         for (; !z[-1] && z>a; z--);
  240.     }
  241.    
  242.     if ((t|32)=='g') {
  243.         if (!p) p++;
  244.         if (p>e && e>=-4) {
  245.             t--;
  246.             p-=e+1;
  247.         } else {
  248.             t-=2;
  249.             p--;
  250.         }
  251.         if (!(fl&ALT_FORM)) {
  252.             /* Count trailing zeros in last place */
  253.             if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
  254.             else j=9;
  255.             if ((t|32)=='f')
  256.                 p = MIN(p,MAX(0,9*(z-r-1)-j));
  257.             else
  258.                 p = MIN(p,MAX(0,9*(z-r-1)+e-j));
  259.         }
  260.     }
  261.     l = 1 + p + (p || (fl&ALT_FORM));
  262.     if ((t|32)=='f') {
  263.         if (e>0) l+=e;
  264.     } else {
  265.         estr=fmt_u(e<0 ? -e : e, ebuf);
  266.         while(ebuf-estr<2) *--estr='0';
  267.         *--estr = (e<0 ? '-' : '+');
  268.         *--estr = t;
  269.         l += ebuf-estr;
  270.     }
  271.  
  272.     pad(&sp, ' ', w, pl+l, fl);
  273.     out(&sp, prefix, pl);
  274.     pad(&sp, '0', w, pl+l, fl^ZERO_PAD);
  275.  
  276.     if ((t|32)=='f') {
  277.         if (a>r) a=r;
  278.         for (d=a; d<=r; d++) {
  279.             char *s = fmt_u(*d, buf+9);
  280.             if (d!=a) while (s>buf) *--s='0';
  281.             else if (s==buf+9) *--s='0';
  282.             out(&sp, s, buf+9-s);
  283.         }
  284.         if (p || (fl&ALT_FORM)) out(&sp, ".", 1);
  285.         for (; d<z && p>0; d++, p-=9) {
  286.             char *s = fmt_u(*d, buf+9);
  287.             while (s>buf) *--s='0';
  288.             out(&sp, s, MIN(9,p));
  289.         }
  290.         pad(&sp, '0', p+9, 9, 0);
  291.     } else {
  292.         if (z<=a) z=a+1;
  293.         for (d=a; d<z && p>=0; d++) {
  294.             char *s = fmt_u(*d, buf+9);
  295.             if (s==buf+9) *--s='0';
  296.             if (d!=a) while (s>buf) *--s='0';
  297.             else {
  298.                 out(&sp, s++, 1);
  299.                 if (p>0||(fl&ALT_FORM)) out(&sp, ".", 1);
  300.             }
  301.             out(&sp, s, MIN(buf+9-s, p));
  302.             p -= buf+9-s;
  303.         }
  304.         pad(&sp, '0', p+18, 18, 0);
  305.         out(&sp, estr, ebuf-estr);
  306.     }
  307.  
  308.     pad(&sp, ' ', w, pl+l, fl^LEFT_ADJ);
  309.     *sp = 0;
  310.  
  311.     return 1+MAX(w, pl+l);
  312. }
  313.  
  314. int main() {
  315.     double test[] = { 0x1.921f9f01b866ep+1, 0x1.9eb851eb851ecp-1, 0x1.0000000000000p+57 };
  316.     size_t i;
  317.     for (i = 0; i < sizeof(test)/sizeof(test[0]); i++) {
  318.         char buffer[256];
  319.         fmt_fp(buffer, test[i], 0, -1, 0, 'f');
  320.         printf("%s\n",buffer);
  321.     }
  322.     return 0;
  323. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement