Raku / old-issue-tracker

Tickets from RT
https://github.com/Raku/old-issue-tracker/issues
2 stars 1 forks source link

sign($x) always returns 1 when $x ~~ Complex #419

Closed p6rt closed 14 years ago

p6rt commented 15 years ago

Migrated from rt.perl.org#60674 (status was 'resolved')

Searchable as RT60674$

p6rt commented 15 years ago

From @masak

\ what should the behaviour of sign($x) be when $x is complex? \ rakudo​: say sign($_) for 42, -42, 0+42i \ rakudo 32877​: OUTPUT[1␤-1␤1␤] \ somehow, that last one doesn't feel right to me. \ I vote for either an error or $x/abs($x) \ why would it be an error? \ because 'sign' could be argued to only be applicable to real numbers. \ i.e. positive numbers, negative numbers, and zero. \ but what is it specced to do? :-) \ ah. \ it's supposed to return the 'sign' of a number. \ i.e. +1, -1 or 0 for the above three groups. \ in that way, it's a bit like \<=>, except it always compares to 0 \ oh, it's wrong anyway I think. \ rakudo​: say sign(-5+3i); \ rakudo 32877​: OUTPUT[1␤] \ that can't be right. \ it always returns 1 on complex numbers. * masak reports a bug

p6rt commented 15 years ago

From @moritz

On Wed Nov 19 07​:35​:48 2008, masak wrote​:

\ what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure. If you care about complex numbers, you usually want an angle instead, which you can get with Complex.polar. (And it's easier to give it a another meaning later that way)

(If you wanted a complex number with magnitude one, then you should call that method "phase" or so, but that would confuse most people when talking about real numbers.)

Cheers, Moritz

\ rakudo​: say sign($_) for 42, -42, 0+42i \ rakudo 32877​: OUTPUT[1␤-1␤1␤] \ somehow, that last one doesn't feel right to me. \ I vote for either an error or $x/abs($x) \ why would it be an error? \ because 'sign' could be argued to only be applicable to real numbers. \ i.e. positive numbers, negative numbers, and zero. \ but what is it specced to do? :-) \ ah. \ it's supposed to return the 'sign' of a number. \ i.e. +1, -1 or 0 for the above three groups. \ in that way, it's a bit like \<=>, except it always compares to 0 \ oh, it's wrong anyway I think. \ rakudo​: say sign(-5+3i); \ rakudo 32877​: OUTPUT[1␤] \ that can't be right. \ it always returns 1 on complex numbers. * masak reports a bug

p6rt commented 15 years ago

The RT System itself - Status changed from 'new' to 'open'

p6rt commented 15 years ago

From @masak

Moritz (>), Carl (>>)​:

\ what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure.

Aye.

[...]

p6rt commented 15 years ago

From wolfgang.laun@gmail.com

There is a definition for the signum function for a complex argument.

sign( z ) = z / |z| for all z != 0 sign( 0 ) = 0

See e.g. http://en.wikipedia.org/wiki/Sign_function

Shouldn't be too difficult to implement.

-----Original Message----- From​: Carl Mäsak [mailto​:cmasak@​gmail.com] Sent​: Mittwoch, 19. November 2008 22​:24 To​: perl6-bugs-followup@​perl.org Subject​: Re​: [perl #​60674] sign($x) always returns 1 when $x ~~ Complex

Moritz (>), Carl (>>)​:

\ what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure.

Aye.

p6rt commented 15 years ago

From @masak

Wolfgang (>)​:

There is a definition for the signum function for a complex argument.

sign( z ) = z / |z| for all z != 0 sign( 0 ) = 0

See e.g. http://en.wikipedia.org/wiki/Sign_function

Shouldn't be too difficult to implement.

It isn't, and note that I also proposed it in my first email.

I guess the question is more about the programmer's expectations. Is this a case where we serve the programmer better by returning Failure, or by generalizing the C\ function to the complex plane?

p6rt commented 15 years ago

From @markjreed

On Thu, Nov 20, 2008 at 8​:34 AM, Carl Mäsak \cmasak@&#8203;gmail\.com wrote​:

I guess the question is more about the programmer's expectations. Is this a case where we serve the programmer better by returning Failure, or by generalizing the C\ function to the complex plane?

This is parallel to the case for sqrt($x) for $x\<0. Which does not by default return Failure, but neither does it return a complex result - it returns NaN. Is that the spec'ed behavior?

On the one hand, as long as sqrt() *doesn't* uncomplainingly return complex numbers for negative inputs, it would seem that one is rather less likely to have a complex number when expecting a real than to have a negative when expecting a positive. So having sgn() return complex results for complex inputs is somewhat safer than having sqrt() return complex results for negative inputs.

On the other hand, a lot of code will be expecting the return value of sign() to always be one(-1,0,1), and might break horribly if that's not the case.

I think the most sensible thing is to be consistent. sgn() fails for non-real input as long as sqrt() returns NaN for negative input. Change the latter behavior (via a pragma or whatever) so that sqrt() returns complex numbers, and then sgn() should start behaving on such numbers.

-- Mark J. Reed \markjreed@&#8203;gmail\.com

p6rt commented 15 years ago

From @masak

Mark (>)​:

I think the most sensible thing is to be consistent. sgn() fails for non-real input as long as sqrt() returns NaN for negative input. Change the latter behavior (via a pragma or whatever) so that sqrt() returns complex numbers, and then sgn() should start behaving on such numbers.

I like that. Both sign() and sqrt() will then behave like they usually do, without complex surprises. But for those who want the generalized behvaiour, it's only a pragma away.

// Carl

p6rt commented 15 years ago

From @TimToady

On Thu, Nov 20, 2008 at 04​:31​:22PM +0100, Carl Mäsak wrote​: : Mark (>)​: : > I think the most sensible thing is to be consistent. sgn() fails for : > non-real input as long as sqrt() returns NaN for negative input. : > Change the latter behavior (via a pragma or whatever) so that sqrt() : > returns complex numbers, and then sgn() should start behaving on such : > numbers. : : I like that. Both sign() and sqrt() will then behave like they usually : do, without complex surprises. But for those who want the generalized : behvaiour, it's only a pragma away.

Doesn't really need a pragma, just import an appropriate multi.

Larry

p6rt commented 15 years ago

From @chrisdolan

Mark (>)​:

I think the most sensible thing is to be consistent. sgn() fails for non-real input as long as sqrt() returns NaN for negative input. Change the latter behavior (via a pragma or whatever) so that sqrt() returns complex numbers, and then sgn() should start behaving on such numbers.

I like that. Both sign() and sqrt() will then behave like they usually do, without complex surprises. But for those who want the generalized behvaiour, it's only a pragma away.

// Carl

Rather than a pragma, wouldn't it make more sense to have

multi sub sgn(Num) -> Num multi sub sqrt(Num) -> Num

behave appropriately for real numbers and

multi sub sgn(Complex) -> Complex multi sub sqrt(Complex) -> Complex

behave appropriately for complex numbers? So people who want sqrt(-1) be return i must pass in Complex.new(-1,0) or whatever the right syntax is.

p6rt commented 15 years ago

From @markjreed

I'd rather retain the dwimmishness of p5.

$ perl -MMath​::Complex -le 'print sqrt(-1)' i

Note that I didn't have to pass in Math​::Complex->make(-1,0). Just -1.

On 11/20/08, Chris Dolan \chris@&#8203;chrisdolan\.net wrote​:

Mark (>)​:

I think the most sensible thing is to be consistent. sgn() fails for non-real input as long as sqrt() returns NaN for negative input. Change the latter behavior (via a pragma or whatever) so that sqrt() returns complex numbers, and then sgn() should start behaving on such numbers.

I like that. Both sign() and sqrt() will then behave like they usually do, without complex surprises. But for those who want the generalized behvaiour, it's only a pragma away.

// Carl

Rather than a pragma, wouldn't it make more sense to have

multi sub sgn(Num) -> Num multi sub sqrt(Num) -> Num

behave appropriately for real numbers and

multi sub sgn(Complex) -> Complex multi sub sqrt(Complex) -> Complex

behave appropriately for complex numbers? So people who want sqrt(-1) be return i must pass in Complex.new(-1,0) or whatever the right syntax is.

-- Sent from Gmail for mobile | mobile.google.com

Mark J. Reed \markjreed@&#8203;gmail\.com

p6rt commented 15 years ago

From Thomas.Sandlass@vts-systems.de

HaloO,

Moritz Lenz via RT wrote​:

On Wed Nov 19 07​:35​:48 2008, masak wrote​:

\ what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure.

This is a bit drastic. If one computes in the complex domain a complex valued sign function is appropriate.

  multi sub sign(Complex $z --> Complex)   {   return $z.abs ?? $z / $z.abs !! 0;   }

That is, it returns a unit complex number or zero. This nicely fits the notion that the set {-1,1} is the zero dimensional unit sphere with 0 as center just like the unit circle is the one dimensional unit sphere.

Regards, TSa. --

"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare "Simplicity does not precede complexity, but follows it." -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan

p6rt commented 15 years ago

From wolfgang.laun@gmail.com

If a programmer calls a function with an argument that has a well-established type, s/he may very well expect a result according to that type, (considering that overloading isn't just a word for not caring about type).

So, calling sqrt with a real \< 0, should not come back with a complex number. Calling sqrt with a complex z where Re(z) \< 0 and Im(z)=0 should return a complex number. Calling sgn() with a complex - why not give me what I'm (obviously) asking for?

On Thu, Nov 20, 2008 at 4​:31 PM, Carl Mäsak \cmasak@&#8203;gmail\.com wrote​:

Mark (>)​:

I think the most sensible thing is to be consistent. sgn() fails for non-real input as long as sqrt() returns NaN for negative input. Change the latter behavior (via a pragma or whatever) so that sqrt() returns complex numbers, and then sgn() should start behaving on such numbers.

I like that. Both sign() and sqrt() will then behave like they usually do, without complex surprises. But for those who want the generalized behvaiour, it's only a pragma away.

// Carl

p6rt commented 15 years ago

From @markjreed

On Thu, Nov 20, 2008 at 4​:25 PM, Wolfgang Laun \wolfgang\.laun@&#8203;gmail\.com wrote​:

So, calling sqrt with a real \< 0, should not come back with a complex number.

Again, I think this should depend on context. In Perl5, simply use'ing "Math​::Complex" changes the behavior of sqrt such that sqrt(-1) returns i. That fits with the fact that 1/2 returns 0.5, and not zero (unlike certain other languages); I don't have to coerce one of the operands to a float to get a float result. I want to keep that sort of DWIMmishness - if I'm computing with complex numbers, reals should be autopromoted without my having to convert them manually.

So simply making sqrt a multi doesn't quite suffice.

Calling sqrt with a complex z where Re(z) \< 0 and Im(z)=0 should return a complex number.

Agreed. (Side topic​: what about autodemotion? Should calling sqrt with a complex z where Re(z) >= 0 and Im(z) = 0 return a complex or a real?)

Calling sgn() with a complex - why not give me what I'm (obviously) asking for?

My only objection to that behavior was that I want to avoid surprise interactions; a lot of code assumes that sgn() can only return one of three values. As long as it's sufficiently unlikely that a Complex will show up when the programmer isn't expecting it, I'm fine with just having sgn() return 0 for 0 and z/abs(z) for everything else.

-- Mark J. Reed \markjreed@&#8203;gmail\.com

p6rt commented 14 years ago

From @kyleha

This is an automatically generated mail to inform you that tests are now available in t/spec/S32-num/sign.t

commit 82872635f7c3f0494a1291fa5b359ea56ee5cde5 Author​: moritz \moritz@&#8203;c213334d\-75ef\-0310\-aa23\-eaa082d1ae64 Date​: Thu Oct 29 08​:12​:57 2009 +0000

  [t/spec] test for RT #​60674, sign(Complex)  
  git-svn-id​: http://svn.pugscode.org/pugs@&#8203;28948 c213334d-75ef-0310-aa23-eaa082d1ae64

Inline Patch ```diff diff --git a/t/spec/S32-num/sign.t b/t/spec/S32-num/sign.t index 819943a..d04e35f 100644 --- a/t/spec/S32-num/sign.t +++ b/t/spec/S32-num/sign.t @@ -1,6 +1,6 @@ use v6; use Test; -plan 14; +plan *; # L @@ -29,5 +29,8 @@ is(sign(NaN),NaN, 'sign of NaN is NaN'); } ok sign(undef) ~~ undef, 'sign(undef) is undef'; +ok sign(3+4i) ~~ undef, 'sign(Complex) fails'; + +done_testing; # vim: ft=perl6 ```
p6rt commented 14 years ago

From @moritz

As per Rakudo 27e0d69c8f4927eb3df3087ca12b8b1cb616365f and spec non-consensus sign(Complex) now fail()s, and we have a test in t/spec/S32-num/sign.t. Closing Ticket.

Cheers, Moritz

p6rt commented 14 years ago

@moritz - Status changed from 'open' to 'resolved'