Skip to content

Commit c6f8621

Browse files
committed
Clean traits and identities up
This changes the exception type of `one(Q0f7)` etc. from `InexactError` to `ArgumentError`.
1 parent 3caea52 commit c6f8621

File tree

4 files changed

+47
-36
lines changed

4 files changed

+47
-36
lines changed

src/FixedPointNumbers.jl

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ include("utilities.jl")
3737
reinterpret(x::FixedPoint) = x.i
3838
reinterpret(::Type{T}, x::FixedPoint{T,f}) where {T,f} = x.i
3939

40+
# static parameters
41+
nbitsfrac(::Type{X}) where {T, f, X <: FixedPoint{T,f}} = f
42+
rawtype(::Type{X}) where {T, X <: FixedPoint{T}} = T
43+
4044
# construction using the (approximate) intended value, i.e., N0f8
4145
*(x::Real, ::Type{X}) where {X<:FixedPoint} = X(x)
4246

@@ -61,7 +65,17 @@ end
6165
# predicates
6266
isinteger(x::FixedPoint{T,f}) where {T,f} = (x.i&(1<<f-1)) == 0
6367

68+
# identities
69+
zero(::Type{X}) where {X <: FixedPoint} = X(zero(rawtype(X)), 0)
70+
oneunit(::Type{X}) where {X <: FixedPoint} = X(rawone(X), 0)
71+
one(::Type{X}) where {X <: FixedPoint} = oneunit(X)
72+
73+
# for Julia v1.0, which does not fold `div_float` before inlining
74+
inv_rawone(x) = (@generated) ? (y = 1.0 / rawone(x); :($y)) : 1.0 / rawone(x)
75+
6476
# traits
77+
sizeof(::Type{X}) where {X <: FixedPoint} = sizeof(rawtype(X))
78+
eps(::Type{X}) where {X <: FixedPoint} = X(oneunit(rawtype(X)), 0)
6579
typemax(::Type{T}) where {T <: FixedPoint} = T(typemax(rawtype(T)), 0)
6680
typemin(::Type{T}) where {T <: FixedPoint} = T(typemin(rawtype(T)), 0)
6781
floatmin(::Type{T}) where {T <: FixedPoint} = eps(T)
@@ -95,18 +109,25 @@ floattype(::Type{T}) where {T <: Real} = T # fallback
95109
floattype(::Type{T}) where {T <: Union{ShortInts, Bool}} = Float32
96110
floattype(::Type{T}) where {T <: Integer} = Float64
97111
floattype(::Type{T}) where {T <: LongInts} = BigFloat
98-
floattype(::Type{FixedPoint{T,f}}) where {T <: ShortInts,f} = Float32
99-
floattype(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = Float64
100-
floattype(::Type{FixedPoint{T,f}}) where {T <: LongInts,f} = BigFloat
101-
floattype(::Type{F}) where {F <: FixedPoint} = floattype(supertype(F))
102-
floattype(x::FixedPoint) = floattype(typeof(x))
103-
104-
nbitsfrac(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = f
105-
nbitsfrac(::Type{F}) where {F <: FixedPoint} = nbitsfrac(supertype(F))
112+
floattype(::Type{X}) where {T <: ShortInts, X <: FixedPoint{T}} = Float32
113+
floattype(::Type{X}) where {T <: Integer, X <: FixedPoint{T}} = Float64
114+
floattype(::Type{X}) where {T <: LongInts, X <: FixedPoint{T}} = BigFloat
106115

107-
rawtype(::Type{FixedPoint{T,f}}) where {T <: Integer,f} = T
108-
rawtype(::Type{F}) where {F <: FixedPoint} = rawtype(supertype(F))
109-
rawtype(x::FixedPoint) = rawtype(typeof(x))
116+
for f in (:zero, :oneunit, :one, :eps, :rawone, :rawtype, :floattype)
117+
@eval begin
118+
$f(x::FixedPoint) = $f(typeof(x))
119+
end
120+
end
121+
for f in (:div, :fld, :fld1)
122+
@eval begin
123+
$f(x::X, y::X) where {X <: FixedPoint} = $f(x.i, y.i)
124+
end
125+
end
126+
for f in (:rem, :mod, :mod1, :min, :max)
127+
@eval begin
128+
$f(x::X, y::X) where {X <: FixedPoint} = X($f(x.i, y.i), 0)
129+
end
130+
end
110131

111132
# Printing. These are used to generate type-symbols, so we need them
112133
# before we include any files.
@@ -136,10 +157,6 @@ include("normed.jl")
136157
include("deprecations.jl")
137158
const UF = (N0f8, N6f10, N4f12, N2f14, N0f16)
138159

139-
eps(::Type{T}) where {T <: FixedPoint} = T(oneunit(rawtype(T)),0)
140-
eps(::T) where {T <: FixedPoint} = eps(T)
141-
sizeof(::Type{T}) where {T <: FixedPoint} = sizeof(rawtype(T))
142-
143160
# Promotions for reductions
144161
const Treduce = Float64
145162
Base.add_sum(x::FixedPoint, y::FixedPoint) = Treduce(x) + Treduce(y)
@@ -150,17 +167,6 @@ Base.reduce_empty(::typeof(Base.mul_prod), ::Type{F}) where {F<:FixedPoint} = on
150167
Base.reduce_first(::typeof(Base.mul_prod), x::FixedPoint) = Treduce(x)
151168

152169

153-
for f in (:div, :fld, :fld1)
154-
@eval begin
155-
$f(x::T, y::T) where {T <: FixedPoint} = $f(reinterpret(x),reinterpret(y))
156-
end
157-
end
158-
for f in (:rem, :mod, :mod1, :min, :max)
159-
@eval begin
160-
$f(x::T, y::T) where {T <: FixedPoint} = T($f(reinterpret(x),reinterpret(y)),0)
161-
end
162-
end
163-
164170
"""
165171
sd, ad = scaledual(s::Number, a)
166172

src/fixed.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ for T in (Int8, Int16, Int32, Int64)
4141
end
4242
end
4343

44+
function rawone(::Type{Fixed{T,f}}) where {T, f}
45+
f >= bitwidth(T)-1 && throw_converterror(Fixed{T,f}, 1)
46+
oneunit(T) << f
47+
end
48+
4449
# basic operators
4550
-(x::Fixed{T,f}) where {T,f} = Fixed{T,f}(-x.i,0)
4651
abs(x::Fixed{T,f}) where {T,f} = Fixed{T,f}(abs(x.i),0)

src/normed.jl

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,9 @@ end
3737

3838
reinterpret(::Type{Normed{T,f}}, x::T) where {T <: Unsigned,f} = Normed{T,f}(x, 0)
3939

40-
zero(::Type{Normed{T,f}}) where {T,f} = Normed{T,f}(zero(T),0)
41-
function oneunit(::Type{T}) where {T <: Normed}
42-
T(typemax(rawtype(T)) >> (bitwidth(T)-nbitsfrac(T)), 0)
40+
function rawone(::Type{Normed{T,f}}) where {T <: Unsigned, f}
41+
typemax(T) >> (bitwidth(T) - f)
4342
end
44-
one(::Type{T}) where {T <: Normed} = oneunit(T)
45-
zero(x::Normed) = zero(typeof(x))
46-
oneunit(x::Normed) = one(typeof(x))
47-
one(x::Normed) = oneunit(x)
48-
rawone(v) = reinterpret(one(v))
4943

5044
# Conversions
5145
function Normed{T,f}(x::Normed{T2}) where {T <: Unsigned,T2 <: Unsigned,f}
@@ -113,8 +107,6 @@ rem(x::Float16, ::Type{T}) where {T <: Normed} = rem(Float32(x), T) # avoid ove
113107

114108
float(x::Normed) = convert(floattype(x), x)
115109

116-
# for Julia v1.0, which does not fold `div_float` before inlining
117-
inv_rawone(x) = (@generated) ? (y = 1.0 / rawone(x); :($y)) : 1.0 / rawone(x)
118110

119111
function (::Type{T})(x::Normed) where {T <: AbstractFloat}
120112
# The following optimization for constant division may cause rounding errors.

test/fixed.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ function test_fixed(::Type{T}, f) where {T}
5050
end
5151
end
5252

53+
@testset "inexactness" begin
54+
@test_throws InexactError Q0f7(-2)
55+
# TODO: change back to InexactError when it allows message strings
56+
@test_throws ArgumentError one(Q0f15)
57+
@test_throws ArgumentError oneunit(Q0f31)
58+
@test_throws ArgumentError one(Fixed{Int8,8})
59+
end
60+
5361
@testset "conversion" begin
5462
@test isapprox(convert(Fixed{Int8,7}, 0.8), 0.797, atol=0.001)
5563
@test isapprox(convert(Fixed{Int8,7}, 0.9), 0.898, atol=0.001)

0 commit comments

Comments
 (0)