]>
git.saurik.com Git - apple/libc.git/blob - ppc/gen/ecvt.c
4e1ec5187c7bde4ee4132273fe52ddfcd66992d0
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
25 * File: libc/m98k/gen/ecvt.c
27 * char *ecvt(double x, int ndigits, int *decimal, int *sign);
28 * char *fcvt(double x, int ndigits, int *decimal, int *sign);
30 * The function `ecvt' converts the double `x' to a null-terminated
31 * string of `ndigits' ASCII digits and returns a pointer to the string.
32 * The position of the decimal point relative to the beginning of the
33 * string is stored in the int pointed to by `decimal'. A negative
34 * value means that the decimal point appears to the left of the returned
35 * digits. If the sign of the result is negative, a non-zero value is
36 * stored in the int pointed to by `sign'; otherwise, a zero value is stored.
37 * The low-order digit of the returned value is rounded.
39 * The function `fcvt' is identical to `ecvt', except that the correct digit
40 * has been rounded for Fortran F-format output of the number of digits
41 * specified by `ndigits'.
44 * 10-Nov-92 Derek B Clegg (dclegg@next.com)
46 * 8-Jan-92 Peter King (king@next.com)
47 * Created from M68K sources which was created from VAX sources.
51 static double ecvt_rint(double x
);
52 static double ecvt_copysign(double x
, double y
);
53 static char *cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
);
55 #define isNAN(x) ((x) != (x))
57 /* big enough to handle %.20f conversion of 1e308 */
61 ecvt(double arg
, int ndigits
, int *decptp
, int *signp
)
63 return (cvt(arg
, ndigits
, decptp
, signp
, 1));
67 fcvt(double arg
, int ndigits
, int *decptp
, int *signp
)
69 return (cvt(arg
, ndigits
, decptp
, signp
, 0));
73 cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
)
78 static char buf
[NDIG
] = { 0 };
82 if (ndigits
>= NDIG
- 1)
91 while (p
< &buf
[ndigits
])
100 arg
= modf(arg
, &fi
);
103 /* Do integer part */
107 fj
= modf(fi
/10, &fi
);
109 *--p1
= (int)((fj
+ 0.03) * 10) + '0';
111 *--p1
= (int)ecvt_rint(fj
* 10) + '0';
115 while (p1
< &buf
[NDIG
])
117 } else if (arg
> 0) {
118 while ((fj
= arg
*10) < 1) {
125 /* Do the fractional part.
126 * p pts to where fraction should be concatenated.
127 * p1 is how far conversion must go to.
131 /* fcvt must provide ndigits after decimal pt */
133 /* if decpt was negative, we might be done for fcvt */
140 while (p
<= p1
&& p
< &buf
[NDIG
]) {
142 arg
= modf(arg
, &fj
);
143 *p
++ = (int)fj
+ '0';
146 /* If we converted all the way to the end of the buf, don't mess with
147 * rounding since there's nothing significant out here anyway.
149 if (p1
>= &buf
[NDIG
]) {
154 /* Round by adding 5 to last digit and propagating carries. */
175 static double L
= 4503599627370496.0E0
; /* 2**52 */
177 static int ecvt_init
= 0;
180 * FIXME: This deserves a comment if you turn this off!
181 * This used to #pragma CC_OPT_OFF.
182 * (Probably this was because the isNAN test was optimized away.)
183 * Why don't we just use the value of L given above?
193 if (ecvt_init
== 0) {
196 for (i
= 52; i
!= 0; i
--)
202 if (ecvt_copysign(x
, one
) >= L
) /* already an integer */
204 s
= ecvt_copysign(L
, x
);
205 t
= x
+ s
; /* x+s rounded to integer */
209 /* Couldn't we use something like the following structure instead of the
210 hacky unsigned short pointer stuff?
212 struct double_format {
214 unsigned exponent:11;
215 unsigned hi_fraction:20;
216 unsigned lo_fraction:32;
221 #define msign ((unsigned short)0x7fff)
222 #define mexp ((unsigned short)0x7ff0)
225 ecvt_copysign(double x
, double y
)
227 unsigned short *px
, *py
;
229 px
= (unsigned short *)&x
;
230 py
= (unsigned short *)&y
;
231 *px
= (*px
& msign
) | (*py
& ~msign
);
236 * This used to #pragma CC_OPT_ON