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

Infinity MathConst #6062

Closed
wants to merge 4 commits into from
Closed

Infinity MathConst #6062

wants to merge 4 commits into from

Conversation

MikeInnes
Copy link
Member

I've added infinity and its symbol as a MathConst.

Should be straightforward enough but let me know if I've missed anything.

@JeffBezanson
Copy link
Member

const ∞ = Inf might be sufficient. Inf is exact already, and I'd rather not export both Inf and infinity (and inf).

@MikeInnes
Copy link
Member Author

Inf is exact, but it's a special case of an inexact type. For symbolic routines (or custom numeric types, anything else where infinity should be dealt with specially) it might be handy to dispatch on an explicitly exact type rather than having isinf checks everywhere.

Also, (∞*(x::T))::T may be desirable behaviour - you can use inf(x) of course, but it's definitely less clear.

I agree with the exporting concern, though. My suggestion would be to have inf as the constant for the reasons above - you can write e.g. inf*x rather than inf(x)*x, and if you need a particular type you can use big(inf), float(inf) etc. Obviously this is a breaking change which you might want to avoid, though.

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

I have a serious objection to this PR, namely that the current mathematical semantics of ∞ are only well-defined for FloatingPoint types.

First, it is not possible to represent ∞ for Integers. Second, there are multiple kinds of ∞ for more complicated objects like complex numbers or matrices. For Real numbers one has +∞ and -∞, but for Complex numbers you have an infinite number of infinities: not just +∞+i∞, +∞-i∞, -∞+i∞, -∞-i∞, but also ∞*exp(im*k) for any k in 0:2pi. For matrices you could easily construct matrices with any number of real or complex infinite eigenvalues which behave like some generalization of real infinity.

The issue with Complex numbers is actually a solved problem: one can "fix" the algebra of complex numbers by defining a closure at , which identifies all the complex infinities to the same point. However, one then technically no longer has complex numbers in the complex plane, but rather extended complex numbers (extended by ∞) on the Riemann sphere. Now the nice thing is that it is actually not hard to define the algebra of extended complex numbers using an ∞ MathConst. Conversely, this is a breaking change to the behavior of complex numbers (to put it mildly), to replace complex numbers by their extended closure.

Infinity is a limit, not a number. If we want to do this, we should do it cognizant of what we are really doing.

@MikeInnes
Copy link
Member Author

I see what you're saying - this is obviously a topic that deserves some thought.

That said, it's worth pointing out that where you've defined the complex infinities etc., you've consistently used the symbol to refer to a particular kind of infinity - the positive real one. The fact that infinity can only be well defined in this way seems in support of using that definition, not against it - as long as you're clear about what the symbol does or does not represent.

The nice thing about MathConst{:∞} is that libraries can use it to support other concepts like extended complex numbers or matrices without it being in base. There may well be other downsides to this, but personally I would view total mathematical completeness as a future possibility rather than an immediate necessity.

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

you've consistently used the ∞ symbol to refer to a particular kind of infinity - the positive real one. The fact that infinity can only be well defined in this way seems in support of using that definition, not against it

I thought I was being quite careful in drawing a distinction between the usage of ∞ in the real and complex settings, which are extremely different beasts. The fact that I wrote out real ∞s in the usual Cartesian and polar notations of complex numbers is irrelevant.

There is a genuine problem with correctness in the Complex setting, and the last thing we should be doing is accepting things that are only half-correct at best, and of limited utility when it is actually correct.

The nice thing about MathConst{:∞} is that libraries can use it to support other concepts like extended complex numbers or matrices without it being in base.

Packages that want to overload notions of ∞ for extended complex numbers or special matrices can easily define it within their own scope. In fact, the limited utility of ∞ for Base types argues strongly against putting it in Base.

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

I'll relent slightly, in that everyone understands what real positive infinity is. Here are the pros and cons of defining real positive infinity as a MathConst, as I see it:

Pros

  • New shiny Unicode character to play with
  • Well defined for real positive infinity

Cons

  • Potential for serious bogosity for complex numbers; it's too easy to forget that real positive infinity is but one of many complex infinities. convert(Complex, infinity) is a semantic quagmire.
  • All the other MathConsts are finite numbers, while Inf isn't. In principle, the former can be rounded off to integers or rationalized to Rationals in well-defined ways. Inf cannot.
  • The whole point of MathConsts, as I recall, is to have a clever dispatch mechanism to avoid unnecessary loss of precision. Inf, however, is exactly representable in all FloatingPoint types, and so the only use case for the new MathConst is as convenient, if potentially confusing, notation.

@toivoh
Copy link
Contributor

toivoh commented Mar 6, 2014

Perhaps we can focus this discussion on whether ∞ should be defined as a
MathConst or Float64?
Right now, I agree that the MathConst might be overkill, creating more
problems than it solves. Would we be prepared to revisit this question if
it is later found that a MathConst would be better?

On Thu, Mar 6, 2014 at 3:06 PM, Jiahao Chen [email protected]:

I'll relent slightly, in that everyone understands what real positive
infinity is. Here are the pros and cons of defining real positive infinity
as a MathConst, as I see it:

Pros

  • New shiny Unicode character to play with
  • Well defined for real positive infinity

Cons

  • Potential for serious bogosity for complex numbers; it's too easy to
    forget that real positive infinity is but one of many complex infinities.
    convert(Complex, infinity) is a semantic quagmire.
  • All the other MathConsts are finite numbers, while Inf isn't. In
    principle, the former can be rounded off to integers or rationalized to
    Rationals in well-defined ways. Inf cannot.
  • The whole point of MathConsts, as I recall, is to have a clever
    dispatch mechanism to avoid unnecessary loss of precision. Inf, however, is
    exactly representable in all FloatingPoint types, and so the only use case
    for the new MathConst is as convenient, if potentially confusing, notation.


Reply to this email directly or view it on GitHubhttps://github.com//pull/6062#issuecomment-36890410
.

@JeffBezanson
Copy link
Member

I'll point out that the intent of MathConst was to provide a convenient interface to the various functions that exist for computing constants to different precisions, so you don't have to write things like bigfloat_pi(). The intent was not to provide symbolic versions of the constants, such that you might define sin(::MathConst{:pi}) and so on.

Strange idea: maybe Inf should be a Float16 so that it doesn't force unwanted promotions.

@MikeInnes
Copy link
Member Author

@jiahao The thing is, your notation for the complex infinities is entirely relevant, because this about notation. And in notation - including yours - is used to refer not to the general concept of infinity, but specifically to "real positive infinity". That being the case, it should refer to "real positive infinity" in code, too. If you then want to represent complex infinities, for example, you can do so using the exact ∞*exp(im*k) notation you have used.

OTOH, perhaps I'm wrong and there is a use case where does refer to another value with different semantics - in that case, absolutely, giving a fixed value is a bad idea. I haven't seen such a case, but that doesn't mean there isn't one of course.

The issues you've mentioned with a MathConst definition are orthogonal to this, since could be its own singleton type or Inf.

@MikeInnes
Copy link
Member Author

@toivoh I'm happy to discuss this, but I believe @jiahao is against defining at all.

@JeffBezanson +1, that's a really neat idea.

@JeffBezanson
Copy link
Member

Also, not too related, but I think the functions infs and nans are just silly and should be removed.

@pao
Copy link
Member

pao commented Mar 6, 2014

@JeffBezanson: nans() is a helpful default array when NaN is used as portable NA; for instance, in data you might exchange with a customer.

@StefanKarpinski
Copy link
Member

@jiahao:

Infinity is a limit, not a number. If we want to do this, we should do it cognizant of what we are really doing.

I think that cantor and all the set theorists since might disagree with you.

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

OTOH, perhaps I'm wrong and there is a use case where ∞ does refer to another value with different semantics - in that case, absolutely, giving ∞ a fixed value is a bad idea. I haven't seen such a case, but that doesn't mean there isn't one of course.

Let me try to be clearer: the real case isn't that hard. The complex case is. That was exactly why I made a point of distinguishing between ordinary complex numbers and their compactification on the Riemann sphere. In the former, there are many infinities lying on a circle of infinite radius in the complex plane. In the latter, all these points are identified to be the same. Both of these notions are used in complex analysis, using whichever is convenient at the time. The consequence, however, is that ∞ has different semantics. complex(Inf, 0) == complex(-Inf, 0) == ∞ on the Riemann sphere, whereas they are distinct for ordinary complex numbers. Conversely, ordinary complex numbers can distinguish between complex(Inf, +0.0) and complex(Inf, -0.0), whereas on the Riemann sphere they are both ∞.

@StefanKarpinski do you really want to discuss the semantics of transfinite cardinals? That might be a somewhat, erm, divisive issue.

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

Until someone can explain to me why convert(Complex, ∞) is semantically unambiguous, yes, I do object to defining at all.

@JeffBezanson
Copy link
Member

We give a meaning to convert(Complex, Inf) via the usual embedding of reals. True, this is only one possible "correct" answer, but most complex functions have the same issue.

@pao At that point I prefer to use fill(NaN, m, n).

@jiahao
Copy link
Member

jiahao commented Mar 6, 2014

I have no issue with convert(Complex, Inf). The issue is with convert(Complex, ∞). The claim is being made that the notation ∞ is an exact synonym for Inf, when in fact this is only true in the context of real numbers. ∞ is also widely used in complex analysis to mean the things I have described already, and is not necessarily a single-valued concept.

@JeffBezanson
Copy link
Member

In that case, we can simultaneously placate the complex analysts and unicode luddites by simply closing this issue :)

@pao
Copy link
Member

pao commented Mar 6, 2014

At that point I prefer to use fill(NaN, m, n).

Fair enough--still spending more time than not in MATLAB and forgot about that.

@StefanKarpinski
Copy link
Member

We should not have infinite MathConsts. The reason that MathConsts exist is so that you can write expressions like π*x/2 and have them produce a correct value of the correct type. For example, this expression is really nicely behaved for all kinds of inputs:

julia> f(x) = π*x/2
f (generic function with 1 method)

julia> f(1)
1.5707963267948966

julia> f(1.0)
1.5707963267948966

julia> f(1.0f0)
1.5707964f0

julia> f(big(1))
1.570796326794896619231321691639751442098584699687552910487472296153908203143099e+00 with 256 bits of precision

In each case, that's exactly what the type and value you want. Why doesn't the same rationale apply to having infinite MathConsts? Because you literally never write things like ∞*x/2. That's not a useful expression at all. Algebraic expressions involving literal infinities beyond just and -∞ are never useful – because they can only ever give you infinity, its negation, or NaN.

So when does one use infinity? You can use it in situations like this:

minval =for x in v
    if x < minval
        minval = x
    end
end
# what type is minval?

In this kind of situation, having be a MathConst is not only not helpful, it's dangerous – it completely destroys the type stability of this code since it can yield a minval of the element type of v or a MathConst. The correct way to handle this situations is to either write inf(eltype(v)) or raise an error in the case that v is empty. MathConsts are not useful for either one.

Currently Inf behaves like a Float64 literal, which is fine. Sometimes you just want to write 1.0 and sometimes you want to write Inf too. Changing Inf to a MathConst buys nothing useful and leaves you not only having to be more careful about type stability, but also verbosely writing float64(Inf) for the positive infinite Float64 value. This is very ugly and verbose for something that used to be simple and clear.

In this post, I've been writing for a value that might or might not be a MathConst. That doesn't mean that the name is important – it's not. Whether we use the name is a bikeshed and fundamentally just window dressing. The real question is whether we should have infinte MathConst values or not – we definitely should not.

@MikeInnes
Copy link
Member Author

@jiahao I don't think we're going to agree on this, so don't take this as a counter argument as such, but this would be my approach. The ambiguity comes not from the meaning of , but from the ambiguity in the type of complex number you're working with.

Julia's complex numbers are standard, non-extended ones, so "real positive infinity" is simply convert(Complex, Inf) == ∞ + 0im.

From what you've said, extended complex numbers have different semantics, in which case they should have their own type, too. convert(ExtendedComplex, ∞) == ExtendedComplex(∞) == ∞.

So it's not infinity's semantics which change here, it's the field's - but luckily Julia allows for that. As long as infinity behaves the same when used with reals, complexes, extended complexes etc. individually, there's no issue with defining it as a singleton type.

@MikeInnes
Copy link
Member Author

@StefanKarpinski +1 for this line of reasoning. The thing is, if it's not a MathConst it loses the few benefits it had, so I think @JeffBezanson is right, and I should just close the issue.

@waldyrious waldyrious mentioned this pull request Jul 9, 2018
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

Successfully merging this pull request may close these issues.

6 participants