Skip to content

Commit

Permalink
make flipsign(typemin(T), -1) == typemin(T) consistently
Browse files Browse the repository at this point in the history
Also, make `flipsign(::Bool, y)` typestable, and add
`flipsign(x, Unsigned) = +x`.
  • Loading branch information
rfourquet committed May 30, 2017
1 parent 0e8408f commit 8e86be3
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 5 deletions.
1 change: 1 addition & 0 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ signbit(x::Integer) = x < 0
signbit(x::Unsigned) = false

flipsign(x::T, y::T) where {T<:BitSigned} = flipsign_int(x, y)
flipsign(x::BitSigned, y::BitSigned) = flipsign_int(promote(x, y)...) % typeof(x)

flipsign(x::Signed, y::Signed) = convert(typeof(x), flipsign(promote_noncircular(x, y)...))
flipsign(x::Signed, y::Float16) = flipsign(x, bitcast(Int16, y))
Expand Down
4 changes: 2 additions & 2 deletions base/number.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ abs2(x::Real) = x*x
Return `x` with its sign flipped if `y` is negative. For example `abs(x) = flipsign(x,x)`.
"""
flipsign(x::Real, y::Real) = ifelse(signbit(y), -x, x)
copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, x)
flipsign(x::Real, y::Real) = ifelse(signbit(y), -x, +x) # the + is for type-stability on Bool
copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, +x)

conj(x::Real) = x
transpose(x::Number) = x
Expand Down
6 changes: 6 additions & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ function deepcopy_internal end
# BigInts and BigFloats
include("gmp.jl")
importall .GMP

for T in [Signed, Integer, BigInt, Float32, Float64, Real, Complex, Rational]
@eval flipsign(x::$T, ::Unsigned) = +x
@eval copysign(x::$T, ::Unsigned) = +x
end

include("mpfr.jl")
importall .MPFR
big(n::Integer) = convert(BigInt,n)
Expand Down
21 changes: 18 additions & 3 deletions test/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,31 @@ for y in (4, Float32(4), 4.0, big(4.0))
@test copysign(-3, y) == 3
end

# Result type must be type of first argument
for T in (Base.BitInteger_types..., BigInt,
# Result type must be type of first argument, except for Bool
for U in (Base.BitInteger_types..., BigInt,
Rational{Int}, Rational{BigInt},
Float16, Float32, Float64)
for U in (Base.BitInteger_types..., BigInt,
for T in (Base.BitInteger_types..., BigInt,
Rational{Int}, Rational{BigInt},
Float16, Float32, Float64)
@test typeof(copysign(T(3), U(4))) === T
@test typeof(flipsign(T(3), U(4))) === T
end
# Bool promotes to Int
U <: Unsigned && continue
for x in [true, false]
@test flipsign(x, U(4)) === Int(x)
@test flipsign(x, U(-1)) === -Int(x)
@test copysign(x, U(4)) === Int(x)
@test copysign(x, U(-1)) === -Int(x)
end
end

@testset "flipsign/copysign(typemin($T), -1)" for T in Base.BitInteger_types
for U in (Base.BitSigned_types..., BigInt, Float16, Float32, Float64)
@test flipsign(typemin(T), U(-1)) == typemin(T)
@test copysign(typemin(T), U(-1)) == typemin(T)
end
end

for s1 in (-1,+1), s2 in (-1,+1)
Expand Down

0 comments on commit 8e86be3

Please sign in to comment.