]> git.saurik.com Git - apple/libc.git/blob - i386/gen/ecvt.c
Libc-320.tar.gz
[apple/libc.git] / i386 / gen / ecvt.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * ecvt converts to decimal
27 * the number of digits is specified by ndigit
28 * decptp is set to the position of the decimal point
29 * signp is set to 0 for positive, 1 for negative
30 */
31
32
33 static double ecvt_rint(double x);
34 static double ecvt_copysign(double x, double y);
35
36 static char *cvt();
37
38 /* big enough to handle %.20f conversion of 1e308 */
39 #define NDIG 350
40
41 char*
42 ecvt(arg, ndigits, decptp, signp)
43 double arg;
44 int ndigits, *decptp, *signp;
45 {
46 return(cvt(arg, ndigits, decptp, signp, 1));
47 }
48
49 char*
50 fcvt(arg, ndigits, decptp, signp)
51 double arg;
52 int ndigits, *decptp, *signp;
53 {
54 return(cvt(arg, ndigits, decptp, signp, 0));
55 }
56
57 static char*
58 cvt(arg, ndigits, decptp, signp, eflag)
59 double arg;
60 int ndigits, *decptp, *signp;
61 int eflag;
62 {
63 register int decpt;
64 double fi, fj;
65 register char *p, *p1;
66 static char buf[NDIG] = { 0 };
67 double modf();
68
69 if (ndigits < 0)
70 ndigits = 0;
71 if (ndigits >= NDIG-1)
72 ndigits = NDIG-2;
73
74 decpt = 0;
75 *signp = 0;
76 p = &buf[0];
77
78 if (arg == 0) {
79 *decptp = 0;
80 while (p < &buf[ndigits])
81 *p++ = '0';
82 *p = '\0';
83 return(buf);
84 } else if (arg < 0) {
85 *signp = 1;
86 arg = -arg;
87 }
88
89 arg = modf(arg, &fi);
90 p1 = &buf[NDIG];
91
92 /*
93 * Do integer part
94 */
95 if (fi != 0) {
96 while (fi != 0) {
97 fj = modf(fi/10, &fi);
98 /**--p1 = (int)((fj+.03)*10) + '0';*/
99 *--p1 = (int)ecvt_rint((fj)*10) + '0';
100 decpt++;
101 }
102 while (p1 < &buf[NDIG])
103 *p++ = *p1++;
104 } else if (arg > 0) {
105 while ((fj = arg*10) < 1) {
106 arg = fj;
107 decpt--;
108 }
109 }
110 *decptp = decpt;
111
112 /*
113 * do fraction part
114 * p pts to where fraction should be concatenated
115 * p1 is how far conversion must go to
116 */
117 p1 = &buf[ndigits];
118 if (eflag==0) {
119 /* fcvt must provide ndigits after decimal pt */
120 p1 += decpt;
121 /* if decpt was negative, we might done for fcvt */
122 if (p1 < &buf[0]) {
123 buf[0] = '\0';
124 return(buf);
125 }
126 }
127 while (p <= p1 && p < &buf[NDIG]) {
128 arg *= 10;
129 arg = modf(arg, &fj);
130 *p++ = (int)fj + '0';
131 }
132 /*
133 * if we converted all the way to the end of the
134 * buf, don't mess with rounding since there's nothing
135 * significant out here anyway
136 */
137 if (p1 >= &buf[NDIG]) {
138 buf[NDIG-1] = '\0';
139 return(buf);
140 }
141 /*
142 * round by adding 5 to last digit and propagating
143 * carries
144 */
145 p = p1;
146 *p1 += 5;
147 while (*p1 > '9') {
148 *p1 = '0';
149 if (p1 > buf)
150 ++*--p1;
151 else {
152 *p1 = '1';
153 (*decptp)++;
154 if (eflag == 0) {
155 if (p > buf)
156 *p = '0';
157 p++;
158 }
159 }
160 }
161 *p = '\0';
162 return(buf);
163 }
164
165 static double ecvt_rint(double x)
166 {
167 asm("frndint" : "=t" (x) : "0" (x));
168 return(x);
169 }