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

"-0".Num isn't negative #5557

Closed
p6rt opened this issue Aug 11, 2016 · 16 comments
Closed

"-0".Num isn't negative #5557

p6rt opened this issue Aug 11, 2016 · 16 comments
Labels
LTA Less Than Awesome; typically an error message that could be better math

Comments

@p6rt
Copy link

p6rt commented Aug 11, 2016

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

Searchable as RT128897$

@p6rt
Copy link
Author

p6rt commented Aug 11, 2016

From zefram@fysh.org

"-0".Num.perl
0e0

It's surprising that that's producing a floating-point positive zero,
rather than the negative zero that is also available​:

(-("0".Num)).perl
-0e0

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 17, 2016

From @zoffixznet

On Thu, 11 Aug 2016 09​:32​:31 -0700, zefram@​fysh.org wrote​:

"-0".Num.perl
0e0

It's surprising that that's producing a floating-point positive zero,
rather than the negative zero that is also available​:

(-("0".Num)).perl
-0e0

-zefram

Thanks for the report. Are you able to describe any usecases where the string cast resulting in a positive zero as opposed to negative zero creates a problem?

The reason we have a negative floating point zero at all is more due to underlying implementations at whose level such zeros are used to signal various exceptions. But such usage isn't needed on Perl 6 level.

Looking at the current implementation, fixing the described issue would involve special-casing the .Num string
conversion AND special-casing the negative zero numeric case. This would result in extra maintenance burden and performance loss in a very hot spot of the codebase, so I'm trying to see what the justification for that is.


As for what's happening​: "-0" gets converted to Numeric under the hood, and the containing numeric is an Int, and there's no Int negative zeros, so you end up with a plain 'ol zero that then gets converted to a Num, without the
negative sign.

In the second case you present, the string coersion ends up with an Int, which then is converted to a Num; when
you apply the prefix minus, it gets converted to a negative zero, since those exist in Nums.

So this issue gives us first special-casing​: that we need to notify the Numeric conversion that we explicitly want a Num at the end.

Now, if you try, you'll notice that '-0e0' also results in a positive zero. This is because that Numeric conversion parses the string in parts, each part being an Int and is parsed using radix_I nqp op, and Ints ain't got negative zeros, so even though the code asks the radix_I op to negate the result if we have a minus, we still end up with a positive zero.

So this is the second special case, where we have to check whether we've got a minus and a zero result and we explicitly want a Num as the end result.


So considering the impact of the end result that fixes this bug, I'm willing to sacrifice minor inconsistency of string casts never resulting in negative zeros, for the sake of clearer and more performant code, but perhaps I'm missing some viable usecase where string cast to numeric losing the sign of the zero is a problem at the high level that Perl 6 operates in?

@p6rt
Copy link
Author

p6rt commented Nov 17, 2016

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

@p6rt
Copy link
Author

p6rt commented Nov 17, 2016

From @geekosaur

On Thu, Nov 17, 2016 at 10​:13 AM, Zoffix Znet via RT <
perl6-bugs-followup@​perl.org> wrote​:

The reason we have a negative floating point zero at all is more due to
underlying implementations at whose level such zeros are used to signal
various exceptions. But such usage isn't needed on Perl 6 level.

IEEE supports negative zero because it is useful when working with limits
of series. Are you suggesting Perl 6 should not support this usage?

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 17, 2016

From @zoffixznet

More discussion on IRC​: https://irclog.perlgeek.de/perl6-dev/2016-11-17#i_13584755

So it seems a fix is indeed needed.

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From zefram@fysh.org

Zoffix Znet via RT wrote​:

The reason we have a negative floating point zero at all is more due to
underlying implementations at whose level such zeros are used to signal
various exceptions.

No, that's not what negative zero is about in floating point. (Maybe
you're thinking of ones-complement integer formats.) In floating point,
zero doesn't only represent exact zero quantities, it also represents
underflow, and it's useful to know from which side of zero a quantity
underflowed. Generally, IEEE 754 provides well defined semantics
for signed zeroes throughout, which put negative zero on a par with
positive zero.

Are you able to describe any usecases where the string cast resulting
in a positive zero as opposed to negative zero creates a problem?

Getting the right zero particularly matters in trigonometry and in complex
arithmetic, where the zeroes are on opposite sides of many branch cuts.
For example​:

atan2(0e0, -1)
3.14159265358979
atan2(-0e0, -1)
-3.14159265358979

The above behaviour is correct and desirable. In a situation where the
arguments come from string input, getting this correct behaviour depends
on the Str->Num conversion properly supporting signed zeroes.

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From @duncand

And here I thought IEEE floats had distinct values to represent overflows and
underflows that were distinct from both the zeros and the infinities. -- Darren
Duncan

On 2016-11-22 8​:19 PM, Zefram wrote​:

Zoffix Znet via RT wrote​:

The reason we have a negative floating point zero at all is more due to
underlying implementations at whose level such zeros are used to signal
various exceptions.

No, that's not what negative zero is about in floating point. (Maybe
you're thinking of ones-complement integer formats.) In floating point,
zero doesn't only represent exact zero quantities, it also represents
underflow, and it's useful to know from which side of zero a quantity
underflowed. Generally, IEEE 754 provides well defined semantics
for signed zeroes throughout, which put negative zero on a par with
positive zero.

Are you able to describe any usecases where the string cast resulting
in a positive zero as opposed to negative zero creates a problem?

Getting the right zero particularly matters in trigonometry and in complex
arithmetic, where the zeroes are on opposite sides of many branch cuts.
For example​:

atan2(0e0, -1)
3.14159265358979
atan2(-0e0, -1)
-3.14159265358979

The above behaviour is correct and desirable. In a situation where the
arguments come from string input, getting this correct behaviour depends
on the Str->Num conversion properly supporting signed zeroes.

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From @geekosaur

Zefrem and I both misspoke on this, but I clarified on IRC and this was
iirc already fixed as a result.

On Tue, Nov 22, 2016 at 11​:33 PM, Darren Duncan <darren@​darrenduncan.net>
wrote​:

And here I thought IEEE floats had distinct values to represent overflows
and underflows that were distinct from both the zeros and the infinities.
-- Darren Duncan

On 2016-11-22 8​:19 PM, Zefram wrote​:

Zoffix Znet via RT wrote​:

The reason we have a negative floating point zero at all is more due to
underlying implementations at whose level such zeros are used to signal
various exceptions.

No, that's not what negative zero is about in floating point. (Maybe
you're thinking of ones-complement integer formats.) In floating point,
zero doesn't only represent exact zero quantities, it also represents
underflow, and it's useful to know from which side of zero a quantity
underflowed. Generally, IEEE 754 provides well defined semantics
for signed zeroes throughout, which put negative zero on a par with
positive zero.

Are you able to describe any usecases where the string cast resulting

in a positive zero as opposed to negative zero creates a problem?

Getting the right zero particularly matters in trigonometry and in complex
arithmetic, where the zeroes are on opposite sides of many branch cuts.
For example​:

atan2(0e0, -1)

3.14159265358979

atan2(-0e0, -1)

-3.14159265358979

The above behaviour is correct and desirable. In a situation where the
arguments come from string input, getting this correct behaviour depends
on the Str->Num conversion properly supporting signed zeroes.

-zefram

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From zefram@fysh.org

Brandon Allbery via RT wrote​:

Zefrem and I both misspoke on this,

In which aspect did I misspeak?

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From @geekosaur

On Wed, Nov 23, 2016 at 1​:11 AM, Zefram <zefram@​fysh.org> wrote​:

In which aspect did I misspeak?

iirc underflow doesn't work quite the way either you or Darren said; it's
not just the signed zero, it's also a status flag indicating that that
signed zero reflects an underflow condition. What it is not is a separate
value as Darren seemed to think. But it's also not merely the signed zero,
although in some cases that may be sufficient.

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From @geekosaur

And my own misspeaking was a slight mis-description of the relevance of
signed zero in the ticket, which I corrected to Zoffix in IRC.

On Wed, Nov 23, 2016 at 1​:20 AM, Brandon Allbery <allbery.b@​gmail.com>
wrote​:

On Wed, Nov 23, 2016 at 1​:11 AM, Zefram <zefram@​fysh.org> wrote​:

In which aspect did I misspeak?

iirc underflow doesn't work quite the way either you or Darren said; it's
not just the signed zero, it's also a status flag indicating that that
signed zero reflects an underflow condition. What it is not is a separate
value as Darren seemed to think. But it's also not merely the signed zero,
although in some cases that may be sufficient.

--
brandon s allbery kf8nh sine nomine
associates
allbery.b@​gmail.com
ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad
http://sinenomine.net

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From zefram@fysh.org

Brandon Allbery wrote​:

iirc underflow doesn't work quite the way either you or Darren said; it's
not just the signed zero, it's also a status flag indicating that that
signed zero reflects an underflow condition.

There is no flag attached to a zero to indicate that it came
from underflow. There is an underflow exception, which in many
implementations is signalled by setting a processor status flag, but
that's quite separate from the result value. (Rakudo doesn't make this
status available afaics.) I was not attempting to describe the whole
process of underflow; I was only describing what a floating point zero,
in isolation, represents.

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From @geekosaur

On Wed, Nov 23, 2016 at 1​:53 AM, Zefram <zefram@​fysh.org> wrote​:

There is no flag attached to a zero

A status flag is not attached to a value, it is a processor status flag.
Why would you say I claimed that?

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Nov 23, 2016

From zefram@fysh.org

Brandon Allbery wrote​:

A status flag is not attached to a value, it is a processor status flag.
Why would you say I claimed that?

I didn't say that you claimed that, and indeed you hadn't. But the
implication of you saying that I had erred in my description of floating
point zeroes, with your mention of the status flag as explanation,
is that you regard this flag as being closely tied to the zero value,
which it is not.

-zefram

@p6rt
Copy link
Author

p6rt commented Nov 26, 2016

From @zoffixznet

On Thu, 11 Aug 2016 09​:32​:31 -0700, zefram@​fysh.org wrote​:

"-0".Num.perl
0e0

It's surprising that that's producing a floating-point positive zero,
rather than the negative zero that is also available​:

(-("0".Num)).perl
-0e0

-zefram

Thank you for the report. This is now fixed \o/

rakudo​:
  rakudo/rakudo@e2587cd012
  rakudo/rakudo@a9654c0d8e
tests​:
  Raku/roast@7fed1c00a0
  Raku/roast@cbc959fc22

@p6rt p6rt closed this as completed Nov 26, 2016
@p6rt
Copy link
Author

p6rt commented Nov 26, 2016

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

@p6rt p6rt added LTA Less Than Awesome; typically an error message that could be better math labels Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LTA Less Than Awesome; typically an error message that could be better math
Projects
None yet
Development

No branches or pull requests

1 participant