JuliaMath / FixedPointNumbers.jl

fixed point types for julia

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding rounding functions for `Fixed`

kimikage opened this issue · comments

As I mentioned in #139, there are no rounding functions for Fixed.

julia> round(0.502N0f8)
1.0N0f8

julia> round(0.500Q0f7)
ERROR: MethodError: no method matching round(::Fixed{Int8,7}, ::RoundingMode{:Nearest})

An important difference between Normed and Fixed is that Normed has no tie (or half) numbers, but Fixed has.
So, I also think it is a good idea to support the 2nd argument (i.e. RoundingMode) explicitly.

BTW, I think the current implementation has an overflow problem. (1 is a Int64 or Int32 number.)

function round(x::Normed{T,f}) where {T,f}
mask = convert(T, 1<<(f-1))
y = trunc(x)
return convert(T, reinterpret(x)-reinterpret(y)) & mask>0 ?
Normed{T,f}(y+oneunit(Normed{T,f})) : y
end

The method using divrem proposed in the PR #143 will probably solve the overflow problem. (I guess it cannot handle the signed Normed correctly, though.)

function round(x::Normed{T,f}) where {T,f}
    d, r = divrem(reinterpret(x), rawone(x))
    return Normed{T,f}((d + r>>(f-1))*rawone(x), 0)
end
julia> round(typemax(N0f64)) # on 64-bit version
ERROR: InexactError: check_top_bit(Int64, -9223372036854775808)

julia> ceil(typemax(N1f7)) # wraparound
0.984N1f7

testtrunc is not so powerful even though it spends a lot of time.

This is off-topic, but not only rem but also div is going to accept a rounding mode in Julia v1.4.