@rfateman: I agree that there are some tricky questions, but the first thing to do is to make it easy to implement and experiment with.
Here is a first example of using a polar type with intervals. I believe this is an illustrative example of Julia’s flexibility.
First we define a generic, parametrised Polar type, and conversions to and from Julia’s standard Complex type:
struct Polar{T}
r::T
θ::T
end
Base.Complex(p::Polar) = p.r * cis(p.θ)
function Polar(z::Complex)
x, y = reim(z)
r = sqrt(x^2 + y^2)
θ = atan(y, x)
return Polar(r, θ)
end
We define + by converting to rectangular form, then converting back:
function Base.:+(p1::Polar, p2::Polar)
z1 = Complex(p1)
z2 = Complex(p2)
return Polar(z1 + z2)
end
The above definitions and functions are generic – they will work with any type. (We may want to restrict them to e.g. accept only subtypes of Real, but for clarity I have not done so.)
Now we load the IntervalArithmetic.jl package, which represents intervals using endpoints (rather than midpoint + radius, for which we could use Arb via the Arblib.jl wrapper), and define some objects and add them
using IntervalArithmetic
p1 = Polar(1..2, 3..4)
p2 = Polar(3..4, 5..6)
p1 + p2
This produces an object of type Polar{Interval{Float64}};
Julia has automatically generated compiled, specialised code for the sum of two Polars containing Intervals. (Currently two-argument atan calls into MPFR for correct rounding, so it is rather slow.)
We can easily use intervals of BigFloats (i.e. MPFR floats with 256 bits of precision by default) instead:
p1 = Polar(big(1..2), big(3..4))
p2 = Polar(big(3..4), big(5..6))
p1 + p2
which produces an object of type Polar{Interval{BigFloat}} instead (and all necessary methods have again been specialised for the new type).
If at some point we came up with a better algorithm for the sum of two Polars containing Intervals, we could specialise just that method as
function Base.:+(p1::Polar{<:Interval}, p2::Polar{<:Interval})
...
end
In most of this code types are not mentioned, but nonetheless they just flow through the code, and the correct methods / versions of each function are called automatically. This is one of the places where Julia shines.