]>
git.saurik.com Git - apple/libc.git/blob - ppc/gen/ecvt.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
27 * File: libc/m98k/gen/ecvt.c
29 * char *ecvt(double x, int ndigits, int *decimal, int *sign);
30 * char *fcvt(double x, int ndigits, int *decimal, int *sign);
32 * The function `ecvt' converts the double `x' to a null-terminated
33 * string of `ndigits' ASCII digits and returns a pointer to the string.
34 * The position of the decimal point relative to the beginning of the
35 * string is stored in the int pointed to by `decimal'. A negative
36 * value means that the decimal point appears to the left of the returned
37 * digits. If the sign of the result is negative, a non-zero value is
38 * stored in the int pointed to by `sign'; otherwise, a zero value is stored.
39 * The low-order digit of the returned value is rounded.
41 * The function `fcvt' is identical to `ecvt', except that the correct digit
42 * has been rounded for Fortran F-format output of the number of digits
43 * specified by `ndigits'.
46 * 10-Nov-92 Derek B Clegg (dclegg@next.com)
48 * 8-Jan-92 Peter King (king@next.com)
49 * Created from M68K sources which was created from VAX sources.
53 static double ecvt_rint(double x
);
54 static double ecvt_copysign(double x
, double y
);
55 static char *cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
);
57 #define isNAN(x) ((x) != (x))
59 /* big enough to handle %.20f conversion of 1e308 */
63 ecvt(double arg
, int ndigits
, int *decptp
, int *signp
)
65 return (cvt(arg
, ndigits
, decptp
, signp
, 1));
69 fcvt(double arg
, int ndigits
, int *decptp
, int *signp
)
71 return (cvt(arg
, ndigits
, decptp
, signp
, 0));
75 cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
)
80 static char buf
[NDIG
] = { 0 };
84 if (ndigits
>= NDIG
- 1)
93 while (p
< &buf
[ndigits
])
102 arg
= modf(arg
, &fi
);
105 /* Do integer part */
109 fj
= modf(fi
/10, &fi
);
111 *--p1
= (int)((fj
+ 0.03) * 10) + '0';
113 *--p1
= (int)ecvt_rint(fj
* 10) + '0';
117 while (p1
< &buf
[NDIG
])
119 } else if (arg
> 0) {
120 while ((fj
= arg
*10) < 1) {
127 /* Do the fractional part.
128 * p pts to where fraction should be concatenated.
129 * p1 is how far conversion must go to.
133 /* fcvt must provide ndigits after decimal pt */
135 /* if decpt was negative, we might be done for fcvt */
142 while (p
<= p1
&& p
< &buf
[NDIG
]) {
144 arg
= modf(arg
, &fj
);
145 *p
++ = (int)fj
+ '0';
148 /* If we converted all the way to the end of the buf, don't mess with
149 * rounding since there's nothing significant out here anyway.
151 if (p1
>= &buf
[NDIG
]) {
156 /* Round by adding 5 to last digit and propagating carries. */
177 static double L
= 4503599627370496.0E0
; /* 2**52 */
179 static int ecvt_init
= 0;
182 * FIXME: This deserves a comment if you turn this off!
183 * This used to #pragma CC_OPT_OFF.
184 * (Probably this was because the isNAN test was optimized away.)
185 * Why don't we just use the value of L given above?
195 if (ecvt_init
== 0) {
198 for (i
= 52; i
!= 0; i
--)
204 if (ecvt_copysign(x
, one
) >= L
) /* already an integer */
206 s
= ecvt_copysign(L
, x
);
207 t
= x
+ s
; /* x+s rounded to integer */
211 /* Couldn't we use something like the following structure instead of the
212 hacky unsigned short pointer stuff?
214 struct double_format {
216 unsigned exponent:11;
217 unsigned hi_fraction:20;
218 unsigned lo_fraction:32;
223 #define msign ((unsigned short)0x7fff)
224 #define mexp ((unsigned short)0x7ff0)
227 ecvt_copysign(double x
, double y
)
229 unsigned short *px
, *py
;
231 px
= (unsigned short *)&x
;
232 py
= (unsigned short *)&y
;
233 *px
= (*px
& msign
) | (*py
& ~msign
);
238 * This used to #pragma CC_OPT_ON