From m@ech|er @end|ng |rom @t@t@m@th@ethz@ch  Tue Nov  7 09:26:15 2023
From: m@ech|er @end|ng |rom @t@t@m@th@ethz@ch (Martin Maechler)
Date: Tue, 7 Nov 2023 09:26:15 +0100
Subject: [Rd] c(NA, 0+1i) not the same as c(as.complex(NA), 0+1i)?
In-Reply-To: <9BE84B0E-A8D3-44E5-96BC-692B57B78A73@gmail.com>
References: <CAPRVBcx4OxpWDH_cyunMfZ=eLhQCD3V62ka1yQV4y5jCoEXL6A@mail.gmail.com>
 <9BE84B0E-A8D3-44E5-96BC-692B57B78A73@gmail.com>
Message-ID: <25929.62631.316066.852606@stat.math.ethz.ch>

>>>>> peter dalgaard 
>>>>>     on Mon, 6 Nov 2023 11:59:51 +0100 writes:

    > Hmm, it is not actually at odds with help(c), it is just that the autocoercion works different that it used to, so that
    > as.complex(NA) == as.complex(NA_real) == NA_real_+0i)

    > which now differs from

    > NA_complex 

    > although both print as NA.

    > I haven't been quite alert when this change was discussed,

The discussion was here, at first
1) started by Davis Vaughan on  14 Apr 2023
   "[Rd] Possible inconsistency between `as.complex(NA_real_)` and the docs", 
   https://stat.ethz.ch/pipermail/r-devel/2023-April/082545.html
   to which I replied, and then committed (r84322), with msg  'as.complex(NA_real_) |=> NA_complex_'

2) A couple of months later,  21 Sep 2023,
   an R-devel thread started by Mikael Jagan  "[Rd] Recent changes to as.complex(NA_real_)",
   https://stat.ethz.ch/pipermail/r-devel/2023-September/082864.html

   a discussion that took several iterations and lead to the
   reversal of the April change and rather have integer and
   logical *also* behave as real/double had before (and in all released R versions).
   This lead to the much more recent change (r85233) with msg
       'as.complex(NA_{real,integer,logical}) now keeps imaginary part zero'




    > but it does look a bit unfortunate that usage patterns like c(NA, 0+1i) does not give complex NA for the 1st component, effectively changing the interpretation from "I don't know what this is" to "I don't know what this is but I'm sure it is on the real line".

    > Also, notice that things like 

    >> Im(scan(text= "NA 0+1i", what=complex()))
    > Read 2 items
    > [1] NA  1

    > and

    >> Im(as.complex(c(NA,"0+1i")))
    > [1] NA  1

    > but Martin probably thought more deeply about this?

    > -pd


Yes,  I have been aware that   NA_character_  has now been the
only atomic type that would still  coerce to NA_complex_
{there is no NA_raw_ for good reasons}.

More context:  In R version from 3.3? (definitely 3.5.x) to 4.3.x  we have had

   > pz <- function(z) noquote(paste0("(", Re(z), ",", Im(z), ")"))
   > pz(as.complex(NA_character_))
   [1] (NA,NA)
   > pz(as.complex(NA)) # NA is logical
   [1] (NA,NA)
   > pz(as.complex(NA_integer_))
   [1] (NA,NA)
   > pz(as.complex(NA_real_))
   [1] (NA,0)
   > 

So the double/real  behaviour has been the exception.

Currently in R-devel, integer and logical behave like double:

   > pz <- function(z) noquote(paste0("(", Re(z), ",", Im(z), ")"))
   > pz(as.complex(NA_character_))
   [1] (NA,NA)
   > pz(as.complex(NA)) # NA is logical
   [1] (NA,0)
   > pz(as.complex(NA_integer_))
   [1] (NA,0)
   > pz(as.complex(NA_real_))
   [1] (NA,0)
   > 

which makes much more sense, as this (integer & logical, treated
as numbers behave the same as double)  is a prinicple in R
almost everywhere.

We could well look into also changing the
as.complex(NA_character_)

Martin

    >> On 5 Nov 2023, at 18:41 , Michael Chirico <michaelchirico4 at gmail.com> wrote:
    >> 
    >> 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
    >> 
    >> [[alternative HTML version deleted]]
    >> 
    >> ______________________________________________
    >> R-devel at r-project.org mailing list
    >> https://stat.ethz.ch/mailman/listinfo/r-devel

    > -- 
    > Peter Dalgaard, Professor,
    > Center for Statistics, Copenhagen Business School
    > Solbjerg Plads 3, 2000 Frederiksberg, Denmark
    > Phone: (+45)38153501
    > Office: A 4.23
    > Email: pd.mes at cbs.dk  Priv: PDalgd at gmail.com



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