Illegal Logical Values

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Illegal Logical Values

R devel mailing list
I'm wondering if WRE Section 5.2 should be a little more explicit about misuse of integer values other than NA, 0, and 1 in LGLSXPs.  I'm thinking of this passage:

> Logical values are sent as 0 (FALSE), 1 (TRUE) or INT_MIN = -2147483648 (NA, but only if NAOK is true), and the compiled code should return one of these three values. (Non-zero values other than INT_MIN are mapped to TRUE.)

The parenthetical seems to suggest that something like 'LOGICAL(x)[0] = 2;' will be treated as TRUE, which it sometimes is, and sometimes isn't:

not.true <- inline::cfunction(body='
  SEXP res = allocVector(LGLSXP, 1);
  LOGICAL(res)[0] = 2;
  return res;'
)()
not.true
## [1] TRUE
not.true == TRUE
## [1] FALSE
not.true[1] == TRUE  # due to scalar subset handling
## [1] TRUE
not.true == 2L
## [1] TRUE


Perhaps a more explicit warning that using anything other than 0, 1, or NA is undefined behavior is warranted?  Obviously people should know better than to expect correct behavior, but the fact that the behavior is correct in some cases (e.g. printing, scalar subsetting) might be confusing.

This is based off of Drew Schmidt's accidental discovery yesterday: <https://gist.github.com/wrathematics/c3e5225cf56596b31e01f717e8675640>.
Best,
Brodie.

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Illegal Logical Values

Martyn Plummer-3
On Fri, 2017-10-20 at 14:01 +0000, brodie gaslam via R-devel wrote:

> I'm wondering if WRE Section 5.2 should be a little more explicit
> about misuse of integer values other than NA, 0, and 1 in LGLSXPs.
> I'm thinking of this passage:
>
> > Logical values are sent as 0 (FALSE), 1 (TRUE) or INT_MIN =
> > -2147483648 (NA, but only if NAOK is true), and the compiled code
> > should return one of these three values. (Non-zero values other
> > than INT_MIN are mapped to TRUE.)
>
> The parenthetical seems to suggest that something like 'LOGICAL(x)[0]
> = 2;' will be treated as TRUE, which it sometimes is, and sometimes
> isn't:

The title of Section 5.2 is "Interface functions .C and .Fortran" and
the text above refers to those interfaces. It explains how logical
vectors are mapped to C integer arrays on entry and back again on exit.

This does work as advertised. Here is a simple example. File
"nottrue.c" contains the text

void nottrue(int *x)
{
   x[0] = 2;
}

This is compiled with "R CMD SHLIB nottrue.c" to created the shared
object "nottrue.so"

> dyn.load("nottrue.so")
> a <- .C("nottrue", x=integer(1))
> a
$x
[1] 2

> a <- .C("nottrue", x=logical(1))
> a
$x
[1] TRUE

> isTRUE(a$x)
[1] TRUE
> as.integer(a)
[1] 1

So for a logical argument, the integer value 2 is mapped back to a
valid value on return.

> not.true <- inline::cfunction(body='
>   SEXP res = allocVector(LGLSXP, 1);
>   LOGICAL(res)[0] = 2;
>   return res;'
> )()
> not.true
> ## [1] TRUE
> not.true == TRUE
> ## [1] FALSE
> not.true[1] == TRUE  # due to scalar subset handling
> ## [1] TRUE
> not.true == 2L
> ## [1] TRUE

In your last example, not.true is coerced to integer (as explain in the
help for ("==") and its integer value of 2 is recovered.

> Perhaps a more explicit warning that using anything other than 0, 1,
> or NA is undefined behavior is warranted?  Obviously people should
> know better than to expect correct behavior, but the fact that the
> behavior is correct in some cases (e.g. printing, scalar subsetting)
> might be confusing.

Yes if people are tripping up on this then we could clarify that the
.Call interface does not remap logical vectors on exit. Hence
assignment of any value other than 0, 1 or INT_MIN to the elements of a
logical vector may cause unexpected behaviour when this vector is
returned to R.

Martyn

> >
> Best,
> B.rodie.
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Illegal Logical Values

Radford Neal
In reply to this post by R devel mailing list
> On Fri, 2017-10-20 at 14:01 +0000, brodie gaslam via R-devel wrote:

> > I'm thinking of this passage:
> >
> > > Logical values are sent as 0 (FALSE), 1 (TRUE) or INT_MIN =
> > > -2147483648 (NA, but only if NAOK is true), and the compiled code
> > > should return one of these three values. (Non-zero values other
> > > than INT_MIN are mapped to TRUE.)
> >
> > The parenthetical seems to suggest that something like 'LOGICAL(x)[0]
> > = 2;' will be treated as TRUE, which it sometimes is, and sometimes
> > isn't:
>
> From: Martyn Plummer <[hidden email]>

> The title of Section 5.2 is "Interface functions .C and .Fortran" and
> the text above refers to those interfaces. It explains how logical
> vectors are mapped to C integer arrays on entry and back again on exit.
>
> This does work as advertised.


Not always.  As I reported on bugzilla three years ago (PR#15878), it
only works if the logical argument does not have to be copied.  The
bug has been fixed in pqR since pqR-2014-09-30.

   Radford Neal

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Illegal Logical Values

Tomas Kalibera
On 10/21/2017 04:14 PM, Radford Neal wrote:

>> On Fri, 2017-10-20 at 14:01 +0000, brodie gaslam via R-devel wrote:
>>> I'm thinking of this passage:
>>>
>>>> Logical values are sent as 0 (FALSE), 1 (TRUE) or INT_MIN =
>>>> -2147483648 (NA, but only if NAOK is true), and the compiled code
>>>> should return one of these three values. (Non-zero values other
>>>> than INT_MIN are mapped to TRUE.)
>>> The parenthetical seems to suggest that something like 'LOGICAL(x)[0]
>>> = 2;' will be treated as TRUE, which it sometimes is, and sometimes
>>> isn't:
>> From: Martyn Plummer <[hidden email]>
>> The title of Section 5.2 is "Interface functions .C and .Fortran" and
>> the text above refers to those interfaces. It explains how logical
>> vectors are mapped to C integer arrays on entry and back again on exit.
>>
>> This does work as advertised.
>
> Not always.  As I reported on bugzilla three years ago (PR#15878), it
> only works if the logical argument does not have to be copied.  The
> bug has been fixed in pqR since pqR-2014-09-30.
>
>     Radford Neal
Thanks, that's indeed a bug - now fixed in 73583.
Tomas

>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel