1 
2 #define DIGMAX	30		/* max # of digits in string */
3 #define DIGPREC	17		/* max # of significant digits */
4 #define ECVT	0
5 #define FCVT	1
6 static char digstr[DIGMAX + 1 + 1];    /* +1 for end of string         */
7 
8     /* +1 in case rounding adds     */
9     /* another digit                */
10 static double negtab[] =
11     { 1e-256, 1e-128, 1e-64, 1e-32, 1e-16, 1e-8, 1e-4, 1e-2, 1e-1, 1.0 };
12 static double postab[] =
13     { 1e+256, 1e+128, 1e+64, 1e+32, 1e+16, 1e+8, 1e+4, 1e+2, 1e+1 };
14 
15 static char *_cvt();
16 
17 /*************************
18  * Convert double val to a string of
19  * decimal digits.
20  *	ndig = # of digits in resulting string
21  * Returns:
22  *	*pdecpt = position of decimal point from left of first digit
23  *	*psign  = nonzero if value was negative
24  */
25 char *
ecvt(val,ndig,pdecpt,psign)26 ecvt(val, ndig, pdecpt, psign)
27 double val;
28 int   ndig, *pdecpt, *psign;
29 
30 {
31    return _cvt(ECVT, val, ndig, pdecpt, psign);
32 }
33 
34 char *
fcvt(val,nfrac,pdecpt,psign)35 fcvt(val, nfrac, pdecpt, psign)
36 double val;
37 int   nfrac, *pdecpt, *psign;
38 
39 {
40    return _cvt(FCVT, val, nfrac, pdecpt, psign);
41 }
42 
43 static char *
_cvt(cnvflag,val,ndig,pdecpt,psign)44 _cvt(cnvflag, val, ndig, pdecpt, psign)
45 double val;
46 int   ndig, *pdecpt, *psign;
47 
48 {
49    int   decpt, pow, i;
50    char *p;
51    *psign = (val < 0) ? ((val = -val), 1) : 0;
52    ndig = (ndig < 0) ? 0 : (ndig < DIGMAX) ? ndig : DIGMAX;
53    if (val == 0) {
54       for (p = &digstr[0]; p < &digstr[ndig]; p++)
55 	 *p = '0';
56       decpt = 0;
57    } else {
58       /* Adjust things so that 1 <= val < 10  */
59       /* in these loops if val == MAXDOUBLE)  */
60       decpt = 1;
61       pow = 256;
62       i = 0;
63       while (val < 1) {
64 	 while (val < negtab[i + 1]) {
65 	    val /= negtab[i];
66 	    decpt -= pow;
67 	 }
68 	 pow >>= 1;
69 	 i++;
70       }
71       pow = 256;
72       i = 0;
73       while (val >= 10) {
74 	 while (val >= postab[i]) {
75 	    val /= postab[i];
76 	    decpt += pow;
77 	 }
78 	 pow >>= 1;
79 	 i++;
80       }
81       if (cnvflag == FCVT) {
82 	 ndig += decpt;
83 	 ndig = (ndig < 0) ? 0 : (ndig < DIGMAX) ? ndig : DIGMAX;
84       }
85 
86       /* Pick off digits 1 by 1 and stuff into digstr[]       */
87       /* Do 1 extra digit for rounding purposes               */
88       for (p = &digstr[0]; p <= &digstr[ndig]; p++) {
89 	 int   n;
90 
91 	 /* 'twould be silly to have zillions of digits  */
92 	 /* when only DIGPREC are significant            */
93 	 if (p >= &digstr[DIGPREC])
94 	    *p = '0';
95 
96 	 else {
97 	    n = val;
98 	    *p = n + '0';
99 	    val = (val - n) * 10;	/* get next digit */
100 	 }
101       }
102       if (*--p >= '5') {	/* if we need to round              */
103 	 while (1) {
104 	    if (p == &digstr[0]) {	/* if at start      */
105 	       ndig += cnvflag;
106 	       decpt++;		/* shift dec pnt */
107 	       digstr[0] = '1';	/* "100000..." */
108 	       break;
109 	    }
110 	    *p = '0';
111 	    --p;
112 	    if (*p != '9') {
113 	       (*p)++;
114 	       break;
115 	    }
116 	 }			/* while */
117       }				/* if */
118    }				/* else */
119    *pdecpt = decpt;
120    digstr[ndig] = 0;		/* terminate string             */
121    return &digstr[0];
122 }
123