mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* sprintf.c (rb_str_format): support %a format. [ruby-dev:40650]
* missing/vsnprintf.c (BSD_vfprintf): ditto. * missing/vsnprintf.c (cvt): ditto. * util.c (BSD__hdtoa): added. This is 2-clause BSDL licensed by David Schultz and from FreeBSD. * LEGAL: add about hdtoa() in util.c. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4d399f12d4
commit
12b2e16e21
6 changed files with 242 additions and 10 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
Thu Apr 1 13:30:12 2010 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
|
* sprintf.c (rb_str_format): support %a format. [ruby-dev:40650]
|
||||||
|
|
||||||
|
* missing/vsnprintf.c (BSD_vfprintf): ditto.
|
||||||
|
|
||||||
|
* missing/vsnprintf.c (cvt): ditto.
|
||||||
|
|
||||||
|
* util.c (BSD__hdtoa): added. This is 2-clause BSDL licensed
|
||||||
|
by David Schultz and from FreeBSD.
|
||||||
|
|
||||||
|
* LEGAL: add about hdtoa() in util.c.
|
||||||
|
|
||||||
Thu Apr 1 13:24:12 2010 NARUSE, Yui <naruse@ruby-lang.org>
|
Thu Apr 1 13:24:12 2010 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* object.c (rb_cstr_to_dbl): return 0.0 if hexadecimal and
|
* object.c (rb_cstr_to_dbl): return 0.0 if hexadecimal and
|
||||||
|
|
26
LEGAL
26
LEGAL
|
@ -123,6 +123,32 @@ win32/win32.[ch]:
|
||||||
You may distribute under the terms of either the GNU General Public
|
You may distribute under the terms of either the GNU General Public
|
||||||
License or the Artistic License, as specified in the perl README file.
|
License or the Artistic License, as specified in the perl README file.
|
||||||
|
|
||||||
|
util.c (partly):
|
||||||
|
|
||||||
|
Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
random.c
|
random.c
|
||||||
|
|
||||||
This file is under the new-style BSD license.
|
This file is under the new-style BSD license.
|
||||||
|
|
|
@ -559,7 +559,7 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
||||||
struct __suio uio; /* output information: summary */
|
struct __suio uio; /* output information: summary */
|
||||||
struct __siov iov[NIOV];/* ... and individual io vectors */
|
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||||
char ox[2]; /* space for 0x hex-prefix */
|
char ox[4]; /* space for 0x hex-prefix, hexadecimal's 1. */
|
||||||
char *const ebuf = buf + sizeof(buf);
|
char *const ebuf = buf + sizeof(buf);
|
||||||
#if SIZEOF_LONG > SIZEOF_INT
|
#if SIZEOF_LONG > SIZEOF_INT
|
||||||
long ln;
|
long ln;
|
||||||
|
@ -784,6 +784,11 @@ reswitch: switch (ch) {
|
||||||
base = 10;
|
base = 10;
|
||||||
goto number;
|
goto number;
|
||||||
#ifdef FLOATING_POINT
|
#ifdef FLOATING_POINT
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
if (prec >= 0)
|
||||||
|
prec++;
|
||||||
|
goto fp_begin;
|
||||||
case 'e': /* anomalous precision */
|
case 'e': /* anomalous precision */
|
||||||
case 'E':
|
case 'E':
|
||||||
if (prec != 0)
|
if (prec != 0)
|
||||||
|
@ -822,7 +827,12 @@ fp_begin: _double = va_arg(ap, double);
|
||||||
else
|
else
|
||||||
ch = 'g';
|
ch = 'g';
|
||||||
}
|
}
|
||||||
if (ch <= 'e') { /* 'e' or 'E' fmt */
|
if (ch == 'a' || ch == 'A') {
|
||||||
|
--expt;
|
||||||
|
expsize = exponent(expstr, expt, ch + 'p' - 'a');
|
||||||
|
size = expsize + ndig;
|
||||||
|
}
|
||||||
|
else if (ch <= 'e') { /* 'e' or 'E' fmt */
|
||||||
--expt;
|
--expt;
|
||||||
expsize = exponent(expstr, expt, ch);
|
expsize = exponent(expstr, expt, ch);
|
||||||
size = expsize + ndig;
|
size = expsize + ndig;
|
||||||
|
@ -1048,7 +1058,20 @@ long_len:
|
||||||
if ((flags & FPT) == 0) {
|
if ((flags & FPT) == 0) {
|
||||||
PRINT(cp, fieldsz);
|
PRINT(cp, fieldsz);
|
||||||
} else { /* glue together f_p fragments */
|
} else { /* glue together f_p fragments */
|
||||||
if (ch >= 'f') { /* 'f' or 'g' */
|
if (ch == 'a' || ch == 'A') {
|
||||||
|
ox[0] = '0';
|
||||||
|
ox[1] = ch + ('x' - 'a');
|
||||||
|
PRINT(ox, 2);
|
||||||
|
if (ndig > 1 || flags & ALT) {
|
||||||
|
ox[2] = *cp++;
|
||||||
|
ox[3] = '.';
|
||||||
|
PRINT(ox+2, 2);
|
||||||
|
PRINT(cp, ndig-1);
|
||||||
|
} else /* XpYYY */
|
||||||
|
PRINT(cp, 1);
|
||||||
|
PRINT(expstr, expsize);
|
||||||
|
}
|
||||||
|
else if (ch >= 'f') { /* 'f' or 'g' */
|
||||||
if (_double == 0) {
|
if (_double == 0) {
|
||||||
/* kludge for __dtoa irregularity */
|
/* kludge for __dtoa irregularity */
|
||||||
if (ndig <= 1 &&
|
if (ndig <= 1 &&
|
||||||
|
@ -1112,6 +1135,7 @@ error:
|
||||||
#ifdef FLOATING_POINT
|
#ifdef FLOATING_POINT
|
||||||
|
|
||||||
extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
|
extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
|
||||||
|
extern char *BSD__hdtoa(double, const char *, int, int *, int *, char **);
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
|
cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
|
||||||
|
@ -1135,7 +1159,14 @@ cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
|
||||||
} else {
|
} else {
|
||||||
*sign = '\000';
|
*sign = '\000';
|
||||||
}
|
}
|
||||||
|
if (ch == 'a' || ch =='A') {
|
||||||
|
digits = BSD__hdtoa(value,
|
||||||
|
ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF",
|
||||||
|
ndigits, decpt, &dsgn, &rve);
|
||||||
|
}
|
||||||
|
else {
|
||||||
digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
|
digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
|
||||||
|
}
|
||||||
memcpy(buf, digits, rve - digits);
|
memcpy(buf, digits, rve - digits);
|
||||||
xfree(digits);
|
xfree(digits);
|
||||||
rve = buf + (rve - digits);
|
rve = buf + (rve - digits);
|
||||||
|
@ -1181,7 +1212,7 @@ exponent(p0, exp, fmtch)
|
||||||
for (; t < expbuf + MAXEXP; *p++ = *t++);
|
for (; t < expbuf + MAXEXP; *p++ = *t++);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*p++ = '0';
|
if (fmtch & 15) *p++ = '0'; /* other than p or P */
|
||||||
*p++ = to_char(exp);
|
*p++ = to_char(exp);
|
||||||
}
|
}
|
||||||
return (int)(p - p0);
|
return (int)(p - p0);
|
||||||
|
|
16
sprintf.c
16
sprintf.c
|
@ -227,6 +227,10 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
|
||||||
* | equal to the precision, or in dd.dddd form otherwise.
|
* | equal to the precision, or in dd.dddd form otherwise.
|
||||||
* | The precision specifies the number of significant digits.
|
* | The precision specifies the number of significant digits.
|
||||||
* G | Equivalent to `g', but use an uppercase `E' in exponent form.
|
* G | Equivalent to `g', but use an uppercase `E' in exponent form.
|
||||||
|
* a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
|
||||||
|
* | which is consisted from optional sign, "0x", fraction part
|
||||||
|
* | as hexadecimal, "p", and exponential part as decimal.
|
||||||
|
* A | Equivalent to `a', but use uppercase `X' and `P'.
|
||||||
*
|
*
|
||||||
* Field | Other Format
|
* Field | Other Format
|
||||||
* ------+--------------------------------------------------------------
|
* ------+--------------------------------------------------------------
|
||||||
|
@ -244,7 +248,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
|
||||||
* Flag | Applies to | Meaning
|
* Flag | Applies to | Meaning
|
||||||
* ---------+---------------+-----------------------------------------
|
* ---------+---------------+-----------------------------------------
|
||||||
* space | bBdiouxX | Leave a space at the start of
|
* space | bBdiouxX | Leave a space at the start of
|
||||||
* | eEfgG | non-negative numbers.
|
* | aAeEfgG | non-negative numbers.
|
||||||
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
|
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
|
||||||
* | | a minus sign with absolute value for
|
* | | a minus sign with absolute value for
|
||||||
* | | negative values.
|
* | | negative values.
|
||||||
|
@ -255,19 +259,19 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
|
||||||
* | | sprintf string.
|
* | | sprintf string.
|
||||||
* ---------+---------------+-----------------------------------------
|
* ---------+---------------+-----------------------------------------
|
||||||
* # | bBoxX | Use an alternative format.
|
* # | bBoxX | Use an alternative format.
|
||||||
* | eEfgG | For the conversions `o', increase the precision
|
* | aAeEfgG | For the conversions `o', increase the precision
|
||||||
* | | until the first digit will be `0' if
|
* | | until the first digit will be `0' if
|
||||||
* | | it is not formatted as complements.
|
* | | it is not formatted as complements.
|
||||||
* | | For the conversions `x', `X', `b' and `B'
|
* | | For the conversions `x', `X', `b' and `B'
|
||||||
* | | on non-zero, prefix the result with ``0x'',
|
* | | on non-zero, prefix the result with ``0x'',
|
||||||
* | | ``0X'', ``0b'' and ``0B'', respectively.
|
* | | ``0X'', ``0b'' and ``0B'', respectively.
|
||||||
* | | For `e', `E', `f', `g', and 'G',
|
* | | For `a', `A', `e', `E', `f', `g', and 'G',
|
||||||
* | | force a decimal point to be added,
|
* | | force a decimal point to be added,
|
||||||
* | | even if no digits follow.
|
* | | even if no digits follow.
|
||||||
* | | For `g' and 'G', do not remove trailing zeros.
|
* | | For `g' and 'G', do not remove trailing zeros.
|
||||||
* ---------+---------------+-----------------------------------------
|
* ---------+---------------+-----------------------------------------
|
||||||
* + | bBdiouxX | Add a leading plus sign to non-negative
|
* + | bBdiouxX | Add a leading plus sign to non-negative
|
||||||
* | eEfgG | numbers.
|
* | aAeEfgG | numbers.
|
||||||
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
|
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
|
||||||
* | | a minus sign with absolute value for
|
* | | a minus sign with absolute value for
|
||||||
* | | negative values.
|
* | | negative values.
|
||||||
|
@ -275,7 +279,7 @@ get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
|
||||||
* - | all | Left-justify the result of this conversion.
|
* - | all | Left-justify the result of this conversion.
|
||||||
* ---------+---------------+-----------------------------------------
|
* ---------+---------------+-----------------------------------------
|
||||||
* 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
|
* 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
|
||||||
* | eEfgG | For `o', `x', `X', `b' and `B', radix-1
|
* | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
|
||||||
* | (numeric fmt) | is used for negative numbers formatted as
|
* | (numeric fmt) | is used for negative numbers formatted as
|
||||||
* | | complements.
|
* | | complements.
|
||||||
* ---------+---------------+-----------------------------------------
|
* ---------+---------------+-----------------------------------------
|
||||||
|
@ -983,6 +987,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
||||||
case 'G':
|
case 'G':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
{
|
{
|
||||||
VALUE val = GETARG();
|
VALUE val = GETARG();
|
||||||
double fval;
|
double fval;
|
||||||
|
|
|
@ -191,6 +191,19 @@ class TestSprintf < Test::Unit::TestCase
|
||||||
assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
|
assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_float_hex
|
||||||
|
assert_equal("-0x0p+0", sprintf("%a", -0.0))
|
||||||
|
assert_equal("0x0p+0", sprintf("%a", 0.0))
|
||||||
|
assert_equal("0x1p-1", sprintf("%a", 0.5))
|
||||||
|
assert_equal("0x1p+0", sprintf("%a", 1.0))
|
||||||
|
assert_equal("0x1p+1", sprintf("%a", 2.0))
|
||||||
|
assert_equal("0x1.193ea7aad030ap+0", sprintf("%a", Math.log(3)))
|
||||||
|
assert_equal("0X1.193EA7AAD030AP+0", sprintf("%A", Math.log(3)))
|
||||||
|
assert_equal("0x1p+10", sprintf("%a", 1024))
|
||||||
|
assert_equal("0x1.23456p+789", sprintf("%a", 3.704450999893983e+237))
|
||||||
|
assert_equal("0x1p-1074", sprintf("%a", 4.9e-324))
|
||||||
|
end
|
||||||
|
|
||||||
BSIZ = 120
|
BSIZ = 120
|
||||||
|
|
||||||
def test_skip
|
def test_skip
|
||||||
|
|
143
util.c
143
util.c
|
@ -3857,6 +3857,149 @@ ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *ar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DBL_MANH_SIZE 20
|
||||||
|
#define DBL_MANL_SIZE 32
|
||||||
|
#define INFSTR "Infinity"
|
||||||
|
#define NANSTR "NaN"
|
||||||
|
#define DBL_ADJ (DBL_MAX_EXP - 2)
|
||||||
|
#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
|
||||||
|
#define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1)
|
||||||
|
#define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | (v << Exp_shift)))
|
||||||
|
#define dmanh_get(u) ((int)(word0(u) & Frac_mask))
|
||||||
|
#define dmanl_get(u) ((int)word1(u))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This procedure converts a double-precision number in IEEE format
|
||||||
|
* into a string of hexadecimal digits and an exponent of 2. Its
|
||||||
|
* behavior is bug-for-bug compatible with dtoa() in mode 2, with the
|
||||||
|
* following exceptions:
|
||||||
|
*
|
||||||
|
* - An ndigits < 0 causes it to use as many digits as necessary to
|
||||||
|
* represent the number exactly.
|
||||||
|
* - The additional xdigs argument should point to either the string
|
||||||
|
* "0123456789ABCDEF" or the string "0123456789abcdef", depending on
|
||||||
|
* which case is desired.
|
||||||
|
* - This routine does not repeat dtoa's mistake of setting decpt
|
||||||
|
* to 9999 in the case of an infinity or NaN. INT_MAX is used
|
||||||
|
* for this purpose instead.
|
||||||
|
*
|
||||||
|
* Note that the C99 standard does not specify what the leading digit
|
||||||
|
* should be for non-zero numbers. For instance, 0x1.3p3 is the same
|
||||||
|
* as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes
|
||||||
|
* the leading digit a 1. This ensures that the exponent printed is the
|
||||||
|
* actual base-2 exponent, i.e., ilogb(d).
|
||||||
|
*
|
||||||
|
* Inputs: d, xdigs, ndigits
|
||||||
|
* Outputs: decpt, sign, rve
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
BSD__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
|
||||||
|
char **rve)
|
||||||
|
{
|
||||||
|
U u;
|
||||||
|
char *s, *s0;
|
||||||
|
int bufsize;
|
||||||
|
uint32_t manh, manl;
|
||||||
|
|
||||||
|
u.d = d;
|
||||||
|
if (word0(u) & Sign_bit) {
|
||||||
|
/* set sign for everything, including 0's and NaNs */
|
||||||
|
*sign = 1;
|
||||||
|
word0(u) &= ~Sign_bit; /* clear sign bit */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*sign = 0;
|
||||||
|
|
||||||
|
switch (fpclassify(d)) {
|
||||||
|
case FP_NORMAL:
|
||||||
|
*decpt = dexp_get(u) - DBL_ADJ;
|
||||||
|
break;
|
||||||
|
case FP_ZERO:
|
||||||
|
*decpt = 1;
|
||||||
|
return (nrv_alloc("0", rve, 1));
|
||||||
|
case FP_SUBNORMAL:
|
||||||
|
u.d *= 5.363123171977039e+154 /* 0x1p514 */;
|
||||||
|
*decpt = dexp_get(u) - (514 + DBL_ADJ);
|
||||||
|
break;
|
||||||
|
case FP_INFINITE:
|
||||||
|
*decpt = INT_MAX;
|
||||||
|
return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
|
||||||
|
default: /* FP_NAN or unrecognized */
|
||||||
|
*decpt = INT_MAX;
|
||||||
|
return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FP_NORMAL or FP_SUBNORMAL */
|
||||||
|
|
||||||
|
if (ndigits == 0) /* dtoa() compatibility */
|
||||||
|
ndigits = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If ndigits < 0, we are expected to auto-size, so we allocate
|
||||||
|
* enough space for all the digits.
|
||||||
|
*/
|
||||||
|
bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
|
||||||
|
s0 = rv_alloc(bufsize);
|
||||||
|
|
||||||
|
/* Round to the desired number of digits. */
|
||||||
|
if (SIGFIGS > ndigits && ndigits > 0) {
|
||||||
|
float redux = 1.0;
|
||||||
|
int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
|
||||||
|
dexp_set(u, offset);
|
||||||
|
u.d += redux;
|
||||||
|
u.d -= redux;
|
||||||
|
*decpt += dexp_get(u) - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
manh = dmanh_get(u);
|
||||||
|
manl = dmanl_get(u);
|
||||||
|
*s0 = '1';
|
||||||
|
for (s = s0 + 1; s < s0 + bufsize; s++) {
|
||||||
|
*s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf];
|
||||||
|
manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4));
|
||||||
|
manl <<= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If ndigits < 0, we are expected to auto-size the precision. */
|
||||||
|
if (ndigits < 0) {
|
||||||
|
for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s0 + ndigits;
|
||||||
|
*s = '\0';
|
||||||
|
if (rve != NULL)
|
||||||
|
*rve = s;
|
||||||
|
return (s0);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue