From murdoch@dunc@n @end|ng |rom gm@||@com  Fri Sep 22 22:43:43 2023
From: murdoch@dunc@n @end|ng |rom gm@||@com (Duncan Murdoch)
Date: Fri, 22 Sep 2023 16:43:43 -0400
Subject: [Rd] Recent changes to as.complex(NA_real_)
In-Reply-To: <4abe101e-55be-8800-31ee-e0414c89740e@gmail.com>
References: <1cf40db9-ea70-483a-a547-270da6926935@gmail.com>
 <25869.28353.595831.807741@stat.math.ethz.ch>
 <4abe101e-55be-8800-31ee-e0414c89740e@gmail.com>
Message-ID: <57f77592-26ad-43dd-8e36-f9989c915308@gmail.com>

Since the result of is.na(x) is the same on each of those, I don't see a 
problem.  As long as that is consistent, I don't see a problem.  You 
shouldn't be using any other test for NA-ness.  You should never be 
expecting identical() to treat different types as the same (e.g. 
identical(NA, NA_real_) is FALSE, as it should be).  If you are using a 
different test, that's user error.

Duncan Murdoch

On 22/09/2023 2:41 p.m., Herv? Pag?s wrote:
> We could also question the value of having an infinite number of NA
> representations in the complex space. For example all these complex
> values are displayed the same way (as NA), are considered NAs by
> is.na(), but are not identical or semantically equivalent (from an Re()
> or Im() point of view):
> 
>   ??? NA_real_ + 0i
> 
>   ??? complex(r=NA_real_, i=Inf)
> 
>   ??? complex(r=2, i=NA_real_)
> 
>   ??? complex(r=NaN, i=NA_real_)
> 
> In other words, using a single representation for complex NA (i.e.
> complex(r=NA_real_, i=NA_real_)) would avoid a lot of unnecessary
> complications and surprises.
> 
> Once you do that, whether as.complex(NA_real_) should return
> complex(r=NA_real_, i=0) or complex(r=NA_real_, i=NA_real_) becomes a
> moot point.
> 
> Best,
> 
> H.
> 
> On 9/22/23 03:38, Martin Maechler wrote:
>>>>>>> Mikael Jagan
>>>>>>>       on Thu, 21 Sep 2023 00:47:39 -0400 writes:
>>       > Revisiting this thread from April:
>>
>>       >https://stat.ethz.ch/pipermail/r-devel/2023-April/082545.html
>>
>>       > where the decision (not yet backported) was made for
>>       > as.complex(NA_real_) to give NA_complex_ instead of
>>       > complex(r=NA_real_, i=0), to be consistent with
>>       > help("as.complex") and as.complex(NA) and as.complex(NA_integer_).
>>
>>       > Was any consideration given to the alternative?
>>       > That is, to changing as.complex(NA) and as.complex(NA_integer_) to
>>       > give complex(r=NA_real_, i=0), consistent with
>>       > as.complex(NA_real_), then amending help("as.complex")
>>       > accordingly?
>>
>> Hmm, as, from R-core, mostly I was involved, I admit to say "no",
>> to my knowledge the (above) alternative wasn't considered.
>>
>>     > The principle that
>>     > Im(as.complex(<real=(double|integer|logical)>)) should be zero
>>     > is quite fundamental, in my view, hence the "new" behaviour
>>     > seems to really violate the principle of least surprise ...
>>
>> of course "least surprise"  is somewhat subjective.  Still,
>> I clearly agree that the above would be one desirable property.
>>
>> I think that any solution will lead to *some* surprise for some
>> cases, I think primarily because there are *many* different
>> values z  for which  is.na(z)  is true,  and in any case
>> NA_complex_  is only of the many.
>>
>> I also agree with Mikael that we should reconsider the issue
>> that was raised by Davis Vaughan here ("on R-devel") last April.
>>
>>       > Another (but maybe weaker) argument is that
>>       > double->complex coercions happen more often than
>>       > logical->complex and integer->complex ones.  Changing the
>>       > behaviour of the more frequently performed coercion is
>>       > more likely to affect code "out there".
>>
>>       > Yet another argument is that one expects
>>
>>       >      identical(as.complex(NA_real_), NA_real_ + (0+0i))
>>
>>       > to be TRUE, i.e., that coercing from double to complex is
>>       > equivalent to adding a complex zero.  The new behaviour
>>       > makes the above FALSE, since NA_real_ + (0+0i) gives
>>       > complex(r=NA_real_, i=0).
>>
>> No!  --- To my own surprise (!) --- in current R-devel the above is TRUE,
>> and
>>         NA_real_ + (0+0i)  , the same as
>>         NA_real_ + 0i      , really gives  complex(r=NA, i=NA) :
>>
>> Using showC() from ?complex
>>
>>     showC <- function(z) noquote(sprintf("(R = %g, I = %g)", Re(z), Im(z)))
>>
>> we see (in R-devel) quite consistently
>>
>>> showC(NA_real_ + 0i)
>> [1] (R = NA, I = NA)
>>> showC(NA       + 0i)  # NA is 'logical'
>> [1] (R = NA, I = NA)
>> where as in R 4.3.1 and "R-patched" -- *in*consistently
>>
>>> showC(NA_real_ + 0i)
>> [1] (R = NA, I = 0)
>>> showC(NA + 0i)
>> [1] (R = NA, I = NA)
>> .... and honestly, I do not see *where* (and when) we changed
>> the underlying code (in arithmetic.c !?)  in R-devel to *also*
>> produce  NA_complex_  in such complex *arithmetic*
>>
>>
>>       > Having said that, one might also (but more naively) expect
>>
>>       >     identical(as.complex(as.double(NA_complex_)), NA_complex_)
>>
>>       > to be TRUE.
>>
>> as in current R-devel
>>
>>       > Under my proposal it continues to be FALSE.
>>
>> as in "R-release"
>>
>>       > Well, I'd prefer if it gave FALSE with a warning
>>       > "imaginary parts discarded in coercion", but it seems that
>>       > as.double(complex(r=a, i=b)) never warns when either of
>>       > 'a' and 'b' is NA_real_ or NaN, even where "information"
>>       > {nonzero 'b'} is clearly lost ...
>>
>> The question of *warning* here is related indeed, but I think
>> we should try to look at it only *secondary* to your first
>> proposal.
>>
>>       > Whatever decision is made about as.complex(NA_real_),
>>       > maybe these points should be weighed before it becomes part of
>>       > R-release ...
>>
>>       > Mikael
>>
>> Indeed.
>>
>> Can we please get other opinions / ideas here?
>>
>> Thank you in advance for your thoughts!
>> Martin
>>
>> ---
>>
>> PS:
>>
>>    Our *print()*ing  of complex NA's ("NA" here meaning NA or NaN)
>>    is also unsatisfactory, e.g. in the case where all entries of a
>>    vector are NA in the sense of is.na(.), but their
>>    Re() and Im() are not all NA:
>>    
>>     showC <- function(z) noquote(sprintf("(R = %g, I = %g)", Re(z), Im(z)))
>>     z <- complex(, c(11, NA, NA), c(NA, 99, NA))
>>     z
>>     showC(z)
>>
>> gives
>>
>>     > z
>>     [1] NA NA NA
>>     > showC(z)
>>     [1] (R = 11, I = NA) (R = NA, I = 99) (R = NA, I = NA)
>>
>> but that (printing of complex) *is* another issue,
>> in which we have the re-opened bugzilla PR#16752
>>       ==>https://bugs.r-project.org/show_bug.cgi?id=16752
>>
>> on which we also worked during the R Sprint in Warwick three
>> weeks ago, and where I want to commit changes in any case {but
>> think we should change even a bit more than we got to during the
>> Sprint}.
>>
>> ______________________________________________
>> R-devel at r-project.org  mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] Recent changes to as.complex(NA_real_)
Duncan Murdoch