Bug 14933 - Failure to convert "infinity" to Inf constant using as.numeric or type.convert
Failure to convert "infinity" to Inf constant using as.numeric or type.convert
Status: CLOSED FIXED
Product: R
Classification: Unclassified
Component: Low-level
R 2.15.0 patched
All All
: P5 normal
Assigned To: R-core
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-05-31 01:26 UTC by Craig Struble
Modified: 2014-02-16 11:41 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Craig Struble 2012-05-31 01:26:15 UTC
Although R documentation claims to convert "infinity" (ignoring case) to the Inf constant, this does not happen. A simple example is 

> as.numeric("infinity")
[1] NA
Warning message:
NAs introduced by coercion

After digging through the main source code the problem can be seen in src/main/util.c, the R_strtod4 function:

double R_strtod4(const char *str, char **endptr, char dec, Rboolean NA)
{
    long double ans = 0.0, p10 = 10.0, fac = 1.0;
    int n, expn = 0, sign = 1, ndigits = 0, exph = -1;
    const char *p = str;

    /* optional whitespace */
    while (isspace(*p)) p++;

    if (NA && strncmp(p, "NA", 2) == 0) {
	ans = NA_REAL;
	p += 2;
	goto done;
    }

   /* optional sign */
    switch (*p) {
    case '-': sign = -1;
    case '+': p++;
    default: ;
    }

    if (strncasecmp(p, "NaN", 3) == 0) {
	ans = R_NaN;
	p += 3;
	goto done;
    } else if (strncasecmp(p, "Inf", 3) == 0) {
	ans = R_PosInf;
	p += 3;
	goto done;
    /* C99 specifies this */
    } else if (strncasecmp(p, "infinity", 8) == 0) {
	ans = R_PosInf;
	p += 8;
	goto done;
    }

    /* R_strtod4 continues... */


Specifically, the code 

    } else if (strncasecmp(p, "Inf", 3) == 0) {
	ans = R_PosInf;
	p += 3;
	goto done;
    /* C99 specifies this */
    } else if (strncasecmp(p, "infinity", 8) == 0) {
	ans = R_PosInf;
	p += 8;
	goto done;
    }

will always succeed on

    strncasecmp(p, "Inf", 3) == 0

when "infinity" is passed, because only the first 3 characters are considered. The remaining part of the string is pointed to for calling functions, most of which see that parsing did not reach the end of "infinity" and fail to perform the conversion. A proposed fix is to change the order of evaluation for the two if blocks:

    /* C99 specifies this */
    } else if (strncasecmp(p, "infinity", 8) == 0) {
	ans = R_PosInf;
	p += 8;
	goto done;
    } else if (strncasecmp(p, "Inf", 3) == 0) {
	ans = R_PosInf;
	p += 3;
	goto done;
    }

This bug is present in at least 2.12.2 and higher, but may be significantly older.
Comment 1 Jackie Rosen 2014-02-16 11:41:52 UTC
(spam comment removed)