-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Add internal top_set_bit
function
#47523
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
Conversation
I had need of such a function on occasions. With this being documented I assume its stable and can't be removed in future versions, right? |
EDIT: No. Sorry, it will not be documented; see the discussion below. You can use |
I think we should probably triage this to bike-shop the name. |
Triage is 1:15am my time, so I will not be joining you, but that seems like a good idea. |
Seems like this could be exported given that |
Ideally this would be called |
If needed we can also call it |
|
The concern about julia> code_llvm(Tuple{Int}) do x
ndigits(x, base=2)
end
; @ REPL[7]:2 within `#5`
define i64 @"julia_#5_386"(i64 signext %0) #0 {
top:
; ┌ @ intfuncs.jl:658 within `ndigits##kw`
; │┌ @ intfuncs.jl:658 within `#ndigits#426`
%1 = call i64 @j_ndigits0z_388(i64 signext %0, i64 signext 2) #0
; ││┌ @ promotion.jl:488 within `max`
; │││┌ @ essentials.jl:489 within `ifelse`
%2 = icmp sgt i64 %1, 1
%3 = select i1 %2, i64 %1, i64 1
; └└└└
ret i64 %3
}
julia> @benchmark ndigits(x, base=2) setup=(x=rand(1:10000))
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 4.740 ns … 8.200 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 5.390 ns ┊ GC (median): 0.00%
Time (mean ± σ): 5.137 ns ± 0.394 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▅ █
█▂▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂█▄▂▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▂▁▂▂▂▂▁▁▂▂ ▂
4.74 ns Histogram: frequency by time 6.01 ns <
Memory estimate: 0 bytes, allocs estimate: 0. I wonder if anyone is missing the julia> used_bits(x::Base.BitInteger) = 8sizeof(x) - leading_zeros(x)
used_bits (generic function with 2 methods)
julia> code_llvm(Tuple{Int}) do x
used_bits(x)
end
; @ REPL[13]:2 within `#9`
define i64 @"julia_#9_954"(i64 signext %0) #0 {
top:
; ┌ @ REPL[12]:1 within `used_bits`
; │┌ @ int.jl:421 within `leading_zeros`
%1 = call i64 @llvm.ctlz.i64(i64 %0, i1 false)
; │└
; │┌ @ int.jl:86 within `-`
%2 = sub nuw nsw i64 64, %1
; └└
ret i64 %2
}
julia> @benchmark used_bits(x) setup=(x=rand(1:10000))
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
Range (min … max): 1.940 ns … 4.940 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 1.950 ns ┊ GC (median): 0.00%
Time (mean ± σ): 1.951 ns ± 0.062 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
█
▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁█ ▂
1.94 ns Histogram: frequency by time 1.95 ns <
Memory estimate: 0 bytes, allocs estimate: 0. |
These 2ns matter a lot. Uses for this include things like |
Would it be easier if for the time being the proposed |
Yes please. Always do things incrementally if possible imo. |
Thanks! This all seems quite sensible. I was unaware of the existing I named the function |
I'm slightly worried that I will never remember that name. |
Is inconsistency with |
arg. Triage missed that. technically this corresponds to |
top_set_bit |
top_set_bit
function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me and can be merged when green as far as I'm concerned. We might want to have a slightly broader name discussion before considering exporting, but I do think this would be a pretty hand function to export.
julia> top_set_bit(-1) | ||
64 | ||
""" | ||
top_set_bit(x::BitInteger) = 8sizeof(x) - leading_zeros(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
top_set_bit(x::BitInteger) = 8sizeof(x) - leading_zeros(x) | |
top_set_bit(x::BitInteger) = 8*sizeof(x) - leading_zeros(x) |
Needs a rebase. |
Issue: MutableArithmetics for SparseArrays is broken on nightly Julia because SparseArrays.ilog2 doesn't exist anymore. This adds the function _top_set_bit and uses it instead of ilog2. See JuliaSparse/SparseArrays.jl#324 and JuliaLang/julia#47523
At least 17 out of the 36 uses of
leading_zeros
in base are an attempt to compute how many bits are used. This PR defines that function explicitly and documents it for increased robustness and ease of use.