#include <stdlib.h>
#include <math.h>
static int copystring(char* buf,int maxlen, const char* s) {
	int i;
	for (i=0; i<3&&i<maxlen; ++i)
		buf[i]=s[i];
	if (i<maxlen) { buf[i]=0; ++i; }
	return i;
}
int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec,unsigned int prec2) {
#if 1
	union {
		unsigned long long l;
		double d;
	} u = { .d=d };
	
	signed long e=((u.l>>52)&((1<<11)-1))-1023;
#else
	signed long e=(((((unsigned long*)&d)[1])>>20)&((1<<11)-1))-1023;
#endif
	
	signed long e10;
	
	unsigned int i;
	double backup=d;
	double tmp;
	char *oldbuf=buf;
	if ((i=isinf(d))) return copystring(buf,maxlen,i>0?"inf":"-inf");
	if (isnan(d)) return copystring(buf,maxlen,"nan");
	e10=1+(long)(e*0.30102999566398119802); 
	
	if (d==0.0) {
		prec2=prec2==0?1:prec2+2;
		prec2=prec2>maxlen?8:prec2;
		i=0;
		if (prec2 && (long long)u.l<0) { buf[0]='-'; ++i; }
		for (; i<prec2; ++i) buf[i]='0';
		buf[buf[0]=='0'?1:2]='.'; buf[i]=0;
		return i;
	}
	if (d < 0.0) { d=-d; *buf='-'; --maxlen; ++buf; }
	
	tmp = 0.5;
	for (i = 0; i < prec2; i++) { tmp *= 0.1; }
	d += tmp;
	if (d < 1.0) { *buf='0'; --maxlen; ++buf; }
	if (e10>0) {
		int first=1;	
		tmp = 10.0;
		i=e10;
		while (i>10) { tmp=tmp*1e10; i-=10; }
		while (i>1) { tmp=tmp*10; --i; }
		
		while (tmp>0.9) {
			char digit;
			double fraction=d/tmp;
			digit=(int)(fraction);		
			if (!first || digit) {
				first=0;
				*buf=digit+'0'; ++buf;
				if (!maxlen) {
					
					int len=__dtostr(backup/tmp,oldbuf,maxlen,prec,prec2);
					int initial=1;
					if (len==0) return 0;
					maxlen-=len; buf+=len;
					if (maxlen>0) {
						*buf='e';
						++buf;
					}
					--maxlen;
					for (len=1000; len>0; len/=10) {
						if (e10>=len || !initial) {
							if (maxlen>0) {
								*buf=(e10/len)+'0';
								++buf;
							}
							--maxlen;
							initial=0;
							e10=e10%len;
						}
					}
					if (maxlen>0) goto fini;
					return 0;
				}
				d-=digit*tmp;
				--maxlen;
			}
			tmp/=10.0;
		}
	}
	else
	{
		tmp = 0.1;
	}
	if (buf==oldbuf) {
		if (!maxlen) return 0; --maxlen;
		*buf='0'; ++buf;
	}
	if (prec2 || prec>(unsigned int)(buf-oldbuf)+1) {	
		if (!maxlen) return 0; --maxlen;
		*buf='.'; ++buf;
		prec-=buf-oldbuf-1;
		if (prec2) prec=prec2;
		if (prec>maxlen) return 0;
		while (prec>0) {
			char digit;
			double fraction=d/tmp;
			digit=(int)(fraction);		
			*buf=digit+'0'; ++buf;
			d-=digit*tmp;
			tmp/=10.0;
			--prec;
		}
	}
fini:
	*buf=0;
	return buf-oldbuf;
}