Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ror and rol functions for rotating bits #33937

Merged
merged 1 commit into from
Feb 21, 2020
Merged

Add ror and rol functions for rotating bits #33937

merged 1 commit into from
Feb 21, 2020

Conversation

anaveragehuman
Copy link
Contributor

Closes: #11592

@ararslan
Copy link
Member

Welcome, and thanks for the contribution! This is a very nice and tidy first PR, great work. The only thing it needs is a compat annotation in the docstrings of the added functions, e.g.

!!! compat "Julia 1.4"
    This function requires Julia 1.4 or later.

@ararslan ararslan added domain:maths Mathematical functions needs compat annotation Add !!! compat "Julia x.y" to the docstring labels Nov 25, 2019
@GregPlowman
Copy link
Contributor

Could at least one of the examples show wrap-around?

@stevengj
Copy link
Member

stevengj commented Nov 25, 2019

Do we really need two functions for this, since ror(x, -k) == rol(x, k) and looks like it should produce equivalent efficiency?

Should we call it ror or just add a new method to circshift for an integer first argument as suggested here by @StefanKarpinski?

@mbauman
Copy link
Sponsor Member

mbauman commented Nov 25, 2019

This is great, thank you! It looks like constant folding can handle the mask computation:

julia> ror(x::T, k::Integer) where {T <: Integer} = (x >>> ((sizeof(T) << 3 - 1) & k)) | (x <<  ((sizeof(T) << 3 - 1) & -k))
ror (generic function with 11 methods)

julia> @code_native debuginfo=:none ror(2,1)
	.section	__TEXT,__text,regular,pure_instructions
	movl	%esi, %ecx
	rorq	%cl, %rdi
	movq	%rdi, %rax
	retq
	nopl	(%rax)

This would, of course, just rely upon duck-typing (the lack of a sizeof "quack") to throw the error for BigInt, where this operation isn't well-defined. I think that's fine, though. Are there any other downsides to this general definition?

@ararslan

This comment has been minimized.

@mbauman
Copy link
Sponsor Member

mbauman commented Nov 25, 2019

Should we call it ror or just add a new method to circshift for an integer first argument as suggested here by @StefanKarpinski?

I don't think it fits the generic definition of circshift!. We don't think of bits of an integer as "data in [a collection];" we don't use pop! to remove the first bit and shift all bits down; we don't use indexed assignment to change bits in an integer. I think it deserves its own name. Whether it needs two names, however, is worth considering.

@ararslan
Copy link
Member

That's a very good point. circshift +1 retracted.

@mbauman
Copy link
Sponsor Member

mbauman commented Nov 25, 2019

One thing that I think would be helpful would be a first-class TinyFixedSizeBitArray that just wraps a single integer and exposes its bits as elements in a fixed-size array. There have been requests for it more generally on discourse (and elsewhere) IIRC — and I'd bet that we could make circshift on such a wrapper distill down to just a rorq. :)

@vtjnash
Copy link
Sponsor Member

vtjnash commented Nov 25, 2019

I know that llvm and assembly gives these rather cryptic names (fshl and fshr, https://llvm.org/docs/LangRef.html#llvm-fshl-intrinsic), but I feel like these may be just far enough outside the standard lexicon that they should use names instead of abbreviations. Maybe rotateright and rotateleft?

We don't think of bits of an integer as "data in [a collection];" we don't use pop! to remove the first bit and shift all bits down

True, but the complementary set of shift operators (<<, >>, >>>) are generic between BitArrays and Integers.

@stevengj
Copy link
Member

stevengj commented Nov 27, 2019

I still don't understand why we need two functions here when a negative shift works fine. If we don't like circshift, maybe it could be called bitrotate?

@StefanKarpinski
Copy link
Sponsor Member

StefanKarpinski commented Nov 27, 2019

bitrotate would be fine. I think the main thing is just that ror and rol are traditional names. But the fact that the name of the test set is "bit rotate" is suggestive that bitrotate would be good.

@StefanKarpinski
Copy link
Sponsor Member

Ok, nice. I guess now the question is which way should be the default rotation direction? Is it just me or does left rotation, i.e. towards more significant bits, seem like the natural positive direction?

@StefanKarpinski
Copy link
Sponsor Member

Here are some cases of functions named bitrotate:

They all consider positive shifts to rotate left and negative shifts to rotate right. It seems like the primary reason for having left and right rotate functions is this potential ambiguity.

@anaveragehuman
Copy link
Contributor Author

Is it just me or does left rotation, i.e. towards more significant bits, seem like the natural positive direction?

I tried to keep it consistent with circshift, which rotates to the right. Do we know which is more commonly used?

@stevengj
Copy link
Member

I tried to keep it consistent with circshift, which rotates to the right.

"Left" and "right" are ambiguous labels.

circshift with a positive shift rotates towards increasing indices. The conventional "index" of a bit is in order of significance, so the analogous bitrotate would rotate left.

@StefanKarpinski
Copy link
Sponsor Member

That's also what all the versions I linked to do. It also makes more sense to me that positive bit rotation should increase the power of each bit while negative bit rotation should decrease it.

@StefanKarpinski
Copy link
Sponsor Member

I had missed that you updated this to shift bits in the right (left) direction. This looks good to me.

@StefanKarpinski StefanKarpinski added the status:triage This should be discussed on a triage call label Feb 20, 2020
base/int.jl Outdated Show resolved Hide resolved
base/int.jl Outdated Show resolved Hide resolved
@StefanKarpinski StefanKarpinski removed the needs compat annotation Add !!! compat "Julia x.y" to the docstring label Feb 20, 2020
@StefanKarpinski
Copy link
Sponsor Member

You seem to have force pushed over my merge of this, in which I tweaked the NEWS entry for bitrotate to match bitreverse more closely.

NEWS.md Outdated Show resolved Hide resolved
@StefanKarpinski StefanKarpinski removed the status:triage This should be discussed on a triage call label Feb 21, 2020
@StefanKarpinski StefanKarpinski merged commit eac7411 into JuliaLang:master Feb 21, 2020
@StefanKarpinski
Copy link
Sponsor Member

Thanks for the contribution!

birm pushed a commit to birm/julia that referenced this pull request Feb 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:maths Mathematical functions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

efficient bit rotate functions: ror, rol
9 participants