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

Allow negative bit-shift counts #14791

Merged
merged 1 commit into from
Mar 5, 2016

Conversation

eschnett
Copy link
Contributor

This patch concerts the bit shift operators << >> >>>.

  • Convert signed bit-shift counts explicitly to unsigned, reporting InexactErrors for negative counts.
  • Introduce versions that take unsigned arguments, and which thus do not require any tests.
  • Introduce new functions bitshift and unsigned_bitshift that (similar to Matlab) shift left or right for positive and negative counts, respectively.
  • Add documentation.
  • Add tests.

Closes #14516.

@tkelman
Copy link
Contributor

tkelman commented Jan 25, 2016

unsigned_bitshift is not a name we should export. What's the simplest description of the difference between x >> -n and x >>> -n here?

@eschnett
Copy link
Contributor Author

Should we even have unsigned_bitshift? How commonly is >>> used? This function is not necessary; one can always convert to the respective unsigned type instead.

In machine language, this would be called a "logical shift".

@simonbyrne
Copy link
Contributor

We could use <> or <<> as operators?

@tkelman
Copy link
Contributor

tkelman commented Jan 25, 2016

Leaving it out sounds appropriate.

@simonbyrne
Copy link
Contributor

>>> appears 109 times in Base, >> 372.

@eschnett eschnett force-pushed the eschnett/negative-shifts branch 2 times, most recently from e462f12 to 60d4821 Compare February 11, 2016 00:04
@eschnett
Copy link
Contributor Author

Removed unsigned_bitshift, rebased.

@tkelman
Copy link
Contributor

tkelman commented Feb 11, 2016

LGTM. @StefanKarpinski what do you think?

@tkelman
Copy link
Contributor

tkelman commented Feb 11, 2016

IIUC this is breaking, so it could use a mention in NEWS.md.

@StefanKarpinski
Copy link
Member

I'm not sure. I'm somewhat more inclined to define <<, >> and >>> to work "correctly" with negative shift values – and not introduce the bitshift function. The generated code is kind of long, but potentially throwing an exception is also a total performance disaster, so anyone who's not using shift values that the compiler can reason about who cares about performance would need to do additional work anyway.

@StefanKarpinski
Copy link
Member

@JeffBezanson, thoughts?

@eschnett
Copy link
Contributor Author

Ping

@eschnett
Copy link
Contributor Author

@StefanKarpinski: It seems @JeffBezanson doesn't have input on this. What's your verdict?

@StefanKarpinski
Copy link
Member

Rather than introducing a new bitshift function, let's make negative shifts work for existing shift ops:

a  << -b == a >> b
a  >> -b == a << b
a >>> -b == a << b

I suspect that in this case, using a branch will be better than using a select instruction (ifelse) since the branch will tend to be very predictable. Otherwise keep the rest of this change – i.e. making the unsigned version fundamental, so that you can avoid the branch entirely by using an unsigned shift value.

@eschnett, do you mind modifying this PR this way (or making a new one)?

@simonbyrne
Copy link
Contributor

Rather than introducing a new bitshift function, let's make negative shifts work for existing shift ops:

+1

@carnaval
Copy link
Contributor

as long as constant shifts get folded correctly I think that's fine

@eschnett eschnett added potential benchmark Could make a good benchmark in BaseBenchmarks and removed potential benchmark Could make a good benchmark in BaseBenchmarks labels Feb 26, 2016
@eschnett
Copy link
Contributor Author

I think might be worth a benchmark.

@eschnett eschnett force-pushed the eschnett/negative-shifts branch from 60d4821 to 9a0e2b6 Compare February 26, 2016 16:43
@eschnett eschnett changed the title Forbid negative bit-shift counts Allow negative bit-shift counts Feb 26, 2016
@@ -346,23 +346,27 @@ for (fJ, fC) in ((:-, :neg), (:~, :com))
end
end

function <<(x::BigInt, c::Int)
c < 0 && throw(DomainError())
function <<(x::BigInt, c::UInt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be Culong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this Culong would force every caller to explicitly convert to Culong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I misread it (I thought it was Cuint).

What if Culong != UInt (as I think it is on Windows 64-bit): won't the implicit conversion throw an error for typemax(UInt)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly; I don't know whether ccall checks. 64-bit Linux definitely has this problem. That problem was there before, though.

I don't know a good solution -- shifting a BigInt left by a large number should work "in principle", but will in practice run out of memory. So an error message is probably the best we can do anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably true.

@eschnett eschnett force-pushed the eschnett/negative-shifts branch from ee99029 to 78a2d09 Compare February 27, 2016 15:29
@eschnett
Copy link
Contributor Author

eschnett commented Mar 1, 2016

Are there any further comments or requests? I'm ready to squash and merge.

@eschnett eschnett force-pushed the eschnett/negative-shifts branch from 6072d28 to e3d5fda Compare March 2, 2016 17:54
@eschnett
Copy link
Contributor Author

eschnett commented Mar 3, 2016

Rebased and squashed, Travis and Appveyor are green. Ready to go?

where `n >= 0`, filling with `0`s. This is equivalent to `x * 2^n`.
Left bit shift operator, `x << n`. For `n >= 0`, the result is `x` shifted left
by `n` bits, filling with `0`s. This is equivalent to `x * 2^n`. For `n < 0`,
this is equivalent to `x >> -n`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a make docs to update the rst contents

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Anything else I missed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're good.

- Introduce methods that take unsigned shift counts
- Handle signed shift counts by dispatching to the respective unsigned shift counts, shifting in the opposite direction for negative counts
- Update documentation
- Add tests

Closes JuliaLang#14516.
@eschnett eschnett force-pushed the eschnett/negative-shifts branch from e3d5fda to 5a9717b Compare March 4, 2016 14:27
eschnett added a commit that referenced this pull request Mar 5, 2016
@eschnett eschnett merged commit a505b61 into JuliaLang:master Mar 5, 2016
@tkelman
Copy link
Contributor

tkelman commented Mar 5, 2016

This seems to have introduced several ambiguity warnings during bootstrap.

@eschnett
Copy link
Contributor Author

eschnett commented Mar 5, 2016

I will check.

@eschnett
Copy link
Contributor Author

eschnett commented Mar 5, 2016

This is now PR #15368.

@eschnett eschnett deleted the eschnett/negative-shifts branch March 6, 2016 14:01
@tkelman
Copy link
Contributor

tkelman commented Aug 19, 2016

IIUC this is breaking, so it could use a mention in NEWS.md.

This was never addressed here, was it?

@tkelman tkelman added the needs news A NEWS entry is required for this change label Aug 19, 2016
@eschnett
Copy link
Contributor Author

Good catch.

@eschnett
Copy link
Contributor Author

@tkelman In what sense in this breaking? The new functionality is a strict superset of the old one. Do you refer to how one now defines bit-shift operations for user-defined types? Or do you refer to the performance difference between signed and unsigned shift counts?

@tkelman
Copy link
Contributor

tkelman commented Aug 22, 2016

None of those - weren't we previously doing the Perl behavior for #14516 (comment), so after this PR negative shifts now give different results?

@eschnett
Copy link
Contributor Author

Very good; yes, I understand now. I'll add the NEW.md entry.

@eschnett
Copy link
Contributor Author

See ##18188.

@tkelman tkelman removed the needs news A NEWS entry is required for this change label Aug 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants