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