xref: /titanic_50/usr/src/lib/libbc/libc/gen/common/gconvert.c (revision 9acbbeaf2a1ffe5c14b244867d427714fab43c5c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 #pragma ident	"%Z%%M%	%I%	%E% SMI"
23 
24 /*
25  * Copyright (c) 1988 by Sun Microsystems, Inc.
26  */
27 
28 /*
29  * gcvt  - Floating output conversion to minimal length string
30  */
31 
32 #include "base_conversion.h"
33 #ifndef PRE41
34 #include <locale.h>
35 #endif
36 
37 void
38 _gcvt(ndigit, pd, trailing, buf)
39 	int             ndigit;
40 	decimal_record *pd;
41 	char           *buf;
42 {
43 	char           *p, *pstring;
44 	int             i;
45 	static char     *inf8 = "Infinity";
46 	static char     *inf3 = "Inf";
47 	static char     *nan = "NaN";
48 #ifdef PRE41
49 	char decpt = '.';
50 #else
51 	char decpt = *(localeconv()->decimal_point);
52 #endif
53 
54 	p = buf;
55 	if (pd->sign)
56 		*(p++) = '-';
57 	switch (pd->fpclass) {
58 	case fp_zero:
59 		*(p++) = '0';
60 		if (trailing != 0) {
61 			*(p++) = decpt;
62 			for (i = 0; i < ndigit - 1; i++)
63 				*(p++) = '0';
64 		}
65 		break;
66 	case fp_infinity:
67 		if (ndigit < 8)
68 			pstring = inf3;
69 		else
70 			pstring = inf8;
71 		goto copystring;
72 	case fp_quiet:
73 	case fp_signaling:
74 		pstring = nan;
75 copystring:
76 		for (i = 0; *pstring != 0;)
77 			*(p++) = *(pstring++);
78 		break;
79 	default:
80 		if ((pd->exponent > 0) || (pd->exponent < -(ndigit + 3))) {	/* E format. */
81 			char            estring[4];
82 			int             n;
83 
84 			i = 0;
85 			*(p++) = pd->ds[0];
86 			*(p++) = decpt;
87 			for (i = 1; pd->ds[i] != 0;)
88 				*(p++) = pd->ds[i++];
89 			if (trailing == 0) {	/* Remove trailing zeros and . */
90 				p--;
91 				while (*p == '0')
92 					p--;
93 				if (*p != decpt)
94 					p++;
95 			}
96 			*(p++) = 'e';
97 			n = pd->exponent + i - 1;
98 			if (n >= 0)
99 				*(p++) = '+';
100 			else {
101 				*(p++) = '-';
102 				n = -n;
103 			}
104 			_fourdigitsquick((short unsigned) n, estring);
105 			for (i = 0; estring[i] == '0'; i++);	/* Find end of zeros. */
106 			if (i > 2)
107 				i = 2;	/* Guarantee two zeros. */
108 			for (; i <= 3;)
109 				*(p++) = estring[i++];	/* Copy exp digits. */
110 		} else {	/* F format. */
111 			if (pd->exponent >= (1 - ndigit)) {	/* x.xxx */
112 				for (i = 0; i < (ndigit + pd->exponent);)
113 					*(p++) = pd->ds[i++];
114 				*(p++) = decpt;
115 				if (pd->ds[i] != 0) {	/* More follows point. */
116 					for (; i < ndigit;)
117 						*(p++) = pd->ds[i++];
118 				}
119 			} else {/* 0.00xxxx */
120 				*(p++) = '0';
121 				*(p++) = decpt;
122 				for (i = 0; i < -(pd->exponent + ndigit); i++)
123 					*(p++) = '0';
124 				for (i = 0; pd->ds[i] != 0;)
125 					*(p++) = pd->ds[i++];
126 			}
127 			if (trailing == 0) {	/* Remove trailing zeros and point. */
128 				p--;
129 				while (*p == '0')
130 					p--;
131 				if (*p != decpt)
132 					p++;
133 			}
134 		}
135 	}
136 	*(p++) = 0;
137 }
138 
139 char           *
140 gconvert(number, ndigit, trailing, buf)
141 	double          number;
142 	int             ndigit, trailing;
143 	char           *buf;
144 {
145 	decimal_mode    dm;
146 	decimal_record  dr;
147 	fp_exception_field_type fef;
148 
149 	dm.rd = fp_direction;
150 	dm.df = floating_form;
151 	dm.ndigits = ndigit;
152 	double_to_decimal(&number, &dm, &dr, &fef);
153 	_gcvt(ndigit, &dr, trailing, buf);
154 	return (buf);
155 }
156 
157 char           *
158 gcvt(number, ndigit, buf)
159 	double          number;
160 	int             ndigit;
161 	char           *buf;
162 {
163 	return (gconvert(number, ndigit, 0, buf));
164 }
165