Skip to content

Commit

Permalink
Implement generic Int->UInt shift count conversion in one place only
Browse files Browse the repository at this point in the history
  • Loading branch information
eschnett committed Feb 27, 2016
1 parent d74715e commit 78a2d09
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 15 deletions.
4 changes: 0 additions & 4 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,6 @@ end

>>>(x::BigInt, c::UInt) = x >> c

<<(x::BigInt, c::Int) = c >= 0 ? x << unsigned(c) : x >> unsigned(-c)
>>(x::BigInt, c::Int) = c >= 0 ? x >> unsigned(c) : x << unsigned(-c)
>>>(x::BigInt, c::Int) = c >= 0 ? x >>> unsigned(c) : x << unsigned(-c)



trailing_zeros(x::BigInt) = Int(ccall((:__gmpz_scan1, :libgmp), Culong, (Ptr{BigInt}, Culong), &x, 0))
Expand Down
28 changes: 17 additions & 11 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ end
const .≤ = .<=
const .≠ = .!=

# core << >> and >>> takes Int as second arg
# Core <<, >>, and >>> take either Int or UInt as second arg. Signed shift
# counts can shift in either direction, and are translated here to unsigned
# counts. Integer datatypes only need to implement the unsigned version.

"""
<<(x, n)
Expand All @@ -146,12 +149,13 @@ julia> bits(Int8(12))
```
See also [`>>`](:func:`>>`), [`>>>`](:func:`>>>`).
"""
function <<(x,y::Integer)
typemin(Int) <= y <= typemax(Int) && return x << (y % Int)
(x >= 0 || y >= 0) && return zero(x)
function <<(x, c::Integer)
typemin(Int) <= c <= typemax(Int) && return x << (c % Int)
(x >= 0 || c >= 0) && return zero(x)
oftype(x, -1)
end
<<(x,y::Unsigned) = y <= typemax(UInt) ? x << (y % UInt) : zero(x)
<<(x, c::Unsigned) = c <= typemax(UInt) ? x << (c % UInt) : zero(x)
<<(x, c::Int) = c >= 0 ? x << unsigned(c) : x >> unsigned(-c)

"""
>>(x, n)
Expand Down Expand Up @@ -183,12 +187,13 @@ julia> bits(Int8(-4))
```
See also [`>>>`](:func:`>>>`), [`<<`](:func:`<<`).
"""
function >>(x,y::Integer)
typemin(Int) <= y <= typemax(Int) && return x >> (y % Int)
(x >= 0 || y < 0) && return zero(x)
function >>(x, c::Integer)
typemin(Int) <= c <= typemax(Int) && return x >> (c % Int)
(x >= 0 || c < 0) && return zero(x)
oftype(x, -1)
end
>>(x,y::Unsigned) = y <= typemax(UInt) ? x >> (y % UInt) : zero(x)
>>(x, c::Unsigned) = c <= typemax(UInt) ? x >> (c % UInt) : zero(x)
>>(x, c::Int) = c >= 0 ? x >> unsigned(c) : x << unsigned(-c)

"""
>>>(x, n)
Expand All @@ -215,8 +220,9 @@ is equivalent to [`>>`](:func:`>>`).
See also [`>>`](:func:`>>`), [`<<`](:func:`<<`).
"""
>>>(x,y::Integer) = typemin(Int) <= y <= typemax(Int) ? x >>> (y % Int) : zero(x)
>>>(x,y::Unsigned) = y <= typemax(UInt) ? x >>> (y % UInt) : zero(x)
>>>(x, c::Integer) = typemin(Int) <= c <= typemax(Int) ? x >>> (c % Int) : zero(x)
>>>(x ,c::Unsigned) = c <= typemax(UInt) ? x >>> (c % UInt) : zero(x)
>>>(x, c::Int) = c >= 0 ? x >>> unsigned(c) : x << unsigned(-c)

# fallback div, fld, and cld implementations
# NOTE: C89 fmod() and x87 FPREM implicitly provide truncating float division,
Expand Down

0 comments on commit 78a2d09

Please sign in to comment.