Martin Maechler
2023-Nov-06 11:08 UTC
[Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
>>>>> 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
Michael Chirico
2023-Nov-07 07:18 UTC
[Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
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_. 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 >[[alternative HTML version deleted]]
Seemingly Similar Threads
- c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
- c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
- c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
- c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
- c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?