g_fmt.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /****************************************************************
  2. *
  3. * The author of this software is David M. Gay.
  4. *
  5. * Copyright (c) 1991, 1996 by Lucent Technologies.
  6. *
  7. * Permission to use, copy, modify, and distribute this software for any
  8. * purpose without fee is hereby granted, provided that this entire notice
  9. * is included in all copies of any software which is or includes a copy
  10. * or modification of this software and in all copies of the supporting
  11. * documentation for such software.
  12. *
  13. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
  14. * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
  15. * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  16. * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  17. *
  18. ***************************************************************/
  19. /* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
  20. * it suffices to declare buf
  21. * char buf[32];
  22. */
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. extern char *dtoa(double, int, int, int *, int *, char **);
  27. extern int g_fmt(char *, double, int);
  28. extern void freedtoa(char*);
  29. #ifdef __cplusplus
  30. }
  31. #endif
  32. int
  33. fpconv_g_fmt(char *b, double x, int precision)
  34. {
  35. register int i, k;
  36. register char *s;
  37. int decpt, j, sign;
  38. char *b0, *s0, *se;
  39. b0 = b;
  40. #ifdef IGNORE_ZERO_SIGN
  41. if (!x) {
  42. *b++ = '0';
  43. *b = 0;
  44. goto done;
  45. }
  46. #endif
  47. s = s0 = dtoa(x, 2, precision, &decpt, &sign, &se);
  48. if (sign)
  49. *b++ = '-';
  50. if (decpt == 9999) /* Infinity or Nan */ {
  51. while((*b++ = *s++));
  52. /* "b" is used to calculate the return length. Decrement to exclude the
  53. * Null terminator from the length */
  54. b--;
  55. goto done0;
  56. }
  57. if (decpt <= -4 || decpt > precision) {
  58. *b++ = *s++;
  59. if (*s) {
  60. *b++ = '.';
  61. while((*b = *s++))
  62. b++;
  63. }
  64. *b++ = 'e';
  65. /* sprintf(b, "%+.2d", decpt - 1); */
  66. if (--decpt < 0) {
  67. *b++ = '-';
  68. decpt = -decpt;
  69. }
  70. else
  71. *b++ = '+';
  72. for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
  73. for(;;) {
  74. i = decpt / k;
  75. *b++ = i + '0';
  76. if (--j <= 0)
  77. break;
  78. decpt -= i*k;
  79. decpt *= 10;
  80. }
  81. *b = 0;
  82. }
  83. else if (decpt <= 0) {
  84. *b++ = '0';
  85. *b++ = '.';
  86. for(; decpt < 0; decpt++)
  87. *b++ = '0';
  88. while((*b++ = *s++));
  89. b--;
  90. }
  91. else {
  92. while((*b = *s++)) {
  93. b++;
  94. if (--decpt == 0 && *s)
  95. *b++ = '.';
  96. }
  97. for(; decpt > 0; decpt--)
  98. *b++ = '0';
  99. *b = 0;
  100. }
  101. done0:
  102. freedtoa(s0);
  103. #ifdef IGNORE_ZERO_SIGN
  104. done:
  105. #endif
  106. return b - b0;
  107. }