{"action":"created","issue":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/14516","labels_url":"https://api.github.com/repos/JuliaLang/julia/issues/14516/labels{/name}","comments_url":"https://api.github.com/repos/JuliaLang/julia/issues/14516/comments","events_url":"https://api.github.com/repos/JuliaLang/julia/issues/14516/events","html_url":"https://github.com/JuliaLang/julia/issues/14516","id":124424063,"number":14516,"title":"Negative shift counts could be handled better","user":{"login":"eschnett","id":213514,"avatar_url":"https://avatars.githubusercontent.com/u/213514?v=3","gravatar_id":"","url":"https://api.github.com/users/eschnett","html_url":"https://github.com/eschnett","followers_url":"https://api.github.com/users/eschnett/followers","following_url":"https://api.github.com/users/eschnett/following{/other_user}","gists_url":"https://api.github.com/users/eschnett/gists{/gist_id}","starred_url":"https://api.github.com/users/eschnett/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eschnett/subscriptions","organizations_url":"https://api.github.com/users/eschnett/orgs","repos_url":"https://api.github.com/users/eschnett/repos","events_url":"https://api.github.com/users/eschnett/events{/privacy}","received_events_url":"https://api.github.com/users/eschnett/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":10,"created_at":"2015-12-31T02:20:57Z","updated_at":"2016-01-01T21:13:00Z","closed_at":null,"body":"Julia allows both signed and unsigned shift counts, e.g for the operator `<<`. Signed counts are implicitly reinterpreted as unsigned counts, i.e. shifting by a negative value corresponds to shifting by a very large positive value, leaving as result either `0` or `-1` (for `>>`). This implicit conversion not ideal. It would also be very unusual to have code that finds this behaviour useful.\r\n\r\nI can think of three possible alternatives:\r\n- The \"obvious\": left-shifting by a negative amount is interpreted as a corresponding right-shift\r\n- Explicitly convert from signed to unsigned, thus with a run-time error for negative values\r\n- Require the shift count to be explicitly unsigned (very inconvenient, I don't really suggest this)\r\n\r\nIn many cases, the shift count is known at compile time, and I expect the compiler to produce optimal code in this case. Experiments confirm this. I thus expect performance differences (if any) only for variable shift counts.\r\n\r\nCurrent CPU architectures don't have direction-agnostic instructions, so option 1 would require a case distinction in the general case. There is already a case distinctions e.g. on x86 (and probably many other architectures), since the machine shift instructions behave differently from what Julia specifies, and thus there is a branch statement or equivalent in the code. Adding one more branch for unknown, signed shifts might not be that bad.\r\n\r\nI looked at how shifts are used in Base. In the vast majority of cases, the shift is directly known, and the compiler can generate optimal code. In a few cases, the shift is calculated, e.g. `io.jl`, line 136:\r\n```Julia\r\n    for n = 1:sizeof(x)\r\n        x |= (convert(T,read(s,UInt8))<<((n-1)<<3))\r\n    end\r\n```\r\nIn no case there is an `if` statement to handle both shift directions (although I need this in my code, hence my suggestion).\r\n"},"comment":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/comments/168337428","html_url":"https://github.com/JuliaLang/julia/issues/14516#issuecomment-168337428","issue_url":"https://api.github.com/repos/JuliaLang/julia/issues/14516","id":168337428,"user":{"login":"anthonyclays","id":9164065,"avatar_url":"https://avatars.githubusercontent.com/u/9164065?v=3","gravatar_id":"","url":"https://api.github.com/users/anthonyclays","html_url":"https://github.com/anthonyclays","followers_url":"https://api.github.com/users/anthonyclays/followers","following_url":"https://api.github.com/users/anthonyclays/following{/other_user}","gists_url":"https://api.github.com/users/anthonyclays/gists{/gist_id}","starred_url":"https://api.github.com/users/anthonyclays/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anthonyclays/subscriptions","organizations_url":"https://api.github.com/users/anthonyclays/orgs","repos_url":"https://api.github.com/users/anthonyclays/repos","events_url":"https://api.github.com/users/anthonyclays/events{/privacy}","received_events_url":"https://api.github.com/users/anthonyclays/received_events","type":"User","site_admin":false},"created_at":"2016-01-01T21:13:00Z","updated_at":"2016-01-01T21:13:00Z","body":"@eschnett I see. When those branches turn into simple conditional instructions, the additional branch might not be such a bad idea. Behaviour will become very much incompatible with C though, where shifting a number will only use the rightmost few bits of the second operand (e.g. shifting a 64 bit int by `65 = 0b1000001` is equivalent to a shift by `1 = 0b0000001`).\r\n\r\nSide-note: I like the idea of measuring the performance hit from the second branch by benchmarking BitArrays."}}