Skip to content

Commit 9181f07

Browse files
committed
Specialize sign-related functions
1 parent bfb4f47 commit 9181f07

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

src/FixedPointNumbers.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox,
66
zero, oneunit, one, typemin, typemax, floatmin, floatmax, eps, sizeof, reinterpret,
77
float, trunc, round, floor, ceil, bswap,
88
div, fld, rem, mod, mod1, fld1, min, max, minmax,
9+
signed, unsigned, copysign, flipsign, signbit,
910
rand, length
1011

1112
using Base.Checked: checked_add, checked_sub, checked_div
@@ -171,6 +172,30 @@ end
171172

172173
bswap(x::X) where {X <: FixedPoint} = sizeof(X) == 1 ? x : X(bswap(x.i), 0)
173174

175+
# Since `FixedPoint` is not an integer type, it is not clear in what type
176+
# `signed` and `unsigned` for `FixedPoint` should return values. They should
177+
# currently throw errors in case we support "unsigned Fixed" or "signed Normed"
178+
# in the future. The following "incomplete" code is necessary for Julia v1.0
179+
# etc. to prevent accidental conversion to an integer type.
180+
signed(x::X) where {X <: FixedPoint} = signed(X)(signed(x.i), 0)
181+
unsigned(x::X) where {X <: FixedPoint} = unsigned(X)(unsigned(x.i), 0)
182+
183+
function copysign(x::X, y::Real) where {T, X <: FixedPoint{T}}
184+
T <: Signed ? X(copysign(x.i, y), 0) : throw_not_a_signed_number_error(x)
185+
end
186+
function flipsign(x::X, y::Real) where {T, X <: FixedPoint{T}}
187+
T <: Signed ? X(flipsign(x.i, y), 0) : throw_not_a_signed_number_error(x)
188+
end
189+
if copysign(-1, 0x1) !== 1 # for Julia v1.0 and v1.1 (julia #30748)
190+
copysign(x::X, y::Unsigned) where {T, X <: FixedPoint{T}} = copysign(x, signed(y))
191+
flipsign(x::X, y::Unsigned) where {T, X <: FixedPoint{T}} = flipsign(x, signed(y))
192+
end
193+
@noinline function throw_not_a_signed_number_error(x)
194+
throw(ArgumentError("$x is not a signed number."))
195+
end
196+
197+
signbit(x::X) where {X <: FixedPoint} = signbit(x.i)
198+
174199
for f in (:zero, :oneunit, :one, :eps, :rawone, :rawtype, :floattype)
175200
@eval begin
176201
$f(x::FixedPoint) = $f(typeof(x))

src/normed.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ Base.BigFloat(x::Normed) = reinterpret(x)*(1/BigFloat(rawone(x)))
248248

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

251-
abs(x::Normed) = x
252-
253251
# unchecked arithmetic
254252
*(x::T, y::T) where {T <: Normed} = convert(T,convert(floattype(T), x)*convert(floattype(T), y))
255253
/(x::T, y::T) where {T <: Normed} = convert(T,convert(floattype(T), x)/convert(floattype(T), y))

test/fixed.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,23 @@ end
397397
@test bswap(Q0f15(0.5)) === reinterpret(Q0f15, signed(0x0040))
398398
end
399399

400+
@testset "sign-related functions" begin
401+
@test_throws Exception signed(Q0f7)
402+
@test_throws Exception signed(0.5Q0f7)
403+
@test_throws Exception unsigned(Q0f7)
404+
@test_throws Exception unsigned(0.5Q0f7)
405+
@test copysign(0.5Q0f7, 0x1) === 0.5Q0f7
406+
@test copysign(0.5Q0f7, -1) === -0.5Q0f7
407+
@test flipsign(0.5Q0f7, 0x1) === 0.5Q0f7
408+
@test flipsign(0.5Q0f7, -1) === -0.5Q0f7
409+
@test_throws ArgumentError sign(0Q0f7)
410+
@test sign(0Q1f6) === 0Q1f6
411+
@test sign(0.5Q1f6) === 1Q1f6
412+
@test sign(-0.5Q1f6) === -1Q1f6
413+
@test signbit(0.5Q0f7) === false
414+
@test signbit(-0.5Q0f7) === true
415+
end
416+
400417
@testset "Promotion within Fixed" begin
401418
@test @inferred(promote(Q0f7(0.25), Q0f7(0.75))) ===
402419
(Q0f7(0.25), Q0f7(0.75))

test/normed.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,19 @@ end
318318
@test minmax(N0f8(0.8), N0f8(0.2)) === (N0f8(0.2), N0f8(0.8))
319319
end
320320

321+
@testset "sign-related functions" begin
322+
@test_throws Exception signed(N0f8)
323+
@test_throws Exception signed(1N0f8)
324+
@test_throws Exception unsigned(N0f8)
325+
@test_throws Exception unsigned(1N0f8)
326+
@test_throws ArgumentError copysign(1N0f8, 0x1)
327+
@test_throws ArgumentError copysign(1N0f8, -1)
328+
@test_throws ArgumentError flipsign(1N0f8, 0x1)
329+
@test_throws ArgumentError flipsign(1N0f8, -1)
330+
@test_throws ArgumentError sign(0N0f8)
331+
@test signbit(1N0f8) === false
332+
end
333+
321334
@testset "unit range" begin
322335
@test length(N0f8(0):N0f8(1)) == 2
323336
@test length(N0f8(1):N0f8(0)) == 0

0 commit comments

Comments
 (0)