From eac74117c52e098489a06157ec8701d4b861dc54 Mon Sep 17 00:00:00 2001 From: Jeffrey Lin Date: Fri, 21 Feb 2020 15:58:46 +0000 Subject: [PATCH] Add bitrotate function (issue #11592) (#33937) --- NEWS.md | 1 + base/exports.jl | 1 + base/int.jl | 29 +++++++++++++++++++++++++++++ doc/src/base/math.md | 1 + test/int.jl | 16 ++++++++++++++++ 5 files changed, 48 insertions(+) diff --git a/NEWS.md b/NEWS.md index 459f4414c9e4d..1da9e0e11c549 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,7 @@ New library functions * `include` now accepts an optional `mapexpr` first argument to transform the parsed expressions before they are evaluated ([#34595]). * New function `bitreverse` for reversing the order of bits in a fixed-width integer ([#34791]). +* New function `bitrotate(x, k)` for rotating the bits in a fixed-width integer ([#33937]). New library features -------------------- diff --git a/base/exports.jl b/base/exports.jl index e5346c56701a9..2b428dae046f7 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -221,6 +221,7 @@ export big, binomial, bitreverse, + bitrotate, bswap, cbrt, ceil, diff --git a/base/int.jl b/base/int.jl index ea6fbe58563a9..169adf424abc9 100644 --- a/base/int.jl +++ b/base/int.jl @@ -452,6 +452,35 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool) end end +## integer bitwise rotations ## + +""" + bitrotate(x::Base.BitInteger, k::Integer) + +`bitrotate(x, k)` implements bitwise rotation. +It returns the value of `x` with its bits rotated left `k` times. +A negative value of `k` will rotate to the right instead. + +!!! compat "Julia 1.5" + This function requires Julia 1.5 or later. + +```jldoctest +julia> bitrotate(UInt8(114), 2) +0xc9 + +julia> bitstring(bitrotate(0b01110010, 2)) +"11001001" + +julia> bitstring(bitrotate(0b01110010, -2)) +"10011100" + +julia> bitstring(bitrotate(0b01110010, 8)) +"01110010" +``` +""" +bitrotate(x::T, k::Integer) where {T <: BitInteger} = + (x << ((sizeof(T) << 3 - 1) & k)) | (x >>> ((sizeof(T) << 3 - 1) & -k)) + # @doc isn't available when running in Core at this point. # Tuple syntax for documentation two function signatures at the same time # doesn't work either at this point. diff --git a/doc/src/base/math.md b/doc/src/base/math.md index 6947f6ecc5ea3..511e2e6207fc4 100644 --- a/doc/src/base/math.md +++ b/doc/src/base/math.md @@ -32,6 +32,7 @@ Base.denominator Base.:(<<) Base.:(>>) Base.:(>>>) +Base.bitrotate Base.:(:) Base.range Base.OneTo diff --git a/test/int.jl b/test/int.jl index 383849b221d2d..0ed8f3f771912 100644 --- a/test/int.jl +++ b/test/int.jl @@ -190,6 +190,22 @@ end end end end + +@testset "bit rotations" begin + val1 = 0b01100011 + @test 0b00011011 === bitrotate(val1, 3) + @test 0b01101100 === bitrotate(val1, -3) + @test val1 === bitrotate(val1, 0) + + for T in Base.BitInteger_types + @test val1 === bitrotate(val1, sizeof(T) * 8) === bitrotate(val1, sizeof(T) * -8) + end + + val2 = 0xabcd + @test 0x5e6d == bitrotate(val2, 3) + @test 0xb579 == bitrotate(val2, -3) +end + @testset "widen/widemul" begin @test widen(UInt8(3)) === UInt16(3) @test widen(UInt16(3)) === UInt32(3)