Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
p6rt opened this issue Nov 19, 2008 · 17 comments
Closed

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

p6rt opened this issue Nov 19, 2008 · 17 comments

Comments

@p6rt
Copy link

p6rt commented Nov 19, 2008

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

Searchable as RT60674$

@p6rt
Copy link
Author

p6rt commented Nov 19, 2008

From @masak

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

@p6rt
Copy link
Author

p6rt commented Nov 19, 2008

From @moritz

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

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

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

@p6rt
Copy link
Author

p6rt commented Nov 19, 2008

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

@p6rt
Copy link
Author

p6rt commented Nov 19, 2008

From @masak

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

<masak> what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure.

Aye.

[...]

@p6rt
Copy link
Author

p6rt commented Nov 20, 2008

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 (>>)​:

<masak> what should the behaviour of sign($x) be when $x is complex?

I'd argue that it's a Failure.

Aye.

@p6rt
Copy link
Author

p6rt commented Nov 20, 2008

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<sign> function to the complex plane?

@p6rt
Copy link
Author

p6rt commented Nov 20, 2008

From @markjreed

On Thu, Nov 20, 2008 at 8​:34 AM, Carl Mäsak <cmasak@​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<sign> 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@​gmail.com>

@p6rt
Copy link
Author

p6rt commented Nov 20, 2008

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
Copy link
Author

p6rt commented Nov 20, 2008

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
Copy link
Author

p6rt commented Nov 20, 2008

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
Copy link
Author

p6rt commented Nov 20, 2008

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@​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@​gmail.com>

@p6rt
Copy link
Author

p6rt commented Nov 20, 2008

From Thomas.Sandlass@vts-systems.de

HaloO,

Moritz Lenz via RT wrote​:

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

<masak> 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
Copy link
Author

p6rt commented Nov 21, 2008

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@​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
Copy link
Author

p6rt commented Nov 21, 2008

From @markjreed

On Thu, Nov 20, 2008 at 4​:25 PM, Wolfgang Laun <wolfgang.laun@​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@​gmail.com>

@p6rt
Copy link
Author

p6rt commented Oct 29, 2009

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@​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 --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<S32::Numeric/Num/"=item sign">
 
@@ -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
Copy link
Author

p6rt commented Oct 29, 2009

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
Copy link
Author

p6rt commented Oct 29, 2009

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

@p6rt p6rt closed this as completed Oct 29, 2009
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant