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

power returns invalid complex number for negative base and Infinity as exponent #804

Open
balagge opened this Issue Feb 28, 2017 · 20 comments

Comments

Projects
None yet
4 participants
@balagge

balagge commented Feb 28, 2017

Following inputs return NaN - aNi in Notepad. Seems like all negative bases yield the same:

(-0.5)^Infinity
(-1)^Infinity
(-2)^Infinty

probably the underlying function pow() returns a Complex with both Real and Imaginary part set to NaN. (haven't checked).

Definitely, NaN + aNi is wrong. But whether this is simply an issue with the rendering, or the underlying logic, is to be analyzed. Some thoughts:

  • Whether the result should be a Complex with both Real and Imaginary parts set to NaN, is questionable (after all there is a NaN already, no need to introduce a "second, complex NaN" value maybe).

  • for -1 < a < 0, the result should probably be zero, as in javascript, this one converges: Math.pow(-0.5,Infinity) // 0

  • for a < -1 the result should not be Infinity (so, unlike javascript), because this is clearly divergent. (I don't understand javascript behavior: Math.pow(-2,Infinity) // Infinity

  • -Infinity as exponent should also be considered (currently these cases also return incorrect NaN + aNi, but convergence / divergence should also be considered separately for -Infinity)

@josdejong

This comment has been minimized.

Owner

josdejong commented Feb 28, 2017

Thanks for reporting Paal. That NaN - aNi looks like a formatting issue. Besides that we can definitely give these edge cases with NaN and infinity some more thought. We should keep in mind that we're working with a numerical system (with it's limitations).

@josdejong josdejong added the bug label Feb 28, 2017

@harrysarson

This comment has been minimized.

Collaborator

harrysarson commented Apr 20, 2017

I had a look into this: the pow function checks if the base is positive or the exponent is an integer or config.predictable = true and if so returns the result of Math.pow. Otherwise the pow function of Complex.js is used which returns Nan + NaNi for infinite exponents.

Therefore with config.predictable = true negative bases raised to the power of infinity return either Infinity or zero.

I feel that the behaviour should not change in this way regarding config.predictable so it would be worth adding a check for infinite exponents to the pow function.

@josdejong

This comment has been minimized.

Owner

josdejong commented Apr 20, 2017

@harrysarson would you like to pick this issue up?

@harrysarson

This comment has been minimized.

Collaborator

harrysarson commented Apr 20, 2017

Sure I can have a go :)

@josdejong

This comment has been minimized.

Owner

josdejong commented Apr 20, 2017

👍 thanks

@harrysarson

This comment has been minimized.

Collaborator

harrysarson commented Apr 20, 2017

What are your views on the best result for (-2)^Infinity?

  • a) Infinity as javascript, matlab and c++ all go for.
  • b) Not infinity as @balagge says - possibly NaN?.
  • c) Some sort of ComplexInfinity which how it is done in wolfram alpha.

I feel like (c) is the most elegant solution but would require either a new type or and extension of complex.js. (a) and (b) are much easier to do.

Additionally the behaviour of complex.js is currently to return (NaN + NaN * i) for any infinite powers - it would be nice if math.pow(2, Infinity).toString() === math.pow(math.complex(2), Infinity)).toString() so I might raise an issue with complex.js for better support for infinities.

@josdejong

This comment has been minimized.

Owner

josdejong commented Apr 22, 2017

I think returning complex infinity for (-2)^Infinity would be most neat, or else complex NaN like it does now.

@infusion

This comment has been minimized.

Collaborator

infusion commented Apr 22, 2017

For complex numbers NaN can make sense, since the the power function is defined via sin/cos and sin(inf)=nan. However, if we think about it, pow(c∈C, inf) is an infinite rotation of an arrow. With this interpretation, Infinity would make sense too. However, I would go with a new "symbol" - "complex infinity" as well.

I made some minor changes on complex.js regarding the infinity behavior. I'd be glad if you guys could have a look: infusion/Complex.js#5

@infusion

This comment has been minimized.

Collaborator

infusion commented Apr 22, 2017

Ah, and about the printing error, I catch NaN's in complex.js's toString(). I suspect, that we added an own stringifier for math.js.

@josdejong

This comment has been minimized.

Owner

josdejong commented Apr 24, 2017

I've fixed the wrong formatting of NaN + aNi which should be NaN + NaNi. math.js indeed still overwrites the .toString of Complex.js. Maybe that's not needed at all. Let's check that out.

Sounds good @infusion . It may make sense to create a special constant complex infinity rather than using Infinity. It may make sense to create this as a constant in math.js: math.ComplexInfinity, which would simply be the new Complex.Infinity constant of Complex.js. Probably we can do the same for complex NaN: ComplexNaN?

@infusion

This comment has been minimized.

Collaborator

infusion commented Apr 24, 2017

@josdejong for "NaN + NaNi", I decided for complex.js to make the whole complex-number NaN as soon as one component becomes NaN. So, the output is "NaN". I think this lacks some information in the output, but at the end it's just a feedback, that an operation failed, other than for infinity, where the individual dimensions can become infinity with a certain meaning.

Mapping Complex.Infinity to math.ComplexInfinity sounds good to me :)

ComplexNaN is still a big question. We actually use complex numbers to make Math.sqrt(-1)!=NaN work. There're only rare discontinuities where NaN can occur. That are 0/0 and the strange case when 0*Infinity is NaN in Javascript, which we can fix. For my last push to the "infinity" branch of complex.js, I decided to make 0/0 complex infinity as well, since I don't like to introduce a new symbol for that.

What do you guys think?

@balagge

This comment has been minimized.

balagge commented Apr 24, 2017

I think complex infinity is a great idea. Complex infinity is different from "real" infinities Infinity and -Infinity, because those have directions on the complex plane, whereas complex infinity is directionless.

Complex infinity (denoted by I below) should satisfy:

  • I + z = I, for any z ∈ ℂ;
  • -I = I (UNLIKE real Infinities!!);
  • I * I = I;
  • I * z = I for any z ∈ ℂ, z ≠ 0;
  • z / I = 0 for any z ∈ ℂ, z ≠ 0;

Edge cases:

  • I + I is not defined (NaN), UNLIKE real Infinities!;
  • 0 * I is not defined (NaN?)
  • I / I is not defined (NaN?)
  • I - I is not defined (NaN?)
@balagge

This comment has been minimized.

balagge commented Apr 24, 2017

ComplexNaN, on the other hand, maybe should be avoided. I do not see justification for a "separate" NaN value. (for the record: I do not see justification for NaN in the first place). But accepting the fact that we do have NaN, for whatever reason, then creating another one seems awkward to me.

So if any operation could/should return "complex NaN", I would vote for returning simply 'NaN' instead.

@balagge

This comment has been minimized.

balagge commented Apr 24, 2017

http://reference.wolfram.com/language/ref/ComplexInfinity.html

This page is also useful, it has some return values in Wolfram of standard functions on ComplexInfinity. (under "Neat Examples")

@balagge

This comment has been minimized.

balagge commented Apr 24, 2017

If the complex infinity is in the exponent, I would say:

  • z ^ I = I, for any z ∈ ℂ, abs(z) >1 (this includes I^I = I as well);
  • z ^ I = 1, if z = 1;
  • z ^ I is undefined for any z ∈ ℂ, abs(z) = 1 and z ≠ 1;
  • z ^ I = 0 for any z ∈ ℂ, abs(z) <1

update: these may be (are probably) wrong, someone should check it who has better knowledge of complex analysis than me... I have studied this type of stuff more than 2 decades ago.

@harrysarson

This comment has been minimized.

Collaborator

harrysarson commented Apr 24, 2017

The discussion about ComplexInfinity may be better placed at infusion/Complex.js#5 as the implementation of complex pow is handed there.

complex(0).mul(Infinity) shouldn't simply return NaN as complex(0).mul(Infinity).add(4) should propagate the NaN value (in a similar way to 0*Infinity+5) where as if "normal" NaN was returned the user would have to check the result of every function call which would be very annoying for them.

Apart from that I agree :)

@josdejong

This comment has been minimized.

Owner

josdejong commented Apr 24, 2017

Makes sense. So to summarize: we want Infinity, ComplexInfinity, and NaN but no "complex NaN".

The latter may be tricky since that means that after every operations with complex numbers we have to check whether the resulting complex number contains NaN for one or both re and im. What we could do though is adjust the presentation of a complex number containing NaN (like Complex.js already does), and adjust equality checks such that math.equal(math.complex(NaN, NaN), NaN) === true and function isNaN handles complex NaN instances too.

@harrysarson

This comment has been minimized.

Collaborator

harrysarson commented Feb 1, 2018

Complex.js now has infinity support in master branch. When the next release is published to npm we should be able to fix math.pow(complex, Infinity).

I think it should "just work" but some tests might fail and even if they don't we should add some new tests. I will make a PR when the new version is published. :)

@infusion

This comment has been minimized.

Collaborator

infusion commented Feb 1, 2018

I thik the concept of complex infinity must be introduced for math.js as well. (with a special symbol or sth)

@josdejong

This comment has been minimized.

Owner

josdejong commented Feb 3, 2018

Great if you can pick this up coming time Harry !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment