[Rd] Possible inconsistency between `as.complex(NA_real_)` and the docs

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Sat Apr 22 18:41:26 CEST 2023


> Hi all,
> 
> Surprisingly (at least to me), `as.complex(NA_real_)` results in
> `complex(real = NA_real_, imaginary = 0)` rather than `NA_complex_`.

Well, the logic here is really the mathematical equivalence:
if you turn a real number x  in to a complex one, say z,
then  z =  x + i * 0 , i.e., real part x  and imaginary part 0.


> It seems to me that this goes against the docs of `as.complex()`,
> which say this in the Details section:
> 
> "Up to R versions 3.2.x, all forms of NA and NaN were coerced to a
> complex NA, i.e., the NA_complex_ constant, for which both the real
> and imaginary parts are NA. Since R 3.3.0, typically only objects
> which are NA in parts are coerced to complex NA, but others with NaN
> parts, are not. As a consequence, complex arithmetic where only NaN's
> (but no NA's) are involved typically will not give complex NA but
> complex numbers with real or imaginary parts of NaN."

The above was written in  svn commit 69410  (the github mirror
of which you mention below)
------------------------------------------------------------------------
r69410 | maechler | 2015-09-22 10:11:34 +0200 (Tue, 22 Sep 2015) | 1 line

more consistent behavior of complex number NaN / NA - not back-compatible
------------------------------------------------------------------------

which I had to amend a day later in
------------------------------------------------------------------------
r69423 | maechler | 2015-09-23 19:23:57 +0200 (Wed, 23 Sep 2015) | 1 line

even NaN + NA_complex_ is platform dependent
------------------------------------------------------------------------

just with adding the following at the end of
example(as.complex)  :

showC <- function(z) noquote(sprintf("(R = \%g, I = \%g)", Re(z), Im(z)))

## The exact result of this *depends* on the platform, compiler, math-library:
(NpNA <- NaN + NA_complex_) ; str(NpNA) # *behaves* as 'cplx NA' ..
stopifnot(is.na(NpNA), is.na(NA_complex_), is.na(Re(NA_complex_)), is.na(Im(NA_complex_)))
showC(NpNA)# but not always is {shows  '(R = NaN, I = NA)' on some platforms}
## and this is not TRUE everywhere:
identical(NpNA, NA_complex_)
showC(NA_complex_) # always == (R = NA, I = NA)

And that was a while ago.  In the mean time I've become more
aware of the fact that --- to my large chagrin --- our
distinction of NA and NaN  unfortunately   has more problems in
quite platform-dependent arithmetic than I had still hoped at
the time.

> To me this suggests that `NA_real_`, which is "NA in parts", should
> have been coerced to "complex NA".
> 
> `NA_integer_` is actually coerced to `NA_complex_`, which to me is
> further evidence that `NA_real_` should have been as well.

Yeah.. I agree that  as.complex(.) should return the same for integer
and double NA.

I see where and how the change would need to happen.
.. we'll see if it is feasible (I guess "yes" with 0.98 subjective probability)


> Here is the original commit where this behavior was changed in R 3.3.0:
> https://github.com/wch/r-source/commit/4a4c2052e5a541981a249d4fcf92b54ca7f0a2df
> 
> ```
> # This is expected, based on the docs
> x <- as.complex(NaN)
> Re(x)
> #> [1] NaN
> Im(x)
> #> [1] 0
> 
> # This is not expected. The docs say:
> # "Since R 3.3.0, typically only objects which are NA in parts are
> coerced to complex NA"
> # but that doesn't seem true for `NA_real_`.
> x <- as.complex(NA_real_)
> Re(x)
> #> [1] NA
> Im(x)
> #> [1] 0
> 
> # It does seem to be the case for `NA_integer_`
> x <- as.complex(NA_integer_)
> Re(x)
> #> [1] NA
> Im(x)
> #> [1] NA
> ```
> 
> Thanks,
> Davis Vaughan
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list