2 * Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libc/gdtoa/_hldtoa.c,v 1.2 2008/04/12 14:53:52 das Exp $
34 #include "../stdio/floatio.h"
38 #if (LDBL_MANT_DIG > DBL_MANT_DIG)
40 /* Strings values used by dtoa() */
41 #define INFSTR "Infinity"
44 #ifdef LDBL_IMPLICIT_NBIT
45 #define MANH_SIZE LDBL_MANH_SIZE
47 #define MANH_SIZE (LDBL_MANH_SIZE - 1)
51 typedef uint64_t manh_t
;
53 typedef uint32_t manh_t
;
56 #if LDBL_MANL_SIZE > 32
57 typedef uint64_t manl_t
;
59 typedef uint32_t manl_t
;
62 #define LDBL_ADJ (LDBL_MAX_EXP - 2)
63 #define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1)
65 static const float one
[] = { 1.0f
, -1.0f
};
68 * This is the long double version of __hdtoa().
71 __hldtoa(long double e
, const char *xdigs
, int ndigits
, int *decpt
, int *sign
,
83 switch (fpclassify(e
)) {
85 *decpt
= u
.bits
.exp
- LDBL_ADJ
;
89 return (nrv_alloc("0", rve
, 1));
92 *decpt
= u
.bits
.exp
- (514 + LDBL_ADJ
);
96 return (nrv_alloc(INFSTR
, rve
, sizeof(INFSTR
) - 1));
97 default: /* FP_NAN or unrecognized */
99 return (nrv_alloc(NANSTR
, rve
, sizeof(NANSTR
) - 1));
102 /* FP_NORMAL or FP_SUBNORMAL */
104 if (ndigits
== 0) /* dtoa() compatibility */
108 * If ndigits < 0, we are expected to auto-size, so we allocate
109 * enough space for all the digits.
111 bufsize
= (ndigits
> 0) ? ndigits
: SIGFIGS
;
112 s0
= rv_alloc(bufsize
);
114 /* Round to the desired number of digits. */
115 if (SIGFIGS
> ndigits
&& ndigits
> 0) {
116 float redux
= one
[u
.bits
.sign
];
117 int offset
= 4 * ndigits
+ LDBL_MAX_EXP
- 4 - LDBL_MANT_DIG
;
121 *decpt
+= u
.bits
.exp
- offset
;
128 for (s
= s0
+ 1; s
< s0
+ bufsize
; s
++) {
129 *s
= xdigs
[(manh
>> (MANH_SIZE
- 4)) & 0xf];
130 manh
= (manh
<< 4) | (manl
>> (LDBL_MANL_SIZE
- 4));
134 /* If ndigits < 0, we are expected to auto-size the precision. */
136 for (ndigits
= SIGFIGS
; s0
[ndigits
- 1] == '0'; ndigits
--)
147 #else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
150 __hldtoa(long double e
, const char *xdigs
, int ndigits
, int *decpt
, int *sign
,
154 return (__hdtoa((double)e
, xdigs
, ndigits
, decpt
, sign
, rve
));
157 #endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */