Skip to content

Commit e19b493

Browse files
author
ripley
committed
apply patch for PR#18805, with added comments
git-svn-id: https://svn.r-project.org/R/trunk@87294 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent c20ebd2 commit e19b493

File tree

2 files changed

+38
-25
lines changed

2 files changed

+38
-25
lines changed

doc/NEWS.Rd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@
252252

253253
\item The deprecated S-compatibility macros \code{F77_COM} and
254254
\code{F77_COMDECL} have been removed from header \file{R_ext/RS.h}.
255+
256+
\item The functions \code{R_strtod} and \code{R_atof} now allow
257+
hexadecimal constants without an exponent, for compatibility with
258+
their C99 versions, (\PR{18805})
255259
}
256260
}
257261

src/main/util.c

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,9 +2093,9 @@ int attribute_hidden Rf_AdobeSymbol2ucs2(int n)
20932093
R_strtod5 is used by type_convert(numerals=) (utils/src/io.c)
20942094
20952095
The parser uses R_atof (and handles non-numeric strings itself).
2096-
That is the same as R_strtod but ignores endptr.
2097-
Also used by gnuwin32/windlgs/src/ttest.c,
2098-
exported and in Utils.h (but not in R-exts).
2096+
That is the same as R_strtod but ignores endptr. Also used by
2097+
gnuwin32/windlgs/src/ttest.c, exported and in Utils.h (and
2098+
documeented in R-exts only since R 4.4.1 )
20992099
*/
21002100

21012101
double R_strtod5(const char *str, char **endptr, char dec,
@@ -2138,6 +2138,12 @@ double R_strtod5(const char *str, char **endptr, char dec,
21382138

21392139
int n, expn = 0;
21402140
if(strlen(p) > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { // Hexadecimal "0x....."
2141+
/* Prior to 4.5.0 this did not allow forms such as 0x1.234
2142+
without an exponent.: C99 allow this and implictly
2143+
appends "p0"".
2144+
2145+
Changed following PR£18805
2146+
*/
21412147
int exph = -1;
21422148

21432149
/* This will overflow to Inf if appropriate */
@@ -2162,16 +2168,18 @@ double R_strtod5(const char *str, char **endptr, char dec,
21622168
} \
21632169
}
21642170
strtod_EXACT_CLAUSE;
2171+
/* Binary exponent, if any */
21652172
if (*p == 'p' || *p == 'P') {
21662173
int expsign = 1;
2167-
double p2 = 2.0;
21682174
switch(*++p) {
21692175
case '-': expsign = -1;
21702176
case '+': p++;
21712177
default: ;
21722178
}
21732179
#define MAX_EXPONENT_PREFIX 9999
2174-
/* exponents beyond ca +1024/-1076 over/underflow */
2180+
/* exponents beyond ca +1024/-1076 over/underflow
2181+
Limit exponsent from PR#16358.
2182+
*/
21752183
int ndig = 0;
21762184
for (n = 0; *p >= '0' && *p <= '9'; p++, ndig++)
21772185
n = (n < MAX_EXPONENT_PREFIX) ? n * 10 + (*p - '0') : n;
@@ -2180,28 +2188,29 @@ double R_strtod5(const char *str, char **endptr, char dec,
21802188
p = str; /* back out */
21812189
goto done;
21822190
}
2183-
if (ans != 0.0) { /* PR#15976: allow big exponents on 0 */
2184-
LDOUBLE fac = 1.0;
2185-
expn += expsign * n;
2186-
if(exph > 0) {
2187-
if (expn - exph < -122) { /* PR#17199: fac may overflow below if expn - exph is too small.
2188-
2^-122 is a bit bigger than 1E-37, so should be fine on all systems */
2189-
for (n = exph, fac = 1.0; n; n >>= 1, p2 *= p2)
2190-
if (n & 1) fac *= p2;
2191-
ans /= fac;
2192-
p2 = 2.0;
2193-
} else
2194-
expn -= exph;
2195-
}
2196-
if (expn < 0) {
2197-
for (n = -expn, fac = 1.0; n; n >>= 1, p2 *= p2)
2191+
expn += expsign * n;
2192+
}
2193+
if (ans != 0.0) { /* PR#15976: allow big exponents on 0 */
2194+
LDOUBLE fac = 1.0;
2195+
double p2 = 2.0;
2196+
if(exph > 0) {
2197+
if (expn - exph < -122) { /* PR#17199: fac may overflow below if expn - exph is too small.
2198+
2^-122 is a bit bigger than 1E-37, so should be fine on all systems */
2199+
for (n = exph, fac = 1.0; n; n >>= 1, p2 *= p2)
21982200
if (n & 1) fac *= p2;
21992201
ans /= fac;
2200-
} else {
2201-
for (n = expn, fac = 1.0; n; n >>= 1, p2 *= p2)
2202-
if (n & 1) fac *= p2;
2203-
ans *= fac;
2204-
}
2202+
p2 = 2.0;
2203+
} else
2204+
expn -= exph;
2205+
}
2206+
if (expn < 0) {
2207+
for (n = -expn, fac = 1.0; n; n >>= 1, p2 *= p2)
2208+
if (n & 1) fac *= p2;
2209+
ans /= fac;
2210+
} else {
2211+
for (n = expn, fac = 1.0; n; n >>= 1, p2 *= p2)
2212+
if (n & 1) fac *= p2;
2213+
ans *= fac;
22052214
}
22062215
}
22072216
goto done;

0 commit comments

Comments
 (0)