Skip to content

base/twiceprecision.jl needs work #49589

@nsajko

Description

@nsajko

Algorithms for arithmetic (+, -, *, /)

The algorithms for real (as opposed to complex) double-word addition, multiplication and division were seemingly (there are no relevant explanatory comments or references in the code) all created ad-hoc and need to be updated to the standard algos, something I'll try to do in #49569.

Regarding the algorithms for complex numbers, they seem to be missing entirely, causing Base.TwicePrecision{<:Complex} to fall back to the algorithms for real numbers. This is OK for addition because Complex is a Cartesian (orthogonal) representation of complex numbers, but multiplication and division could be quite broken. This could be fixed by adding methods for Base.TwicePrecision{<:Complex} to base/complex.jl. A paper exists for double-word complex multiplication, and I guess I could work something out for division.

Design of the Base.TwicePrecision type

The Base.TwicePrecision type has an awkward and unsafe design. It accepts elements of any type, not just floating-point-based types. I propose this design instead as a replacement:

In base/twiceprecision.jl:

abstract type AbstractMultiWordFloatingPoint{n,T<:Number} end

# some methods for `AbstractMultiWordFloatingPoint` ...

struct MultiWordFloatingPoint{n,T<:AbstractFloat} <:
    AbstractMultiWordFloatingPoint{n,T}

    words::NTuple{n,T}
end

# some methods for `MultiWordFloatingPoint` ...

const DoubleWordFloatingPoint =
    MultiWordFloatingPoint{2,T} where {T<:AbstractFloat}

# some methods for `DoubleWordFloatingPoint`, including arithmetic ...

In base/complex.jl:

struct MultiWordFloatingPointComplex{n,T<:Complex{<:AbstractFloat}} <:
    AbstractMultiWordFloatingPoint{n,T}

    words::NTuple{n,T}
end

# some methods for `MultiWordFloatingPointComplex` ...

const DoubleWordFloatingPointComplex =
    MultiWordFloatingPointComplex{2,T} where {T<:AbstractFloat}

# some methods for `DoubleWordFloatingPointComplex`, including arithmetic ...

Note that MultiWordFloatingPointComplex only makes sense because Complex is an orthogonal coordinate representation of the complex numbers. A polar representation, for example, would be nonsensical in this context because a multi-word representation represents an unevaluated sum.

The n type parameter would be restricted to two in practice for the time being, however I think that having it as a parameter right away gives a more elegant design.

Is supporting complex numbers even necessary?

The point of Base.TwicePrecision is supporting ranges, and while ranges with complex elements do exist, I think the step is always real? This seems like it would mean that double-word algorithms for complex numbers are an unnecessary evil.

EDIT: the answer seems to be yes, supporting complex numbers is necessary:

julia> (1.0:5.0) .* im
0.0 + 1.0im:0.0 + 1.0im:0.0 + 5.0im

julia> (1.0:5.0) .* im .* im
-1.0 + 0.0im:-1.0 + 0.0im:-5.0 + 0.0im

splitprec

This is more of a question than an issue, but I find this dubious so I thought it'd be good to raise it here with the other stuff.

Why does TwicePrecision{<:AbstractFloat}(::Integer) use that splitprec function:

https://github.com/JuliaLang/julia/blob/master/base/twiceprecision.jl#L213-L214

The fallback conversion method TwicePrecision{<:Any}(::Any) is sufficient for converting integers to double-word floating-point:

https://github.com/JuliaLang/julia/blob/master/base/twiceprecision.jl#L203-L207

So it seems that the intention is to give up accuracy on purpose while converting integers to TwicePrecision? It's likely that I'm missing something, but I find this quite strange and I can't imagine why would one desire such behavior. Also, it seems that something similar is happening when the truncbits function is used.

Metadata

Metadata

Assignees

No one assigned

    Labels

    mathsMathematical functionsrangesEverything AbstractRange

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions