Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-28 Thread Martin Maechler
> Martin Maechler 
> on Thu, 28 Sep 2023 12:11:27 +0200 writes:

> Gregory R Warnes 
> on Sat, 23 Sep 2023 13:22:35 -0400 writes:

> > It sounds like we need to add arguments (with sensible
> > defaults) to complex(), Re(), Im(), is.na.complex() etc to
> > allow the user to specify the desired behavior.
> 
> I don't think I'd like such extra flexibility for all these, 
> ... ;-)  and even much less I'd like to be part of the group who
> then has to *maintain* such behavior ;-)
> 
[..]

> Currently, I'm actually tending to *simplify* things
> drastically, also because it means less surprises in the long
> term and much less code reading / debugging in formatting /
> printing and dealing with complex numbers.
> NB: there *is* the re-opened PR#16752,
> https://bugs.r-project.org/show_bug.cgi?id=16752
> where the investigation of the (C-level) R source is a major reason
> for my current thinking ..
> 
> What if we decided to really treat complex numbers much more
> than currently  as pairs of real (i.e. "double") numbers,
> notably also when print()ing them?
> Consequently, Re() and Im() would continue to return what they
> do now (contrary to Hervé's original proposal) also in case of
> non-finite numbers.
> 
> Of course, *no* change in arithmetic or other Ops (such as '==')
> nor  is.na(), is.finite(), is.nan(), etc.
> 
> The current formatting and printing of complex numbers is
> complicated in some cases unnecessarily inaccurate and in other
> cases unnecessarily *ugly*.
> I believe that formatting, we should change to basically format
> the (vector of) real parts and imaginary parts separately.
> E.g., it is really unnecessarily ugly to switch to exponential
> format for both Re and Im, in a situation like this:
> 
> > (-1):2 + 1i*1e99
> [1] 0e+00+1e+99i 0e+00+1e+99i 0e+00+1e+99i 0e+00+1e+99i
> 
> It is very ugly to use  exponential/scientific format for the Re()
> even if we'd fix the confusing and inaccurate *joint* rounding
> of Re and Im.

and then, I end with

> ... and indeed (as discusses here previously:
> While it makes some sense to print  NA
> identically for logical, integer and double,
> it seems often confusing *not* to show   + i
> in the complex case; where that *does* happen for
> Inf and NaN:
> 
>  > complex(, NA, ((-1):2))
>  [1] NA NA NA NA
>  > complex(, NaN, ((-1):2))
>  [1] NaN-1i NaN+0i NaN+1i NaN+2i
>  > complex(, c(-Inf,Inf), ((-1):2))
>  [1] -Inf-1i  Inf+0i -Inf+1i  Inf+2i
>  > 
> 
> where the first of these *does* keep the finite imaginary
> values, but does not show them
> 
> > (cN <- complex(, NA, ((-1):2))); rbind(Re(cN), Im(cN))
> [1] NA NA NA NA
>  [,1] [,2] [,3] [,4]
> [1,]   NA   NA   NA   NA
> [2,]   -1012
> >

where really, I think we should keep that behavior (*), at least
for now: Changing it as well *does* have a relatively large
impact, is not back-compatible with (the long history of) S and
R, *and* it complicates documentation and teaching unnecessarily.

Experts will now how to differentiate the different complex NAs,
e.g. by using a simple utilities such as {"format complex", "print complex"}

  fc <- function(z) paste0("(",Re(z), ",", Im(z),")")
  pc <- function(z) noquote(fc(z))

which I've used now for testing/"visualizing" different scenarios


Martin


---
*) simply printing 'NA' in cases where is.na(.) is true and is.nan(.) is false

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-28 Thread Martin Maechler
> Gregory R Warnes 
> on Sat, 23 Sep 2023 13:22:35 -0400 writes:

> It sounds like we need to add arguments (with sensible
> defaults) to complex(), Re(), Im(), is.na.complex() etc to
> allow the user to specify the desired behavior.

I don't think I'd like such extra flexibility for all these, 
... ;-)  and even much less I'd like to be part of the group who
then has to *maintain* such behavior ;-)

> --  
> Change your thoughts and you change the world.
> --Dr. Norman Vincent Peale

 ( .. *some* hybris from the last century ..)

Currently, I'm actually tending to *simplify* things
drastically, also because it means less surprises in the long
term and much less code reading / debugging in formatting /
printing and dealing with complex numbers.
NB: there *is* the re-opened PR#16752,
https://bugs.r-project.org/show_bug.cgi?id=16752
where the investigation of the (C-level) R source is a major reason
for my current thinking ..

What if we decided to really treat complex numbers much more
than currently  as pairs of real (i.e. "double") numbers,
notably also when print()ing them?
Consequently, Re() and Im() would continue to return what they
do now (contrary to Hervé's original proposal) also in case of
non-finite numbers.

Of course, *no* change in arithmetic or other Ops (such as '==')
nor  is.na(), is.finite(), is.nan(), etc.

The current formatting and printing of complex numbers is
complicated in some cases unnecessarily inaccurate and in other
cases unnecessarily *ugly*.
I believe that formatting, we should change to basically format
the (vector of) real parts and imaginary parts separately.
E.g., it is really unnecessarily ugly to switch to exponential
format for both Re and Im, in a situation like this:

> (-1):2 + 1i*1e99
[1] 0e+00+1e+99i 0e+00+1e+99i 0e+00+1e+99i 0e+00+1e+99i

It is very ugly to use  exponential/scientific format for the Re()
even if we'd fix the confusing and inaccurate *joint* rounding
of Re and Im.

... and indeed (as discusses here previously:
While it makes some sense to print  NA
identically for logical, integer and double,
it seems often confusing *not* to show   + i
in the complex case; where that *does* happen for
Inf and NaN:

 > complex(, NA, ((-1):2))
 [1] NA NA NA NA
 > complex(, NaN, ((-1):2))
 [1] NaN-1i NaN+0i NaN+1i NaN+2i
 > complex(, c(-Inf,Inf), ((-1):2))
 [1] -Inf-1i  Inf+0i -Inf+1i  Inf+2i
 > 

where the first of these *does* keep the finite imaginary
values, but does not show them

> (cN <- complex(, NA, ((-1):2))); rbind(Re(cN), Im(cN))
[1] NA NA NA NA
 [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   -1012
>

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-25 Thread Hervé Pagès


On 9/25/23 07:05, Martin Maechler wrote:
>> Hervé Pagès
>>  on Sat, 23 Sep 2023 16:52:21 -0700 writes:
>  > Hi Martin,
>  > On 9/23/23 06:43, Martin Maechler wrote:
>  >>> Hervé Pagès
>  >>> on Fri, 22 Sep 2023 16:55:05 -0700 writes:
>  >> > The problem is that you have things that are
>  >> > **semantically** different but look exactly the same:
>  >>
>  >> > They look the same:
>  >>
>  >> >> x
>  >> > [1] NA
>  >> >> y
>  >> > [1] NA
>  >> >> z
>  >> > [1] NA
>  >>
>  >> >> is.na(x)
>  >> > [1] TRUE
>  >> >> is.na(y)
>  >> > [1] TRUE
>  >> >> is.na(z)
>  >> > [1] TRUE
>  >>
>  >> >> str(x)
>  >> >   cplx NA
>  >> >> str(y)
>  >> >   num NA
>  >> >> str(z)
>  >> >   cplx NA
>  >>
>  >> > but they are semantically different e.g.
>  >>
>  >> >> Re(x)
>  >> > [1] NA
>  >> >> Re(y)
>  >> > [1] -0.5  # surprise!
>  >>
>  >> >> Im(x)  # surprise!
>  >> > [1] 2
>  >> >> Im(z)
>  >> > [1] NA
>  >>
>  >> > so any expression involving Re() or Im() will produce
>  >> > different results on input that look the same on the
>  >> > surface.
>  >>
>  >> > You can address this either by normalizing the internal
>  >> > representation of complex NA to always be complex(r=NaN,
>  >> > i=NA_real_), like for NA_complex_, or by allowing the
>  >> > infinite variations that are currently allowed and at the
>  >> > same time making sure that both Re() and Im()  always
>  >> > return NA_real_ on a complex NA.
>  >>
>  >> > My point is that the behavior of complex NA should be
>  >> > predictable. Right now it's not. Once it's predictable
>  >> > (with Re() and Im() both returning NA_real_ regardless of
>  >> > internal representation), then it no longer matters what
>  >> > kind of complex NA is returned by as.complex(NA_real_),
>  >> > because they are no onger distinguishable.
>  >>
>  >> > H.
>  >>
>  >> > On 9/22/23 13:43, Duncan Murdoch wrote:
>  >> >> 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.
>  >>
>  >> Thank you, Hervé.
>  >> Your proposition is yet another one,
>  >> to declare that all complex NA's should be treated as identical
>  >> (almost/fully?) everywhere.
>  >>
>  >> This would be a possibility, but I think a drastic one.
>  >>
>  >> I think there are too many cases, where I want to keep the
>  >> information of the real part independent of the values of the
>  >> imaginary part (e.g. think of the Riemann hypothesis), and
>  >> typically vice versa.
>  > Use NaN for that, not NA.
>
> Aa..h, *that* is your point.
>
> Well, I was on exactly this line till a few years ago.
>
> However, very *sadly* to me, note howexample(complex)
> nowadays ends :
>
> ##
>   showC <- function(z) noquote(sprintf("(R = %g, I = %g)", Re(z), Im(z)))
>   
>   ## The exact result of this *depends* on the platform, compiler, 
> math-library:
>   (NpNA <- NaN + NA_complex_) ; str(NpNA) # *behaves* as 'cplx NA' ..
>   stopifnot(is.na(NpNA), is.na(NA_complex_), is.na(Re(NA_complex_)), 
> is.na(Im(NA_complex_)))
>   showC(NpNA)# but 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-25 Thread Martin Maechler
> Hervé Pagès 
> on Sat, 23 Sep 2023 16:52:21 -0700 writes:

> Hi Martin,
> On 9/23/23 06:43, Martin Maechler wrote:
>>> Hervé Pagès
>>> on Fri, 22 Sep 2023 16:55:05 -0700 writes:
>> > The problem is that you have things that are
>> > **semantically** different but look exactly the same:
>> 
>> > They look the same:
>> 
>> >> x
>> > [1] NA
>> >> y
>> > [1] NA
>> >> z
>> > [1] NA
>> 
>> >> is.na(x)
>> > [1] TRUE
>> >> is.na(y)
>> > [1] TRUE
>> >> is.na(z)
>> > [1] TRUE
>> 
>> >> str(x)
>> >   cplx NA
>> >> str(y)
>> >   num NA
>> >> str(z)
>> >   cplx NA
>> 
>> > but they are semantically different e.g.
>> 
>> >> Re(x)
>> > [1] NA
>> >> Re(y)
>> > [1] -0.5  # surprise!
>> 
>> >> Im(x)  # surprise!
>> > [1] 2
>> >> Im(z)
>> > [1] NA
>> 
>> > so any expression involving Re() or Im() will produce
>> > different results on input that look the same on the
>> > surface.
>> 
>> > You can address this either by normalizing the internal
>> > representation of complex NA to always be complex(r=NaN,
>> > i=NA_real_), like for NA_complex_, or by allowing the
>> > infinite variations that are currently allowed and at the
>> > same time making sure that both Re() and Im()  always
>> > return NA_real_ on a complex NA.
>> 
>> > My point is that the behavior of complex NA should be
>> > predictable. Right now it's not. Once it's predictable
>> > (with Re() and Im() both returning NA_real_ regardless of
>> > internal representation), then it no longer matters what
>> > kind of complex NA is returned by as.complex(NA_real_),
>> > because they are no onger distinguishable.
>> 
>> > H.
>> 
>> > On 9/22/23 13:43, Duncan Murdoch wrote:
>> >> 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.
>> 
>> Thank you, Hervé.
>> Your proposition is yet another one,
>> to declare that all complex NA's should be treated as identical
>> (almost/fully?) everywhere.
>> 
>> This would be a possibility, but I think a drastic one.
>> 
>> I think there are too many cases, where I want to keep the
>> information of the real part independent of the values of the
>> imaginary part (e.g. think of the Riemann hypothesis), and
>> typically vice versa.
> Use NaN for that, not NA.

Aa..h, *that* is your point.

Well, I was on exactly this line till a few years ago.

However, very *sadly* to me, note howexample(complex)
nowadays ends :

##
 showC <- function(z) noquote(sprintf("(R = %g, I = %g)", Re(z), Im(z)))
 
 ## The exact result of this *depends* on the platform, compiler, math-library:
 (NpNA <- NaN + NA_complex_) ; str(NpNA) # *behaves* as 'cplx NA' ..
 stopifnot(is.na(NpNA), is.na(NA_complex_), is.na(Re(NA_complex_)), 
is.na(Im(NA_complex_)))
 showC(NpNA)# but does not always show '(R = NaN, I = NA)'
 ## and this is not TRUE everywhere:
 identical(NpNA, NA_complex_)
 showC(NA_complex_) # always == (R = NA, I = NA)
##

Unfortunately --- notably by the appearance of the new (M1, M1 pro, M2, ...)
processors, but not only ---
I (and others, but the real experts) have wrongly assumed  that
NA 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-23 Thread Hervé Pagès
Hi Martin,

On 9/23/23 06:43, Martin Maechler wrote:
>> Hervé Pagès
>>  on Fri, 22 Sep 2023 16:55:05 -0700 writes:
>  > The problem is that you have things that are
>  > **semantically** different but look exactly the same:
>
>  > They look the same:
>
>  >> x
>  > [1] NA
>  >> y
>  > [1] NA
>  >> z
>  > [1] NA
>
>  >> is.na(x)
>  > [1] TRUE
>  >> is.na(y)
>  > [1] TRUE
>  >> is.na(z)
>  > [1] TRUE
>
>  >> str(x)
>  >   cplx NA
>  >> str(y)
>  >   num NA
>  >> str(z)
>  >   cplx NA
>
>  > but they are semantically different e.g.
>
>  >> Re(x)
>  > [1] NA
>  >> Re(y)
>  > [1] -0.5  # surprise!
>
>  >> Im(x)  # surprise!
>  > [1] 2
>  >> Im(z)
>  > [1] NA
>
>  > so any expression involving Re() or Im() will produce
>  > different results on input that look the same on the
>  > surface.
>
>  > You can address this either by normalizing the internal
>  > representation of complex NA to always be complex(r=NaN,
>  > i=NA_real_), like for NA_complex_, or by allowing the
>  > infinite variations that are currently allowed and at the
>  > same time making sure that both Re() and Im()  always
>  > return NA_real_ on a complex NA.
>
>  > My point is that the behavior of complex NA should be
>  > predictable. Right now it's not. Once it's predictable
>  > (with Re() and Im() both returning NA_real_ regardless of
>  > internal representation), then it no longer matters what
>  > kind of complex NA is returned by as.complex(NA_real_),
>  > because they are no onger distinguishable.
>
>  > H.
>
>  > On 9/22/23 13:43, Duncan Murdoch wrote:
>  >> 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.
>
> Thank you, Hervé.
> Your proposition is yet another one,
> to declare that all complex NA's should be treated as identical
> (almost/fully?) everywhere.
>
> This would be a possibility, but I think a drastic one.
>
> I think there are too many cases, where I want to keep the
> information of the real part independent of the values of the
> imaginary part (e.g. think of the Riemann hypothesis), and
> typically vice versa.
Use NaN for that, not NA.
>
> With your proposal, for a (potentially large) vector of complex numbers,
> after
>Re(z)  <-  1/2
>
> I could no longer rely on   Re(z) == 1/2,
> because it would be wrong for those z where (the imaginary part/ the number)
> was NA/NaN.

My proposal is to do this only if the Re and/or Im parts are NAs, not if 
they are NaNs.

BTW the difference between how NAs and NaNs are treated in complex 
vectors is another issue that adds to the confusion:

   > complex(r=NA, i=2)
   [1] NA
   > complex(r=NaN, i=2)
   [1] NaN+2i

Not displaying the real + imaginary parts in the NA case kind of 
suggests that somehow they are gone i.e. that Re(z) and Im(z) are both NA.

Note that my proposal is not to change the display but to change Re() 
and Im() to make them consistent with the display.

In your Re(z) <- 1/2 example (which seems to be theoretical only because 
I don't see `Re<-` in base R), any NA in 'z' would be replaced with 
complex(r=NaN, i=1/2), so you could rely on Re(z) == 1/2.

> Also, in a similar case, a
>
>Im(z) <- NA
>
> would have to "destroy" all real parts  Re(z);
> not really typically in memory, but effectively for the user,  Re(z)
> would be all NA/NaN.
Yes, setting a 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-23 Thread Gregory R. Warnes
It sounds like we need to add arguments (with sensible defaults) to complex(), 
Re(), Im(), is.na.complex() etc to allow the user to specify the desired 
behavior.

--  
Change your thoughts and you change the world.
--Dr. Norman Vincent Peale

> On Sep 23, 2023, at 12:37 PM, Mikael Jagan  wrote:
> 
> 
> 
> On 2023-09-23 9:43 am, Martin Maechler wrote:
>>> Hervé Pagès
>>> on Fri, 22 Sep 2023 16:55:05 -0700 writes:
>> > The problem is that you have things that are
>> > **semantically** different but look exactly the same:
>> > They look the same:
>> >> x
>> > [1] NA
>> >> y
>> > [1] NA
>> >> z
>> > [1] NA
>> >> is.na(x)
>> > [1] TRUE
>> >> is.na(y)
>> > [1] TRUE
>> >> is.na(z)
>> > [1] TRUE
>> >> str(x)
>> >   cplx NA
>> >> str(y)
>> >   num NA
>> >> str(z)
>> >   cplx NA
>> > but they are semantically different e.g.
>> >> Re(x)
>> > [1] NA
>> >> Re(y)
>> > [1] -0.5  # surprise!
>> >> Im(x)  # surprise!
>> > [1] 2
>> >> Im(z)
>> > [1] NA
>> > so any expression involving Re() or Im() will produce
>> > different results on input that look the same on the
>> > surface.
>> > You can address this either by normalizing the internal
>> > representation of complex NA to always be complex(r=NaN,
>> > i=NA_real_), like for NA_complex_, or by allowing the
>> > infinite variations that are currently allowed and at the
>> > same time making sure that both Re() and Im()  always
>> > return NA_real_ on a complex NA.
>> > My point is that the behavior of complex NA should be
>> > predictable. Right now it's not. Once it's predictable
>> > (with Re() and Im() both returning NA_real_ regardless of
>> > internal representation), then it no longer matters what
>> > kind of complex NA is returned by as.complex(NA_real_),
>> > because they are no onger distinguishable.
>> > H.
>> > On 9/22/23 13:43, Duncan Murdoch wrote:
>> >> 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.
>> Thank you, Hervé.
>> Your proposition is yet another one,
>> to declare that all complex NA's should be treated as identical
>> (almost/fully?) everywhere.
>> This would be a possibility, but I think a drastic one.
>> I think there are too many cases, where I want to keep the
>> information of the real part independent of the values of the
>> imaginary part (e.g. think of the Riemann hypothesis), and
>> typically vice versa.
>> With your proposal, for a (potentially large) vector of complex numbers,
>> after
>>   Re(z)  <-  1/2
>> I could no longer rely on   Re(z) == 1/2,
>> because it would be wrong for those z where (the imaginary part/ the number)
>> was NA/NaN.
>> Also, in a similar case, a
>>   Im(z) <- NA
>> would have to "destroy" all real parts  Re(z);
>> not really typically in memory, but effectively for the user,  Re(z)
>> would be all NA/NaN.
>> And I think there are quite a few other situations
>> where looking at Re() and Im() separately makes a lot of sense.
> 
> Indeed, and there is no way to "tell" BLAS and LAPACK to treat both the real 
> and
> imaginary parts as NA_REAL when either is NA_REAL.  Hence the only reliable 
> way
> to implement such a proposal would be to post-process the result of any
> computation returning a complex type, testing for NA_REAL and setting both 
> parts
> to NA_REAL in that case.  My expectation is that such 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-23 Thread Mikael Jagan




On 2023-09-23 9:43 am, Martin Maechler wrote:

Hervé Pagès
 on Fri, 22 Sep 2023 16:55:05 -0700 writes:


 > The problem is that you have things that are
 > **semantically** different but look exactly the same:

 > They look the same:

 >> x
 > [1] NA
 >> y
 > [1] NA
 >> z
 > [1] NA

 >> is.na(x)
 > [1] TRUE
 >> is.na(y)
 > [1] TRUE
 >> is.na(z)
 > [1] TRUE

 >> str(x)
 >   cplx NA
 >> str(y)
 >   num NA
 >> str(z)
 >   cplx NA

 > but they are semantically different e.g.

 >> Re(x)
 > [1] NA
 >> Re(y)
 > [1] -0.5  # surprise!

 >> Im(x)  # surprise!
 > [1] 2
 >> Im(z)
 > [1] NA

 > so any expression involving Re() or Im() will produce
 > different results on input that look the same on the
 > surface.

 > You can address this either by normalizing the internal
 > representation of complex NA to always be complex(r=NaN,
 > i=NA_real_), like for NA_complex_, or by allowing the
 > infinite variations that are currently allowed and at the
 > same time making sure that both Re() and Im()  always
 > return NA_real_ on a complex NA.

 > My point is that the behavior of complex NA should be
 > predictable. Right now it's not. Once it's predictable
 > (with Re() and Im() both returning NA_real_ regardless of
 > internal representation), then it no longer matters what
 > kind of complex NA is returned by as.complex(NA_real_),
 > because they are no onger distinguishable.

 > H.

 > On 9/22/23 13:43, Duncan Murdoch wrote:
 >> 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.

Thank you, Hervé.
Your proposition is yet another one,
to declare that all complex NA's should be treated as identical
(almost/fully?) everywhere.

This would be a possibility, but I think a drastic one.

I think there are too many cases, where I want to keep the
information of the real part independent of the values of the
imaginary part (e.g. think of the Riemann hypothesis), and
typically vice versa.

With your proposal, for a (potentially large) vector of complex numbers,
after
   Re(z)  <-  1/2

I could no longer rely on   Re(z) == 1/2,
because it would be wrong for those z where (the imaginary part/ the number)
was NA/NaN.
Also, in a similar case, a

   Im(z) <- NA

would have to "destroy" all real parts  Re(z);
not really typically in memory, but effectively for the user,  Re(z)
would be all NA/NaN.

And I think there are quite a few other situations
where looking at Re() and Im() separately makes a lot of sense.


Indeed, and there is no way to "tell" BLAS and LAPACK to treat both the real and
imaginary parts as NA_REAL when either is NA_REAL.  Hence the only reliable way
to implement such a proposal would be to post-process the result of any
computation returning a complex type, testing for NA_REAL and setting both parts
to NA_REAL in that case.  My expectation is that such testing would drastically
slow down basic arithmetic and algebraic operations ...

Mikael



Spencer also made a remark in this direction.

All in all I'd be very reluctant to move in this direction;
but yes, I'm just one person ... let's continue musing and
considering !

Martin

 >>> 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:
 
  

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-23 Thread Martin Maechler
> Hervé Pagès 
> on Fri, 22 Sep 2023 16:55:05 -0700 writes:

> The problem is that you have things that are
> **semantically** different but look exactly the same:

> They look the same:

>> x
> [1] NA
>> y
> [1] NA
>> z
> [1] NA

>> is.na(x)
> [1] TRUE
>> is.na(y)
> [1] TRUE
>> is.na(z)
> [1] TRUE

>> str(x)
>   cplx NA
>> str(y)
>   num NA
>> str(z)
>   cplx NA

> but they are semantically different e.g.

>> Re(x)
> [1] NA
>> Re(y)
> [1] -0.5  # surprise!

>> Im(x)  # surprise!
> [1] 2
>> Im(z)
> [1] NA

> so any expression involving Re() or Im() will produce
> different results on input that look the same on the
> surface.

> You can address this either by normalizing the internal
> representation of complex NA to always be complex(r=NaN,
> i=NA_real_), like for NA_complex_, or by allowing the
> infinite variations that are currently allowed and at the
> same time making sure that both Re() and Im()  always
> return NA_real_ on a complex NA.

> My point is that the behavior of complex NA should be
> predictable. Right now it's not. Once it's predictable
> (with Re() and Im() both returning NA_real_ regardless of
> internal representation), then it no longer matters what
> kind of complex NA is returned by as.complex(NA_real_),
> because they are no onger distinguishable.

> H.

> On 9/22/23 13:43, Duncan Murdoch wrote:
>> 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.

Thank you, Hervé.
Your proposition is yet another one,
to declare that all complex NA's should be treated as identical
(almost/fully?) everywhere.

This would be a possibility, but I think a drastic one.

I think there are too many cases, where I want to keep the
information of the real part independent of the values of the
imaginary part (e.g. think of the Riemann hypothesis), and
typically vice versa.

With your proposal, for a (potentially large) vector of complex numbers,
after
  Re(z)  <-  1/2

I could no longer rely on   Re(z) == 1/2,
because it would be wrong for those z where (the imaginary part/ the number)
was NA/NaN.
Also, in a similar case, a

  Im(z) <- NA

would have to "destroy" all real parts  Re(z);
not really typically in memory, but effectively for the user,  Re(z)
would be all NA/NaN.

And I think there are quite a few other situations
where looking at Re() and Im() separately makes a lot of sense.

Spencer also made a remark in this direction.

All in all I'd be very reluctant to move in this direction;
but yes, I'm just one person ... let's continue musing and
considering !

Martin

>>> 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_), 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Hervé Pagès
On 9/22/23 16:55, Hervé Pagès wrote:

> The problem is that you have things that are **semantically** 
> different but look exactly the same:
>
> They look the same:
>
> > x
> [1] NA
> > y
> [1] NA
> > z
> [1] NA
>
> > is.na(x)
> [1] TRUE
> > is.na(y)
> [1] TRUE
> > is.na(z)
> [1] TRUE
>
> > str(x)
>  cplx NA
> > str(y)
>  num NA
>
oops, that was supposed to be:

 > str(y)
  cplx NA

but somehow I managed to copy/paste the wrong thing, sorry.

H.

-- 
Hervé Pagès

Bioconductor Core Team
hpages.on.git...@gmail.com

[[alternative HTML version deleted]]

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Hervé Pagès
The problem is that you have things that are **semantically** different 
but look exactly the same:

They look the same:

 > x
[1] NA
 > y
[1] NA
 > z
[1] NA

 > is.na(x)
[1] TRUE
 > is.na(y)
[1] TRUE
 > is.na(z)
[1] TRUE

 > str(x)
  cplx NA
 > str(y)
  num NA
 > str(z)
  cplx NA

but they are semantically different e.g.

 > Re(x)
[1] NA
 > Re(y)
[1] -0.5  # surprise!

 > Im(x)  # surprise!
[1] 2
 > Im(z)
[1] NA

so any expression involving Re() or Im() will produce different results 
on input that look the same on the surface.

You can address this either by normalizing the internal representation 
of complex NA to always be complex(r=NaN, i=NA_real_), like for 
NA_complex_, or by allowing the infinite variations that are currently 
allowed and at the same time making sure that both Re() and Im()  always 
return NA_real_ on a complex NA.

My point is that the behavior of complex NA should be predictable. Right 
now it's not. Once it's predictable (with Re() and Im() both returning 
NA_real_ regardless of internal representation), then it no longer 
matters what kind of complex NA is returned by as.complex(NA_real_), 
because they are no onger distinguishable.

H.

On 9/22/23 13:43, Duncan Murdoch wrote:
> 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()) 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

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Spencer Graves
	  Perhaps I shouldn't comment without having read the entire thread, 
but I will:  I can envision situations where I might want, e.g., 2 from 
complex(r=2, i=NA_real_).



  Spencer Graves


On 9/22/23 3:43 PM, Duncan Murdoch wrote:
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()) 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 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Duncan Murdoch
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()) 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 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Hervé Pagès
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()) 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 

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Mikael Jagan




On 2023-09-22 6:38 am, 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()) 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) :



Thank you for the correction - indeed, as.complex(NA_real_) and
NA_real_ + (0+0i) are identical in both R-patched and R-devel,
both giving complex(r=NA_real_, i=0) in R-patched and both giving
NA_complex_ in R-devel.  I was hallucating, it seems ...


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*



R_binary() in arithmetic.c has always coerced REALSXP->CPLXSXP when
encountering one of each.  Surely then the changes in coerce.c are the
cause and this arithmetic behaviour is just a (bad, IMO) side effect?



 > 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, Martin, for "reopening".

Mikael


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
 ==>   

Re: [Rd] Recent changes to as.complex(NA_real_)

2023-09-22 Thread Martin Maechler
> 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()) 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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2023-09-20 Thread Mikael Jagan

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?

The principle that Im(as.complex()) should
be zero is quite fundamental, in my view, hence the "new" behaviour seems
to really violate the principle of least surprise ...

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).

Having said that, one might also (but more naively) expect

identical(as.complex(as.double(NA_complex_)), NA_complex_)

to be TRUE.  Under my proposal it continues to be FALSE.  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 ...

Whatever decision is made about as.complex(NA_real_), maybe these points
should be weighed before it becomes part of R-release ...

Mikael

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel