Skip to content

Commit 0446a89

Browse files
authored
Add big() and rationalize() for FixedPoint (#186)
This also stops using the reciprocal technique in `BigFloat(::Normed)`, because the constant folding is not available.
1 parent c1c4e69 commit 0446a89

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

src/FixedPointNumbers.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox,
44
convert, promote_rule, show, bitstring, abs, decompose,
55
isnan, isinf, isfinite, isinteger,
66
zero, oneunit, one, typemin, typemax, floatmin, floatmax, eps, reinterpret,
7-
float, trunc, round, floor, ceil, bswap,
7+
big, rationalize, float, trunc, round, floor, ceil, bswap,
88
div, fld, rem, mod, mod1, fld1, min, max, minmax,
99
rand, length
1010

@@ -71,6 +71,14 @@ function (::Type{Ti})(x::FixedPoint) where {Ti <: Integer}
7171
end
7272
Base.Rational{Ti}(x::FixedPoint) where {Ti <: Integer} = Rational{Ti}(Rational(x))
7373

74+
big(::Type{<:FixedPoint}) = BigFloat
75+
big(x::FixedPoint) = convert(BigFloat, x)
76+
77+
rationalize(x::FixedPoint; tol::Real=eps(x)) = rationalize(Int, x, tol=tol)
78+
function rationalize(::Type{Ti}, x::FixedPoint; tol::Real=eps(x)) where Ti <: Integer
79+
tol <= eps(x) ? Rational{Ti}(x) : rationalize(Ti, float(x), tol)
80+
end
81+
7482
"""
7583
isapprox(x::FixedPoint, y::FixedPoint; rtol=0, atol=max(eps(x), eps(y)))
7684

src/normed.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ function Base.Float64(x::Normed{UInt128,f}) where f
244244
end
245245
end
246246

247-
Base.BigFloat(x::Normed) = reinterpret(x)*(1/BigFloat(rawone(x)))
247+
Base.BigFloat(x::Normed) = reinterpret(x) / BigFloat(rawone(x))
248248

249249
Base.Rational(x::Normed) = reinterpret(x)//rawone(x)
250250

test/fixed.jl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,6 @@ end
256256
@test varm(a, m) === varm(af, m)
257257
end
258258

259-
@testset "convert result type" begin
260-
x = Fixed{Int8,7}(0.75)
261-
for T in (Float16, Float32, Float64, BigFloat)
262-
y = convert(T, x)
263-
@test isa(y, T)
264-
end
265-
end
266-
267259
@testset "bool conversions" begin
268260
@test convert(Bool, 0.0Q1f6) === false
269261
@test convert(Bool, 1.0Q1f6) === true
@@ -272,7 +264,7 @@ end
272264
@test_broken convert(Bool, Fixed{Int8,8}(0.2)) # TODO: remove this
273265
end
274266

275-
@testset "Integer conversions" begin
267+
@testset "integer conversions" begin
276268
@test convert(Int, Q1f6(1)) === 1
277269
@test convert(Integer, Q1f6(1)) === Int8(1)
278270
@test convert(UInt, 1Q1f6) === UInt(1)
@@ -283,7 +275,19 @@ end
283275
@testset "rational conversions" begin
284276
@test convert(Rational, -0.75Q1f6) === Rational{Int8}(-3//4)
285277
@test convert(Rational, -0.75Q0f7) === Rational{Int16}(-3//4)
286-
@test convert(Rational{Int}, -0.75Q0f7) === Rational(-3//4)
278+
@test convert(Rational{Int}, -0.75Q0f7) === Rational{Int}(-3//4)
279+
280+
@test rationalize(-0.75Q3f4) === Rational{Int}(-3//4)
281+
@test rationalize(Int16, 0.81Q3f4) === Rational{Int16}(13//16)
282+
@test rationalize(-0.81Q3f4, tol=0.02) === Rational{Int}(-13//16)
283+
@test rationalize(Int8, -0.81Q3f4, tol=0.07) === Rational{Int8}(-3//4)
284+
end
285+
286+
@testset "BigFloat conversions" begin
287+
@test convert(BigFloat, -0.75Q0f7)::BigFloat == big"-0.75"
288+
289+
@test big(Q7f0) === BigFloat # !== BigInt
290+
@test big(0.75Q3f4)::BigFloat == big"0.75"
287291
end
288292

289293
@testset "Floating-point conversions" begin
@@ -293,7 +297,7 @@ end
293297
end
294298

295299
@testset "conversions to float" begin
296-
for T in (Float16, Float32, Float64, BigFloat)
300+
for T in (Float16, Float32, Float64)
297301
@test isa(convert(T, Q0f7(0.3)), T)
298302
end
299303

test/normed.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ end
113113
@test convert(Integer, one(T)) == 1
114114
@test convert(Rational, one(T)) == 1
115115
end
116-
@test convert(Rational, convert(N0f8, 0.5)) == 0x80//0xff
117116
@test convert(N0f16, one(N0f8)) === one(N0f16)
118117
@test convert(N0f16, N0f8(0.5)).i === 0x8080
119118
@test convert(Normed{UInt16,7}, Normed{UInt8,7}(0.504)) === Normed{UInt16,7}(0.504)
@@ -127,6 +126,24 @@ end
127126
@test_throws InexactError convert(Int8, 256N8f8)
128127
end
129128

129+
@testset "rational conversions" begin
130+
@test convert(Rational, 0.5N0f8) === Rational{UInt8}(0x80//0xff)
131+
@test convert(Rational, 0.5N4f12) === Rational{UInt16}(0x800//0xfff)
132+
@test convert(Rational{Int}, 0.5N0f8) === Rational{Int}(0x80//0xff)
133+
134+
@test rationalize(0.8N0f8) === Rational{Int}(4//5)
135+
@test rationalize(Int16, 0.804N0f8) === Rational{Int16}(41//51)
136+
@test rationalize(0.804N0f8, tol=0.002) === Rational{Int}(41//51)
137+
@test rationalize(Int8, 0.804N0f8, tol=0.005) === Rational{Int8}(4//5)
138+
end
139+
140+
@testset "BigFloat conversions" begin
141+
@test convert(BigFloat, 0.5N0f8)::BigFloat == 128 / big"255"
142+
143+
@test big(N7f1) === BigFloat # !== BigInt
144+
@test big(0.5N4f4)::BigFloat == 8 / big"15"
145+
end
146+
130147
@testset "conversion from float" begin
131148
# issue 102
132149
for T in (UInt8, UInt16, UInt32, UInt64, UInt128)
@@ -161,7 +178,7 @@ end
161178

162179
@testset "conversions to float" begin
163180
x = N0f8(0.3)
164-
for T in (Float16, Float32, Float64, BigFloat)
181+
for T in (Float16, Float32, Float64)
165182
y = convert(T, x)
166183
@test isa(y, T)
167184
end

0 commit comments

Comments
 (0)