fltpr.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * fltpr.c - print floating point numbers
  3. */
  4. /* $Id$ */
  5. #ifndef NOFLOAT
  6. #include <string.h>
  7. #include <stdarg.h>
  8. #include "loc_incl.h"
  9. static char *
  10. _pfloat(long double r, register char *s, int n, int flags)
  11. {
  12. register char *s1;
  13. int sign, dp;
  14. register int i;
  15. s1 = _fcvt(r, n, &dp, &sign);
  16. if (sign)
  17. *s++ = '-';
  18. else if (flags & FL_SIGN)
  19. *s++ = '+';
  20. else if (flags & FL_SPACE)
  21. *s++ = ' ';
  22. if (dp<=0)
  23. *s++ = '0';
  24. for (i=dp; i>0; i--)
  25. if (*s1) *s++ = *s1++;
  26. else *s++ = '0';
  27. if (((i=n) > 0) || (flags & FL_ALT))
  28. *s++ = '.';
  29. while (++dp <= 0) {
  30. if (--i<0)
  31. break;
  32. *s++ = '0';
  33. }
  34. while (--i >= 0)
  35. if (*s1) *s++ = *s1++;
  36. else *s++ = '0';
  37. return s;
  38. }
  39. static char *
  40. _pscien(long double r, register char *s, int n, int flags)
  41. {
  42. int sign, dp;
  43. register char *s1;
  44. s1 = _ecvt(r, n + 1, &dp, &sign);
  45. if (sign)
  46. *s++ = '-';
  47. else if (flags & FL_SIGN)
  48. *s++ = '+';
  49. else if (flags & FL_SPACE)
  50. *s++ = ' ';
  51. *s++ = *s1++;
  52. if ((n > 0) || (flags & FL_ALT))
  53. *s++ = '.';
  54. while (--n >= 0)
  55. if (*s1) *s++ = *s1++;
  56. else *s++ = '0';
  57. *s++ = 'e';
  58. if ( r != 0 ) --dp ;
  59. if ( dp<0 ) {
  60. *s++ = '-' ; dp= -dp ;
  61. } else {
  62. *s++ = '+' ;
  63. }
  64. if (dp >= 100) {
  65. *s++ = '0' + (dp / 100);
  66. dp %= 100;
  67. }
  68. *s++ = '0' + (dp/10);
  69. *s++ = '0' + (dp%10);
  70. return s;
  71. }
  72. #define NDIGINEXP(exp) (((exp) >= 100 || (exp) <= -100) ? 3 : 2)
  73. #define LOW_EXP -4
  74. #define USE_EXP(exp, ndigits) (((exp) < LOW_EXP + 1) || (exp >= ndigits + 1))
  75. static char *
  76. _gcvt(long double value, int ndigit, char *s, int flags)
  77. {
  78. int sign, dp;
  79. register char *s1, *s2;
  80. register int i;
  81. register int nndigit = ndigit;
  82. s1 = _ecvt(value, ndigit, &dp, &sign);
  83. s2 = s;
  84. if (sign) *s2++ = '-';
  85. else if (flags & FL_SIGN)
  86. *s2++ = '+';
  87. else if (flags & FL_SPACE)
  88. *s2++ = ' ';
  89. if (!(flags & FL_ALT))
  90. for (i = nndigit - 1; i > 0 && s1[i] == '0'; i--)
  91. nndigit--;
  92. if (USE_EXP(dp,ndigit)) {
  93. /* Use E format */
  94. dp--;
  95. *s2++ = *s1++;
  96. if ((nndigit > 1) || (flags & FL_ALT)) *s2++ = '.';
  97. while (--nndigit > 0) *s2++ = *s1++;
  98. *s2++ = 'e';
  99. if (dp < 0) {
  100. *s2++ = '-';
  101. dp = -dp;
  102. }
  103. else *s2++ = '+';
  104. s2 += NDIGINEXP(dp);
  105. *s2 = 0;
  106. for (i = NDIGINEXP(dp); i > 0; i--) {
  107. *--s2 = dp % 10 + '0';
  108. dp /= 10;
  109. }
  110. return s;
  111. }
  112. /* Use f format */
  113. if (dp <= 0) {
  114. if (*s1 != '0') {
  115. /* otherwise the whole number is 0 */
  116. *s2++ = '0';
  117. *s2++ = '.';
  118. }
  119. while (dp < 0) {
  120. dp++;
  121. *s2++ = '0';
  122. }
  123. }
  124. for (i = 1; i <= nndigit; i++) {
  125. *s2++ = *s1++;
  126. if (i == dp) *s2++ = '.';
  127. }
  128. if (i <= dp) {
  129. while (i++ <= dp) *s2++ = '0';
  130. *s2++ = '.';
  131. }
  132. if ((s2[-1]=='.') && !(flags & FL_ALT)) s2--;
  133. *s2 = '\0';
  134. return s;
  135. }
  136. char *
  137. _f_print(va_list *ap, int flags, char *s, char c, int precision)
  138. {
  139. register char *old_s = s;
  140. long double ld_val;
  141. if (flags & FL_LONGDOUBLE) ld_val = va_arg(*ap, long double);
  142. else ld_val = (long double) va_arg(*ap, double);
  143. switch(c) {
  144. case 'f':
  145. s = _pfloat(ld_val, s, precision, flags);
  146. break;
  147. case 'e':
  148. case 'E':
  149. s = _pscien(ld_val, s, precision , flags);
  150. break;
  151. case 'g':
  152. case 'G':
  153. s = _gcvt(ld_val, precision, s, flags);
  154. s += strlen(s);
  155. break;
  156. }
  157. if ( c == 'E' || c == 'G') {
  158. while (*old_s && *old_s != 'e') old_s++;
  159. if (*old_s == 'e') *old_s = 'E';
  160. }
  161. return s;
  162. }
  163. #endif /* NOFLOAT */