Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/FixedPointNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox,
big, rationalize, float, trunc, round, floor, ceil, bswap, clamp,
div, fld, cld, rem, mod, mod1, fld1, min, max, minmax,
signed, unsigned, copysign, flipsign, signbit,
length
length, widen, widemul

import Random: Random, AbstractRNG, SamplerType, rand!

Expand Down Expand Up @@ -552,6 +552,38 @@ function _widen_rawtype(::Type{X}, m) where {T, f, X<:FixedPoint{T,f}}
_widen_rawtype(wrapper(X){Tw,f}, m)
end

"""
widen(x::FixedPoint)
widen(X::Type{<:FixedPoint})

Widen the raw type like a bit integer of `Base` and keep the number of fractional bits.

A 128-bit raw type cannot be widened by default.

# Examples

```jldoctest; setup = :(using FixedPointNumbers)
julia> widen(N0f8) === N8f8
true

julia> widen(1N0f8) + widen(1N0f8)
2.0N8f8

julia> widen(-1Q0f7) * widen(-1Q0f7)
1.0Q8f7

julia> widen(Fixed{Int128, 8})
ERROR: MethodError: no method matching widen(::Type{Fixed{Int128, 8}})
[...]
```
"""
widen(::Type{X}) where {T, f, X <: FixedPoint{T, f}} = wrapper(X){widen(T), f}
# `widen` of a 128-bit integer is `BigInt`, which is no valid raw type
widen(::Type{X}) where {T <: Union{Int128, UInt128}, f, X <: FixedPoint{T, f}} = throw(MethodError(widen, (X,)))

# the generic `widen(x) * widen(y)` would round the exact product
widemul(x::FixedPoint, y::FixedPoint) = throw(MethodError(widemul, (x, y)))

# Promotions for reductions
const Treduce = Float64
Base.add_sum(x::FixedPoint, y::FixedPoint) = Treduce(x) + Treduce(y)
Expand Down
9 changes: 9 additions & 0 deletions test/fixed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,15 @@ end
@test @inferred(promote_type(Q0f7, N0f32)) === Float64
end

@testset "widen" begin
@test @inferred(widen(Q0f7)) === Q8f7
@test @inferred(widen(Fixed{Int64,10})) === Fixed{Int128,10}
@test @inferred(widen(0.5Q0f7)) === 0.5Q8f7
@test_throws MethodError widen(Fixed{Int128,8})
@test_throws MethodError widemul(-1Q0f7, -1Q0f7)
@test_throws MethodError widemul(0.5Q0f7, 0.5Q1f6)
end

@testset "show" begin
@test (@test_deprecated FixedPointNumbers.typechar(Q0f7)) === 'Q'

Expand Down
9 changes: 9 additions & 0 deletions test/normed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,15 @@ end
@test @inferred(promote_type(N0f8, Q0f31)) === Float64
end

@testset "widen" begin
@test @inferred(widen(N0f8)) === N8f8
@test @inferred(widen(Normed{UInt64,10})) === Normed{UInt128,10}
@test @inferred(widen(0.2N0f8)) === 0.2N8f8
@test_throws MethodError widen(Normed{UInt128,8})
@test_throws MethodError widemul(N4f4(15), N4f4(15))
@test_throws MethodError widemul(1N0f8, 1N1f7)
end

@testset "show" begin
@test (@test_deprecated FixedPointNumbers.typechar(N0f8)) === 'N'

Expand Down
Loading