]>
git.saurik.com Git - apple/libc.git/blob - gen.subproj/ppc.subproj/ecvt.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
24 * File: libc/m98k/gen/ecvt.c
26 * char *ecvt(double x, int ndigits, int *decimal, int *sign);
27 * char *fcvt(double x, int ndigits, int *decimal, int *sign);
29 * The function `ecvt' converts the double `x' to a null-terminated
30 * string of `ndigits' ASCII digits and returns a pointer to the string.
31 * The position of the decimal point relative to the beginning of the
32 * string is stored in the int pointed to by `decimal'. A negative
33 * value means that the decimal point appears to the left of the returned
34 * digits. If the sign of the result is negative, a non-zero value is
35 * stored in the int pointed to by `sign'; otherwise, a zero value is stored.
36 * The low-order digit of the returned value is rounded.
38 * The function `fcvt' is identical to `ecvt', except that the correct digit
39 * has been rounded for Fortran F-format output of the number of digits
40 * specified by `ndigits'.
43 * 10-Nov-92 Derek B Clegg (dclegg@next.com)
45 * 8-Jan-92 Peter King (king@next.com)
46 * Created from M68K sources which was created from VAX sources.
50 static double ecvt_rint(double x
);
51 static double ecvt_copysign(double x
, double y
);
52 static char *cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
);
54 #define isNAN(x) ((x) != (x))
56 /* big enough to handle %.20f conversion of 1e308 */
60 ecvt(double arg
, int ndigits
, int *decptp
, int *signp
)
62 return (cvt(arg
, ndigits
, decptp
, signp
, 1));
66 fcvt(double arg
, int ndigits
, int *decptp
, int *signp
)
68 return (cvt(arg
, ndigits
, decptp
, signp
, 0));
72 cvt(double arg
, int ndigits
, int *decptp
, int *signp
, int eflag
)
77 static char buf
[NDIG
] = { 0 };
81 if (ndigits
>= NDIG
- 1)
90 while (p
< &buf
[ndigits
])
102 /* Do integer part */
106 fj
= modf(fi
/10, &fi
);
108 *--p1
= (int)((fj
+ 0.03) * 10) + '0';
110 *--p1
= (int)ecvt_rint(fj
* 10) + '0';
114 while (p1
< &buf
[NDIG
])
116 } else if (arg
> 0) {
117 while ((fj
= arg
*10) < 1) {
124 /* Do the fractional part.
125 * p pts to where fraction should be concatenated.
126 * p1 is how far conversion must go to.
130 /* fcvt must provide ndigits after decimal pt */
132 /* if decpt was negative, we might be done for fcvt */
139 while (p
<= p1
&& p
< &buf
[NDIG
]) {
141 arg
= modf(arg
, &fj
);
142 *p
++ = (int)fj
+ '0';
145 /* If we converted all the way to the end of the buf, don't mess with
146 * rounding since there's nothing significant out here anyway.
148 if (p1
>= &buf
[NDIG
]) {
153 /* Round by adding 5 to last digit and propagating carries. */
174 static double L
= 4503599627370496.0E0
; /* 2**52 */
176 static int ecvt_init
= 0;
179 * FIXME: This deserves a comment if you turn this off!
180 * This used to #pragma CC_OPT_OFF.
181 * (Probably this was because the isNAN test was optimized away.)
182 * Why don't we just use the value of L given above?
192 if (ecvt_init
== 0) {
195 for (i
= 52; i
!= 0; i
--)
201 if (ecvt_copysign(x
, one
) >= L
) /* already an integer */
203 s
= ecvt_copysign(L
, x
);
204 t
= x
+ s
; /* x+s rounded to integer */
208 /* Couldn't we use something like the following structure instead of the
209 hacky unsigned short pointer stuff?
211 struct double_format {
213 unsigned exponent:11;
214 unsigned hi_fraction:20;
215 unsigned lo_fraction:32;
220 #define msign ((unsigned short)0x7fff)
221 #define mexp ((unsigned short)0x7ff0)
224 ecvt_copysign(double x
, double y
)
226 unsigned short *px
, *py
;
228 px
= (unsigned short *)&x
;
229 py
= (unsigned short *)&y
;
230 *px
= (*px
& msign
) | (*py
& ~msign
);
235 * This used to #pragma CC_OPT_ON