From j@g@nmn2 @end|ng |rom gm@||@com  Thu Nov  9 16:51:43 2023
From: j@g@nmn2 @end|ng |rom gm@||@com (Mikael Jagan)
Date: Thu, 9 Nov 2023 10:51:43 -0500
Subject: [Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
In-Reply-To: <25932.38029.55724.624739@stat.math.ethz.ch>
References: <mailman.53872.7.1699354802.63488.r-devel@r-project.org>
 <9a9a13d5-c0dd-4f6e-a379-be0c934fb31c@gmail.com>
 <25932.38029.55724.624739@stat.math.ethz.ch>
Message-ID: <cf6874e6-6219-4fd5-b378-b88ea554734f@gmail.com>



On 2023-11-09 3:13 am, Martin Maechler wrote:
>>>>>> Mikael Jagan
>>>>>>      on Wed, 8 Nov 2023 11:13:18 -0500 writes:
> 
>      > So, to summarize, the open questions are:
>      > (1) Should as.complex(NA_character_) give complex(r=NA_real_, i=0)
>      > instead of NA_complex_?
> 
>      > (2) Should the first argument in c(NA, x) and c(NA_integer_, x),
>      > where typeof(x) == "complex", be promoted to complex(r=NA_real_, i=0)
>      > instead of NA_complex_?
> 
>      > My opinions:
> 
>      > (1) No.  The imaginary part of the result of parsing the strings "<b>i",
>      > "<a>+<b>i", and "<a>-<b>i" can be nonzero.
>      > Consider, e.g., Im(eval(str2lang("0+1i"))) and Im(as.complex("0+1i")).
>      > If NA_character_ means "a string with unknown content", then we should
>      > not assume that the string is parsed as a real number.
> 
>      > (2) Yes.  I'd very much like to preserve the identity of c(Im(NA), Im(x))
>      > and Im(c(NA, x)) for atomic (excluding raw, character) vectors 'x'.
> 
>      > And while typing this response I noticed the following in current R-devel and
>      > current R-patched:
> 
>      >> 0+1i
>      > [1] 0+1i
>      >> 1i
>      > [1] 0+1i
>      >> as.complex("0+1i")
>      > [1] 0+1i
>      >> as.complex("1i")
>      > [1] NA
>      > Warning message:
>      > NAs introduced by coercion
> 
>      > That warning seems wrong to me ...
> 
> Well, actually, as we now have had the parser  accept
> 1i or 7i, 3.14i etc
> I think  that it's not the *warning* that is wrong,
> but rather the *result* :
> 

Indeed.  I realized immediately that I had mistyped, and hoped that readers
would understand what I meant.  Yes, as.complex("1i") ought to give 1i and
_not_ NA.

Mikael

> Why should   as.complex("1i")  be different  from  one of these?
> 
>> 1i
> [1] 0+1i
>> str2lang("1i")
> [1] 0+1i
>> scan(textConnection("1i"), complex())
> Read 1 item
> [1] 0+1i
>>
> 
> 
>      > Mikael
> 
>      > On 2023-11-07 6:00 am, r-devel-request at r-project.org wrote:
>      >>>>>>> Michael Chirico
>      >>>>>>> on Mon, 6 Nov 2023 23:18:40 -0800 writes:
>      >> > Thanks Martin. My hang-up was not on what the outcome of as.complex(NA)
>      >> > should be, but rather, how I should read code like c(x, y) generally. Till
>      >> > now, I have thought of it like 'c(x, y)' is c(as(x, typeof(y)), y)` when
>      >> > "type(y) > type(x)". Basically in my mind, "coercion" in R <->
>      >> > as.<newtype>(.) (or coerceVector() in C).
>      >>
>      >> > So I tracked down the source (which admittedly has been this way for much
>      >> > longer than the present discussion) to see what exactly c() is doing in
>      >> > this case:
>      >>
>      >> >https://github.com/r-devel/r-svn/blob/71e7480b07767f3b7d5c45a4247959aa4d83d910/src/main/bind.c#L418-L425
>      >>
>      >> > And indeed! It's not "coercion" in the sense I just described... there's a
>      >> > branch for the 'x == NA_LOGICAL' case to_convert_  to NA_complex_.
>      >>
>      >> Yes; "of course" ... still, I did not answer your main question,
>      >> as you did ask +/-  if  c() should not get an adjustment to the
>      >> new  as.complex(<numeric-alike>)  |-->  (Re = NA, Im = 0)
>      >> behavior.
>      >>
>      >> And that is still a valid open question. ... contrary to what I
>      >> wrote yesterday; sorry for that "answering a different
>      >> question".
>      >>
>      >> Martin
>      >>
>      >>
>      >> > On Mon, Nov 6, 2023 at 3:08?AM Martin Maechler<maechler at stat.math.ethz.ch>
>      >> > wrote:
>      >>
>      >> >> >>>>> Michael Chirico
>      >> >> >>>>>     on Sun, 5 Nov 2023 09:41:42 -0800 writes:
>      >> >>
>      >> >> > This is another follow-up to the thread from September
>      >> >> > "Recent changes to as.complex(NA_real_)".
>      >> >>
>      >> >> > A test in data.table was broken by the changes for NA
>      >> >> > coercion to complex; the breakage essentially comes from
>      >> >>
>      >> >> > c(NA, 0+1i)
>      >> >> > # vs
>      >> >> > c(as.complex(NA), 0+1i)
>      >> >>
>      >> >> > The former is the output we tested against; the latter is
>      >> >> essentially (via
>      >> >> > coerceVector() in C) what's generated by our data.table::shift()
>      >> >>
>      >> >> > However, these are now (r85472) different:
>      >> >>
>      >> >> > Im(c(NA, 0+1i))
>      >> >> > # [1] NA  1
>      >> >> > Im(c(as.complex(NA), 0+1i))
>      >> >> > # [1] 0 1
>      >> >>
>      >> >>
>      >> >> > The former matches the behavior of directly using NA_complex_:
>      >> >>
>      >> >> > Im(c(NA_complex_, 0+1i))
>      >> >> > # [1] NA  1
>      >> >>
>      >> >> > On R4.3.2, they both match the NA_complex_ behavior:
>      >> >> > Im(c(NA, 0+1i))
>      >> >> > # [1] NA  1
>      >> >> > Im(c(as.complex(NA), 0+1i))
>      >> >> > # [1] NA 1
>      >> >>
>      >> >> > Is this intended behavior, does something need to be updated for c()
>      >> >> as
>      >> >> > well?
>      >> >>
>      >> >> > Certainly it's messing with my understanding of how c() behaves,
>      >> >> e.g. in ?c
>      >> >>
>      >> >> >> All arguments are coerced to a common type which is the type of the
>      >> >> > returned value
>      >> >>
>      >> >> I think you have confused yourself, and everything behaves as expected:
>      >> >>
>      >> >> As we now have (in R-devel, since {r85233 | maechler | 2023-09-29 })
>      >> >>
>      >> >> ? ?as.complex(x)? now returns ?complex(real=x, imaginary=0)?
>      >> >> for_all_  numerical and logical ?x?, notably also for ?NA?
>      >> >> or ?NA_integer_?.
>      >> >>
>      >> >> ==> as.complex(NA) is indeed  complex(real = NA, imaginary = 0)
>      >> >>
>      >> >> And now, in your
>      >> >>
>      >> >> c(as.complex(NA), 0+1i)
>      >> >>
>      >> >> you are calling c() on two complex numbers, i.e., there is*no*  coercion
>      >> >> (and c(.) is rather "trivial"),  and the same is true for
>      >> >>
>      >> >> c(NA_complex_, 0+1i)
>      >> >>
>      >> >>
>      >> >> However, in 85233, I had only modified & added examples to  ?as.complex,
>      >> >> and now have added more (corresponding to the above NEWS entry);
>      -> svn rev 85475
>      >> >>
>      >> >> .............
>      >> >>
>      >> >> The underlying "dilemma" that nobody can help us with is that
>      >> >> "almost infinitely" many different complex numbers z fulfill
>      >> >> is.na(z) |--> TRUE
>      >> >> and only one of them is  NA_complex_  and that may be unintuitive.
>      >> >>
>      >> >> OTOH, we already have for the doubles that there are at least two
>      >> >> different x fulfulling is.na(x), namely  NaN and NA
>      >> >> and from C's point of view there are even considerably more
>      >> >> different NaN's .. but now I'm definitely digressing.
>      >> >>
>      >> >> Martin
>      >> >>



[Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
Mikael Jagan