Skip to content

Commit 0f468c6

Browse files
committed
Improve accuracy of rem with Normed types (e.g. ::Float32 % N0f32)
1 parent 930f19a commit 0f468c6

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

src/normed.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ rem(x::T, ::Type{T}) where {T <: Normed} = x
105105
rem(x::Normed, ::Type{T}) where {T <: Normed} = reinterpret(T, _unsafe_trunc(rawtype(T), round((rawone(T)/rawone(x))*reinterpret(x))))
106106
rem(x::Real, ::Type{T}) where {T <: Normed} = reinterpret(T, _unsafe_trunc(rawtype(T), round(rawone(T)*x)))
107107
rem(x::Float16, ::Type{T}) where {T <: Normed} = rem(Float32(x), T) # avoid overflow
108+
function rem(x::Float32, ::Type{T}) where {f, T <: Normed{UInt32,f}}
109+
f <= 24 && return reinterpret(T, _unsafe_trunc(UInt32, round(rawone(T) * x)))
110+
r = _unsafe_trunc(UInt32, round(x * @f32(0x1p24)))
111+
reinterpret(T, r << UInt8(f - 24) - unsigned(signed(r) >> 0x18))
112+
end
113+
function rem(x::Float64, ::Type{T}) where {f, T <: Normed{UInt64,f}}
114+
f <= 53 && return reinterpret(T, _unsafe_trunc(UInt64, round(rawone(T) * x)))
115+
r = _unsafe_trunc(UInt64, round(x * 0x1p53))
116+
reinterpret(T, r << UInt8(f - 53) - unsigned(signed(r) >> 0x35))
117+
end
108118

109119

110120
function (::Type{T})(x::Normed) where {T <: AbstractFloat}

test/normed.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ end
200200

201201
@test 1 % N0f8 == 1
202202
@test 2 % N0f8 == N0f8(0.996)
203+
204+
# issue #150
205+
@test all(f -> 1.0f0 % Normed{UInt32,f} == oneunit(Normed{UInt32,f}), 1:32)
206+
@test all(f -> 1.0e0 % Normed{UInt64,f} == oneunit(Normed{UInt64,f}), 1:64)
203207
end
204208

205209
@testset "bitwise" begin

0 commit comments

Comments
 (0)