xref: /inferno-os/libmath/g_fmt.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 /****************************************************************
2  *
3  * The author of this software is David M. Gay.
4  *
5  * Copyright (c) 1991, 1996 by Lucent Technologies.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose without fee is hereby granted, provided that this entire notice
9  * is included in all copies of any software which is or includes a copy
10  * or modification of this software and in all copies of the supporting
11  * documentation for such software.
12  *
13  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
14  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
15  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
16  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
17  *
18  ***************************************************************/
19 
20 /* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
21  * it suffices to declare buf
22  *	char buf[32];
23  */
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28  extern char *dtoa(double, int, int, int *, int *, char **);
29  extern char *g_fmt(char *, double, int);
30  extern void freedtoa(char*);
31 #ifdef __cplusplus
32 	}
33 #endif
34 
35  char *
36 g_fmt(register char *b, double x, int echr)
37 {
38 	register int i, k;
39 	register char *s;
40 	int decpt, j, sign;
41 	char *b0, *s0, *se;
42 
43 	b0 = b;
44 #ifdef IGNORE_ZERO_SIGN
45 	if (!x) {
46 		*b++ = '0';
47 		*b = 0;
48 		goto done;
49 		}
50 #endif
51 	s = s0 = dtoa(x, 0, 0, &decpt, &sign, &se);
52 	if (sign)
53 		*b++ = '-';
54 	if (decpt == 9999) /* Infinity or Nan */ {
55 		while(*b++ = *s++);
56 		goto done0;
57 		}
58 	if (decpt <= -4 || decpt > se - s + 5) {
59 		*b++ = *s++;
60 		if (*s) {
61 			*b++ = '.';
62 			while(*b = *s++)
63 				b++;
64 			}
65 		*b++ = echr;
66 		/* sprintf(b, "%+.2d", decpt - 1); */
67 		if (--decpt < 0) {
68 			*b++ = '-';
69 			decpt = -decpt;
70 			}
71 		else
72 			*b++ = '+';
73 		for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
74 		for(;;) {
75 			i = decpt / k;
76 			*b++ = i + '0';
77 			if (--j <= 0)
78 				break;
79 			decpt -= i*k;
80 			decpt *= 10;
81 			}
82 		*b = 0;
83 		}
84 	else if (decpt <= 0) {
85 		*b++ = '.';
86 		for(; decpt < 0; decpt++)
87 			*b++ = '0';
88 		while(*b++ = *s++);
89 		}
90 	else {
91 		while(*b = *s++) {
92 			b++;
93 			if (--decpt == 0 && *s)
94 				*b++ = '.';
95 			}
96 		for(; decpt > 0; decpt--)
97 			*b++ = '0';
98 		*b = 0;
99 		}
100  done0:
101 	freedtoa(s0);
102 #ifdef IGNORE_ZERO_SIGN
103  done:
104 #endif
105 	return b0;
106 	}
107