From 45f80a5063bde97401d2f31412e46b3ede3af411 Mon Sep 17 00:00:00 2001 From: matthias314 <56549971+matthias314@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:35:50 -0400 Subject: [PATCH] add `bitrotate` (#42) --- src/BitIntegers.jl | 7 +++++++ test/runtests.jl | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/BitIntegers.jl b/src/BitIntegers.jl index 0dd9ad7..28d5893 100644 --- a/src/BitIntegers.jl +++ b/src/BitIntegers.jl @@ -3,6 +3,7 @@ module BitIntegers import Base: &, *, +, -, <, <<, <=, ==, >>, >>>, |, ~, AbstractFloat, add_with_overflow, + bitrotate, bitstring, bswap, checked_abs, count_ones, div, flipsign, isodd, leading_zeros, mod, mul_with_overflow, ndigits0zpb, peek, promote_rule, read, rem, signed, sub_with_overflow, trailing_zeros, typemax, typemin, unsigned, write, xor @@ -358,6 +359,12 @@ end @inline <<( x::UBI, y::Int) = 0 <= y ? x << unsigned(y) : x >> unsigned(-y) @inline >>>(x::UBI, y::Int) = 0 <= y ? x >>> unsigned(y) : x << unsigned(-y) +function bitrotate(x::T, k::Integer) where {T<:XBI} + l = (sizeof(T) << 3) % UInt + k::UInt = mod(k, l) + (x << k) | (x >>> (l-k)) +end + count_ones( x::XBI) = Int(ctpop_int(x)) leading_zeros( x::XBI) = Int(ctlz_int(x)) trailing_zeros(x::XBI) = Int(cttz_int(x)) diff --git a/test/runtests.jl b/test/runtests.jl index 3c188d0..1898b5f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -257,6 +257,22 @@ end end +@testset "bit rotations" begin + for X in XInts + x = X(24) + l = 8*sizeof(X) + @test bitrotate(x, 2) == 4*x + @test bitrotate(x, l-1) == div(x, 2) + x = rand(X) + for k in (0, UInt8(13), UInt32(371), Int16(-123), Int64(-1072), BigInt(-21330)) + y = @inferred bitrotate(x, k) + @test y isa X && bitrotate(y, k) == bitrotate(x, 2*k) + k isa Signed && @test bitrotate(y, -k) == x + end + end +end + + @testset "arithmetic operations" begin for (X, Y) in TypeCombos T = promote_type(X, Y)