xref: /original-bsd/lib/libcompat/4.3/ecvt.c (revision a1c2194a)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)ecvt.c	5.3 (Berkeley) 04/20/91";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #if defined(hp300) && !defined(IEEE)
13 #define	IEEE	1
14 #endif
15 
16 /*
17  *	ecvt converts to decimal
18  *	the number of digits is specified by ndigit
19  *	decpt is set to the position of the decimal point
20  *	sign is set to 0 for positive, 1 for negative
21  */
22 
23 char	*cvt();
24 
25 #ifdef IEEE
26 #include <signal.h>
27 #define	NDIG	512
28 #else
29 #define	NDIG	80
30 #endif
31 
32 char*
33 ecvt(arg, ndigits, decpt, sign)
34 double arg;
35 int ndigits, *decpt, *sign;
36 {
37 	return(cvt(arg, ndigits, decpt, sign, 1));
38 }
39 
40 char*
41 fcvt(arg, ndigits, decpt, sign)
42 double arg;
43 int ndigits, *decpt, *sign;
44 {
45 	return(cvt(arg, ndigits, decpt, sign, 0));
46 }
47 
48 static char*
49 cvt(arg, ndigits, decpt, sign, eflag)
50 double arg;
51 int ndigits, *decpt, *sign;
52 {
53 	register int r2;
54 	double fi, fj;
55 	register char *p, *p1;
56 	static char buf[NDIG];
57 	double modf();
58 
59 #ifdef IEEE
60 	/* XXX */
61 	if (isspecial(arg, buf))
62 		return(buf);
63 #endif
64 	if (ndigits<0)
65 		ndigits = 0;
66 	if (ndigits>=NDIG-1)
67 		ndigits = NDIG-2;
68 	r2 = 0;
69 	*sign = 0;
70 	p = &buf[0];
71 	if (arg<0) {
72 		*sign = 1;
73 		arg = -arg;
74 	}
75 	arg = modf(arg, &fi);
76 	p1 = &buf[NDIG];
77 	/*
78 	 * Do integer part
79 	 */
80 	if (fi != 0) {
81 		p1 = &buf[NDIG];
82 		while (fi != 0) {
83 			fj = modf(fi/10, &fi);
84 			*--p1 = (int)((fj+.03)*10) + '0';
85 			r2++;
86 		}
87 		while (p1 < &buf[NDIG])
88 			*p++ = *p1++;
89 	} else if (arg > 0) {
90 		while ((fj = arg*10) < 1) {
91 			arg = fj;
92 			r2--;
93 		}
94 	}
95 	p1 = &buf[ndigits];
96 	if (eflag==0)
97 		p1 += r2;
98 	*decpt = r2;
99 	if (p1 < &buf[0]) {
100 		buf[0] = '\0';
101 		return(buf);
102 	}
103 	while (p<=p1 && p<&buf[NDIG]) {
104 		arg *= 10;
105 		arg = modf(arg, &fj);
106 		*p++ = (int)fj + '0';
107 	}
108 	if (p1 >= &buf[NDIG]) {
109 		buf[NDIG-1] = '\0';
110 		return(buf);
111 	}
112 	p = p1;
113 	*p1 += 5;
114 	while (*p1 > '9') {
115 		*p1 = '0';
116 		if (p1>buf)
117 			++*--p1;
118 		else {
119 			*p1 = '1';
120 			(*decpt)++;
121 			if (eflag==0) {
122 				if (p>buf)
123 					*p = '0';
124 				p++;
125 			}
126 		}
127 	}
128 	*p = '\0';
129 	return(buf);
130 }
131 
132 #ifdef IEEE
133 struct IEEEdp {
134 	unsigned sign:1,
135 		 exp:11,
136 		 manh:20,
137 		 manl:32;
138 };
139 
140 isspecial(f, bp)
141 	double f;
142 	char *bp;
143 {
144 	register struct IEEEdp *ip = (struct IEEEdp *) &f;
145 
146 	if (ip->exp != 0x7ff)
147 		return(0);
148 	if (ip->manh || ip->manl)
149 		strcpy(bp, "NaN");
150 	else if (ip->sign)
151 		strcpy(bp, "-Infinity");
152 	else
153 		strcpy(bp, "Infinity");
154 	return(1);
155 }
156 #endif
157