Repository navigation
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #362 +/- ##
==========================================
- Coverage 96.75% 96.74% -0.01%
==========================================
Files 7 7
Lines 800 799 -1
==========================================
- Hits 774 773 -1
Misses 26 26 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PatrickHaecker
left a comment
There was a problem hiding this comment.
I think this would currently violate the promised interface, but the fix seems plausible. LGTM with the fix.
I still haven't understood why this is better than just doing a 0.10 release in the next days, but that is irrelevant in terms of correctness.
| @test floattype(FixedPoint) === BigFloat | ||
| @test floattype(Normed) === BigFloat | ||
| @test floattype(Fixed) === BigFloat | ||
| @test floattype(FixedPoint{Int8}) === Float32 | ||
| @test floattype(Normed{UInt32}) === Float64 | ||
| @test floattype(Fixed{Int64}) === BigFloat | ||
| @test floattype(FixedPoint{MyInteger}) === Float64 | ||
| @test floattype(FixedPoint{Union{},1}) === BigFloat | ||
| @test floattype(Normed{Unsigned,2}) === BigFloat | ||
| @test floattype(Fixed{T,3} where {T<:Signed}) === BigFloat |
There was a problem hiding this comment.
Please add few non-trivial Union cases, too.
| """ | ||
| floattype(::Type{T})::Type{<:AbstractFloat} | ||
|
|
||
| Return a minimal type suitable for performing computations with instances of type `T` without integer overflow. | ||
|
|
||
| The fallback definition of `floattype(T)` applies only to `T<:AbstractFloat`. | ||
| However, it is permissible to extend `floattype` to return types that are not subtypes of | ||
| `AbstractFloat`; the key characteristic is that the return type should support computation without integer overflow. | ||
|
|
||
| In general the returned type should have the minimum bitwidth needed to encode the full precision of the input type. | ||
| however, a priority should be placed on computational efficiency; consequently, types like `Float16` should be avoided | ||
| except in scenarios where they are guaranteed to have hardware support. | ||
|
|
||
| # Examples | ||
|
|
||
| A classic usage is to avoid overflow behavior by promoting `FixedPoint` to `AbstractFloat` | ||
|
|
||
| ```jldoctest; setup = :(using FixedPointNumbers) | ||
| julia> x = N0f8(1.0) | ||
| 1.0N0f8 | ||
|
|
||
| julia> x + x # overflow | ||
| 0.996N0f8 | ||
|
|
||
| julia> T = floattype(x) | ||
| Float32 | ||
|
|
||
| julia> T(x) + T(x) | ||
| 2.0f0 | ||
| ``` | ||
|
|
||
| The following represents a valid extension of `floattype` to non-AbstractFloats: | ||
|
|
||
| ```julia | ||
| julia> using FixedPointNumbers, ColorTypes | ||
|
|
||
| julia> floattype(RGB{N0f8}) | ||
| RGB{Float32} | ||
| ``` | ||
|
|
||
| `RGB` itself is not a subtype of `AbstractFloat`, but unlike `RGB{N0f8}` operations with `RGB{Float32}` are not subject to integer overflow. | ||
| """ |
There was a problem hiding this comment.
The docstring had some weaknesses and should describe the new situation explicitly:
| """ | |
| floattype(::Type{T}) | |
| floattype(x::FixedPoint) | |
| Return a minimal type suitable for performing computations with instances of type `T` without integer overflow. | |
| For a `Real` type `T`, the returned type is a subtype of `AbstractFloat`. In general it has the minimum bitwidth | |
| needed to encode the full precision of `T`. However, computational efficiency takes priority, so the returned type | |
| may be wider. For example, `floattype(N0f8)` is currently `Float32` rather than `Float16`. | |
| For a non-concrete `FixedPoint` type, the returned type suits all of its concrete subtypes. A `Union` of `FixedPoint` | |
| types gives the promoted type of its members. Any other non-concrete `FixedPoint` type gives `floattype(R)` if its raw | |
| type `R` is concrete, and `BigFloat` otherwise. | |
| Methods are defined for `AbstractFloat`, `Integer`, `Rational`, `AbstractIrrational` and `FixedPoint` types. Other | |
| `Real` types currently return `T` itself with a deprecation warning, and will throw a `MethodError` in a future | |
| release. Packages may extend `floattype` to types that are not `Real`, as long as the returned type supports | |
| computation without integer overflow. | |
| # Examples | |
| A classic usage is to avoid overflow by converting `FixedPoint` values to a floating-point type: | |
| ```jldoctest; setup = :(using FixedPointNumbers) | |
| julia> x = N0f8(1.0) | |
| 1.0N0f8 | |
| julia> x + x # overflow | |
| 0.996N0f8 | |
| julia> T = floattype(x) | |
| Float32 | |
| julia> T(x) + T(x) | |
| 2.0f0 |
Non-concrete FixedPoint types:
julia> floattype(Normed{UInt8})
Float32
julia> floattype(Union{N0f8, N0f16})
Float32
julia> floattype(Normed)
BigFloat
The following represents a valid extension of floattype to types that are not subtypes of AbstractFloat:
julia> using FixedPointNumbers, ColorTypes
julia> floattype(RGB{N0f8})
RGB{Float32}RGB itself is not a subtype of AbstractFloat, but unlike RGB{N0f8}, operations with RGB{Float32} are not subject
to integer overflow.
"""
There was a problem hiding this comment.
Aside from the fact that it's long, I think the proposal isn't bad.
However, I don't understand exactly what purpose it serves.
This document is primarily intended for package developers. I don't know of any examples where floattype is actually being used outside of ColorTypes and its downstream packages.
I think the top-down definition of floattype should be discussed in JuliaLang/julia rather than in this package.
There was a problem hiding this comment.
The purpose for me was having documentation for the code which is aligned with each other. I agree that it is verbose, but I am not sure where it can be made shorter without losing something.
There was a problem hiding this comment.
I feel like detailed documentation ends up losing something.
If "The behavior of Union and UnionAll is subject to change until v1.0," who ends up losing out?
|
@PatrickHaecker |
|
@kimikage
The
julia> promote_type(Int128, Float16)
Float16That seems a bit extreme to me, but that is what we should go for if we want to be as compatible as possible to
julia> promote_type(Union{Int8, Int16}, Float32)
RealSo we probably don't want to strive for maximum w = vcat(Int8[100], Int32[3])
w[1] + w[1] # 200: the Int8 was converted to Int32
w = vcat(Int16[100], Int32[3])
w[1] + w[1] # 200: the Int16 was converted to Int32
a = Union{Int8, Int16}[Int8(100)]
v = vcat(a, Int32[3]) # eltype Signed, elements Int8, Int16, Int32
v[1] + v[1] # -56: Int8 arithmetic overflowsI reported that. Should we maybe see whether that report provides any insights? |
|
First of all, since this package is still at v0.x, I don’t think it’s necessary to mark something as deprecated before introducing breaking changes. I thought you were eager to switch from v0.9.x to v0.10, so I'm not quite sure what your priorities are anymore. My intention is, at the very least, to ensure that IMO, the situation that In light of PR #341, what should be my next step? |
That's a good point. I was, however, more focused on when we want to change it in the future. And that might very well be 1.x land.
But why then promoting to
Would it make sense to decouple
Would it help to explain what's the purpose of #362? I think it would if I could understand what problem should be solved and why |
As mentioned above, the purpose is to ensure that |
Ah, okay, wouldn't then the best option be to use the code as is and explicitly mention in the docstring that whenever |
This is a variant of PR #354 with deprecated fallback method retained.
While it would be hypocritical not to call this a breaking change, it does allow us to avoid a direct violation of SemVer.
In other words, I plan to release this in the v0.9 series.