4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 * ecvt converts to decimal
34 * the number of digits is specified by ndigit
35 * decpt is set to the position of the decimal point
36 * sign is set to 0 for positive, 1 for negative
40 #pragma weak _ecvt = ecvt
41 #pragma weak _fcvt = fcvt
44 #include <sys/types.h>
50 #define NMAX ((DSIGNIF * 3 + 19)/10) /* restrict max precision */
53 static char *cvt(double, int, int *, int *, int);
56 ecvt(double value
, int ndigit
, int *decpt
, int *sign
)
58 return (cvt(value
, ndigit
, decpt
, sign
, 0));
62 fcvt(double value
, int ndigit
, int *decpt
, int *sign
)
64 return (cvt(value
, ndigit
, decpt
, sign
, 1));
68 cvt(double value
, int ndigit
, int *decpt
, int *sign
, int f_flag
)
70 char *buf
= tsdalloc(_T_ECVT
, NDIG
, NULL
);
71 char *p
= &buf
[0], *p_last
= &buf
[ndigit
];
75 if (IsNANorINF(value
)) {
76 if (IsINF(value
)) /* value is an INF, return "inf" */
77 (void) strncpy(buf
, "inf", NDIG
);
78 else /* value is a NaN, return "NaN" */
79 (void) strncpy(buf
, "nan", NDIG
);
84 if ((*sign
= (value
< 0.0)) != 0)
89 * rescale to range [1.0, 10.0)
90 * in binary for speed and to minimize error build-up
91 * even for the IEEE standard with its high exponents,
92 * it's probably better for speed to just loop on them
94 static const struct s
{ double p10
; int n
; } s
[] = {
102 const struct s
*sp
= s
;
105 if (value
>= 2.0 * MAXPOWTWO
) /* can't be precisely integral */
107 for (; value
>= sp
->p10
; *decpt
+= sp
->n
)
109 } while (sp
++->n
> 1);
110 else if (value
>= 10.0) { /* convert integer part separately */
111 double pow10
= 10.0, powtemp
;
113 while ((powtemp
= 10.0 * pow10
) <= value
)
115 for (; ; pow10
/= 10.0) {
116 int digit
= value
/pow10
;
118 value
-= digit
* pow10
;
123 } else if (value
< 1.0)
125 for (; value
* sp
->p10
< 10.0; *decpt
-= sp
->n
)
127 } while (sp
++->n
> 1);
132 if (p_last
> &buf
[NDIG
- 2])
133 p_last
= &buf
[NDIG
- 2];
135 if (value
== 0 || p
>= &buf
[NMAX
])
138 int intx
; /* intx in [0, 9] */
139 *p
= (intx
= (int)value
) + '0';
140 value
= 10.0 * (value
- (double)intx
);
147 if (*p
>= '5') /* check rounding in last place + 1 */
149 if (p
== buf
) { /* rollover from 99999... */
150 buf
[0] = '1'; /* later digits are 0 */
157 } while (++*--p
> '9'); /* propagate carries left */