[Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Thu Nov 9 09:13:01 CET 2023
>>>>> 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* :
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 using 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 using 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
>> >>
More information about the R-devel
mailing list