xref: /plan9-contrib/sys/src/ape/lib/ap/stdio/ftoa.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier #include <math.h>
23e12c5d1SDavid du Colombier #include <stdlib.h>
33e12c5d1SDavid du Colombier double pow10(int);
43e12c5d1SDavid du Colombier #define	NDIG	18
53e12c5d1SDavid du Colombier #define	NFTOA	(NDIG+4)
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier  * convert floating to ascii.  ftoa returns an integer e such that
83e12c5d1SDavid du Colombier  * f=g*10**e, with .1<=|g|<1 (e=0 when g==0) and puts an ascii
93e12c5d1SDavid du Colombier  * representation of g in the buffer pointed to by bp.  bp[0] will
103e12c5d1SDavid du Colombier  * be '+' or '-', and bp[1] to bp[NFTOA-2]
113e12c5d1SDavid du Colombier  * will be appropriate digits of g. bp[NFTOA-1] will be '\0'
123e12c5d1SDavid du Colombier  */
ftoa(double f,char * bp)133e12c5d1SDavid du Colombier int ftoa(double f, char *bp){
143e12c5d1SDavid du Colombier 	int e, e1, e2, i;
153e12c5d1SDavid du Colombier 	double digit, g, p;
163e12c5d1SDavid du Colombier 	if(f>=0) *bp++='+';
173e12c5d1SDavid du Colombier 	else{
183e12c5d1SDavid du Colombier 		f=-f;
193e12c5d1SDavid du Colombier 		*bp++='-';
203e12c5d1SDavid du Colombier 	}
213e12c5d1SDavid du Colombier 	/* find e such that f==0 or 1<=f*pow10(e)<10, and set f=f*pow10(e) */
223e12c5d1SDavid du Colombier 	if(f==0.) e=1;
233e12c5d1SDavid du Colombier 	else{
243e12c5d1SDavid du Colombier 		frexp(f, &e);
253e12c5d1SDavid du Colombier 		e=-e*30103/100000;
263e12c5d1SDavid du Colombier 		/* split in 2 pieces to guard against overflow in extreme cases */
273e12c5d1SDavid du Colombier 		e1=e/2;
283e12c5d1SDavid du Colombier 		e2=e-e1;
293e12c5d1SDavid du Colombier 		p=f*pow10(e2);
30*22df390cSDavid du Colombier 		while(p*pow10(e1)<1.) e1++;
313e12c5d1SDavid du Colombier 		while((g=p*pow10(e1))>=10.) --e1;
323e12c5d1SDavid du Colombier 		e=e1+e2;
333e12c5d1SDavid du Colombier 		f=g;
343e12c5d1SDavid du Colombier 	}
353e12c5d1SDavid du Colombier 	for(i=0;i!=NDIG;i++){
363e12c5d1SDavid du Colombier 		f=modf(f, &digit)*10.;
373e12c5d1SDavid du Colombier 		*bp++=digit+'0';
383e12c5d1SDavid du Colombier 	}
393e12c5d1SDavid du Colombier 	*bp='\0';
403e12c5d1SDavid du Colombier 	return 1-e;
413e12c5d1SDavid du Colombier }
42