Skip to content

Commit

Permalink
Merge pull request #13841 from MichaeLeroy/master
Browse files Browse the repository at this point in the history
Documented abs overflow behavior, added checked_abs for overflow prot…
  • Loading branch information
tkelman committed Nov 2, 2015
2 parents 9fe6037 + fbf9331 commit 59cabb6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
25 changes: 25 additions & 0 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,33 @@ copysign(x::Signed, y::Float64) = copysign(x, reinterpret(Int64,y))
copysign(x::Signed, y::Real) = copysign(x, -oftype(x,signbit(y)))

abs(x::Unsigned) = x

"""
abs(x::Signed)
The absolute value of x. When `abs` is applied to signed integers,
overflow may occur, resulting in the return of a negative value. This
overflow occurs only when `abs` is applied to the minimum
representable value of a signed integer. That is when `x ==
typemin(typeof(x))`, `abs(x) == x`, not `-x` as might be expected.
"""
abs(x::Signed) = flipsign(x,x)

"""
checked_abs(x::Signed)
The absolute value of x, with signed integer overflow error trapping.
`checked_abs` will throw an `OverflowError` when `x ==
typemin(typeof(x))`. Otherwise `checked_abs` behaves as `abs`, though
the overflow protection may impose a perceptible performance penalty.
"""
function checked_abs{T<:Signed}(x::T)
x == typemin(T) && throw(OverflowError())
abs(x)
end

~(n::Integer) = -n-1

unsigned(x::Signed) = reinterpret(typeof(convert(Unsigned,zero(x))), x)
Expand Down
7 changes: 6 additions & 1 deletion test/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ end

# checked operations

import Base: checked_add, checked_sub, checked_mul
import Base: checked_add, checked_sub, checked_mul, checked_abs
@test checked_sub(UInt(4), UInt(3)) === UInt(1)
@test_throws OverflowError checked_sub(UInt(5), UInt(6))
@test checked_mul(UInt(4), UInt(3)) === UInt(12)
Expand All @@ -138,6 +138,11 @@ else
@test_throws OverflowError checked_mul(UInt(2)^62, UInt(2)^2)
end

for T in SItypes
@test checked_abs(-one(T)) == one(T)
@test_throws OverflowError checked_abs(typemin(T))
end

# Checked operations on UInt128 are currently broken
# FIXME: #4905

Expand Down

0 comments on commit 59cabb6

Please sign in to comment.