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

Broken functions for complex intervals #41

Open
1 of 5 tasks
dpsanders opened this issue May 27, 2017 · 13 comments
Open
1 of 5 tasks

Broken functions for complex intervals #41

dpsanders opened this issue May 27, 2017 · 13 comments
Labels

Comments

@dpsanders
Copy link
Member

dpsanders commented May 27, 2017

The following functions are currently broken for complex intervals; see JuliaLang/julia#22095.
They give a stack overflow due to incorrect fallbacks in base Julia:

  • exp, sin, cos, cosh, sinh -- due to sincos
  • sqrt, log, log1p, log2, log10
  • asin, acos, atan
  • tanh, asinh, acosh, atanh
  • sinpi, cospi, sinc, cosc
@giordano
Copy link
Member

I'm sure you already carefully thought about typing of AbstractInterval, but what about making it a subtype of AbstractFloat? Are there unwanted side effects?

I did so for Measurement type in Measurements.jl package, and all complex functions work with it, without any effort on my side.

@dpsanders
Copy link
Member Author

Hmm, I haven't tried it; that's good idea, thanks!

It's not actually very clear to me what that would imply though.

@dpsanders
Copy link
Member Author

See the branch subtype_abstractfloat. It currently leads to some ambiguity warnings in convert methods that will have to be fixed first.

@giordano
Copy link
Member

It's not actually very clear to me what that would imply though.

For the complex functions, they would automatically use the f(::Complex{<:AbstractFloat}) method, instead of going through f(x::Complex{<:Real}) = f(float(x)), that triggers the StackOverflowError.

See JuliaPhysics/Measurements.jl#1 for the discussion about typing of Measurement, I first started with Number and after discussion I eventually realized that AbstractType was the most useful and meaningful supertype of my type (see last message).

@giordano
Copy link
Member

However I see that Interval{Rational} is allowed, in that case may not be a good idea to make AbstractInterval a subtype of AbstractFloat. Out of curiosity: why Rational and not Integer?

@dpsanders
Copy link
Member Author

I am not that convinced that we still need Interval{Rational}; cc @lbenet.

Interval{Int} is very restrictive: as soon as you do almost anything to it, you leave the integers.

@giordano
Copy link
Member

Interval{Int} is very restrictive: as soon as you do almost anything to it, you leave the integers.

I see. That was my main concern for Measurement as well, and I decided to go with AbstractFloat only.

If ambiguities you mentioned above can be fixed, this can probably the solution to all these issues ;-)

@dpsanders
Copy link
Member Author

I was actually not aware of Measurement.jl, but it's really quite close to IntervalArithmetic.jl in many ways! Thanks for the useful comments!

@lbenet
Copy link
Member

lbenet commented Jun 1, 2017

Sorry for joining you too late in this discussion...

Out of curiosity: why Rational and not Integer?

In contrast to Integers, you can do quite a lot with Rational arithmetic. For example, rational functions (quotients of polynomials) can be handled exactly using Rationals.

I'm sure you already carefully thought about typing of AbstractInterval, but what about making it a subtype of AbstractFloat? Are there unwanted side effects?

As @dpsanders answered, it would get rid of Interval{Rational{T}}, and as explained above, I think that is actually useful.

Let me twist a bit @giordano's idea, and create a const that almost acts as an abstract type.

julia> const AbstractFloatAndRational = Union{subtypes(AbstractFloat)..., Rational}
Union{BigFloat, Float16, Float32, Float64, Rational}

julia> abstract type AbstractInterval <: AbstractFloat end

julia> type Interval{T<:AbstractFloatAndRational} <: AbstractInterval
           lo :: T
           hi :: T
       end

julia> Interval{T<:AbstractFloatAndRational}(a::T, b::T) = Interval{T}(a,b)
Interval

julia> Interval(0.0, 1.0)
Interval{Float64}(0.0, 1.0)

julia> Interval(0//1, 1//1)
Interval{Rational{Int64}}(0//1, 1//1)

julia> setprecision(BigFloat, 64)
64

julia> Interval(big(0.0), big(1.0))
Interval{BigFloat}(0.00000000000000000000, 1.00000000000000000000)

I'm not so sure if this can solve the problems of this issue, but it allows to have Interval as a subtype of AbstractFloat with the possibility of having Interval{Rational{T}}.

@giordano
Copy link
Member

giordano commented Jun 1, 2017

In contrast to Integers, you can do quite a lot with Rational arithmetic. For example, rational functions (quotients of polynomials) can be handled exactly using Rationals.

Thanks for chiming in this discussion! I see your point and I agree that with interval arithmetic you can do probably all arithmetic with Rationals. The same isn't true for Measurements.jl, because the resulting uncertainty (i.e., the half-width of the interval) is the square root of quadrature sums of contribution to uncertainty of each operand, so virtually any operation ends up with a floating point width.

Regarding your proposal, my only concert is that if you want to keep both Interval{Rational} and Interval{<:AbstractFloat}, making them both subtypes of AbstractFloat may result in wrong methods being picked-up for Interval{Rational} in complex functions (or maybe you don't solve the StackOverflowError for them).

As a side note, I think that AbstractFloatAndRational could be defined as

const AbstractFloatAndRational = Union{AbstractFloat, Rational}

that isn't limited to the value of AbstractFloat at compile-time ;-)

@lbenet lbenet mentioned this issue Jun 1, 2017
@dpsanders
Copy link
Member Author

The simplest thing to do is just define methods to act directly on Complex Intervals and not hold our breath to see when things are improved in Base.

@giordano
Copy link
Member

In Julia's Base library, mathematical non-arithmetic functions of real argument are eventually defined only for specific types of AbstractFloat (usually Float32, Float64, BigFloat), even those implemented in pure Julia. Likewise, most functions of complex argument are eventually defined only for AbstractFloat, usually to ensure type-stability. I'm not sure things will ever change.

@dpsanders
Copy link
Member Author

exp et al. were fixed by JuliaLang/julia#25292.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants