[Rd] Spurious warnings in coercion from double/complex/character to raw
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Fri Sep 10 18:12:02 CEST 2021
On 10/09/2021 11:29 a.m., Hervé Pagès wrote:
> Hi,
>
> The first warning below is unexpected and confusing:
>
> > as.raw(c(3e9, 5.1))
> [1] 00 05
> Warning messages:
> 1: NAs introduced by coercion to integer range
> 2: out-of-range values treated as 0 in coercion to raw
>
> The reason we get it is that coercion from numeric to raw is currently
> implemented on top of coercion from numeric to int (file
> src/main/coerce.c, lines 700-710):
>
> case REALSXP:
> for (i = 0; i < n; i++) {
> // if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();
> tmp = IntegerFromReal(REAL_ELT(v, i), &warn);
> if(tmp == NA_INTEGER || tmp < 0 || tmp > 255) {
> tmp = 0;
> warn |= WARN_RAW;
> }
> pa[i] = (Rbyte) tmp;
> }
> break;
>
> The first warning comes from the call to IntegerFromReal().
>
> The following code avoids the spurious warning and is also simpler and
> slightly faster:
>
> case REALSXP:
> for (i = 0; i < n; i++) {
> // if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();
> double vi = REAL_ELT(v, i);
> if(ISNAN(vi) || (tmp = (int) vi) < 0 || tmp > 255) {
> tmp = 0;
> warn |= WARN_RAW;
> }
> pa[i] = (Rbyte) tmp;
> }
> break;
Doesn't that give different results in case vi is so large that "(int)
vi" overflows? (I don't know what the C standard says, but some online
references say that behaviour is implementation dependent.)
For example, if
vi = 1.0 + INT_MAX;
wouldn't "(int) vi" be equal to a small integer?
Duncan Murdoch
>
> Coercion from complex to raw has the same problem:
>
> > as.raw(c(3e9+0i, 5.1))
> [1] 00 05
> Warning messages:
> 1: NAs introduced by coercion to integer range
> 2: out-of-range values treated as 0 in coercion to raw
>
> Current implementation (file src/main/coerce.c, lines 711-721):
>
> case CPLXSXP:
> for (i = 0; i < n; i++) {
> // if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();
> tmp = IntegerFromComplex(COMPLEX_ELT(v, i), &warn);
> if(tmp == NA_INTEGER || tmp < 0 || tmp > 255) {
> tmp = 0;
> warn |= WARN_RAW;
> }
> pa[i] = (Rbyte) tmp;
> }
> break;
>
> This implementation has the following additional problem when the
> supplied complex has a nonzero imaginary part:
>
> > as.raw(300+4i)
> [1] 00
> Warning messages:
> 1: imaginary parts discarded in coercion
> 2: out-of-range values treated as 0 in coercion to raw
>
> > as.raw(3e9+4i)
> [1] 00
> Warning messages:
> 1: NAs introduced by coercion to integer range
> 2: out-of-range values treated as 0 in coercion to raw
>
> In one case we get a warning about the discarding of the imaginary part
> but not the other case, which is unexpected. We should see the exact
> same warning (or warnings) in both cases.
>
> With the following fix we only get the warning about the discarding of
> the imaginary part if we are not in a "out-of-range values treated as 0
> in coercion to raw" situation:
>
> case CPLXSXP:
> for (i = 0; i < n; i++) {
> // if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();
> Rcomplex vi = COMPLEX_ELT(v, i);
> if(ISNAN(vi.r) || ISNAN(vi.i) || (tmp = (int) vi.r) < 0 ||
> tmp > 255) {
> tmp = 0;
> warn |= WARN_RAW;
> } else {
> if(vi.i != 0.0)
> warn |= WARN_IMAG;
> }
> pa[i] = (Rbyte) tmp;
> }
> break;
>
> Finally, coercion from character to raw has the same problem and its
> code can be fixed in a similar manner:
>
> > as.raw(c("3e9", 5.1))
> [1] 00 05
> Warning messages:
> 1: NAs introduced by coercion to integer range
> 2: out-of-range values treated as 0 in coercion to raw
>
> Cheers,
> H.
>
>
More information about the R-devel
mailing list