I know that if I have a litteral bitstring, I can convert it to an integer with
Int(0b110101)
Now, however, I would like to convert a bit string, either given as a tuple of 0 and 1, or as an actual string, to the corresponding integer value. I figured in the tuple case, I could do something like
julia> bits2int(b::Vararg{Integer,N}) where N = sub2ind(ntuple(_->2,Val(N)),reverse(b.+1)...) - 1;
julia> Int(0b110101) == bits2int(1,1,0,1,0,1)
true
However, the above is really slow.
In the string case, I thought it might be possible to do with a string macro, but I am not sure how.
Ah right of course. Is it possible to obtain the length of the string in a type stable way (i.e. the length will go in a type parameter) using a string macro?
It sounds as if you have the string. The length of that string (its a vanilla string, presumably) is length(string) that returns the number of characters. If your leading zeros are in the string, you are done. If your strings are implicitly left padded with zeros, then you know the length already, you are done. (length(str::AbstractString} is type stable)
Is your goal to accept strings that are a sequence of 1s and 0s and then convert each string as it is available into the corresponding datapair
(stringlength, integer value of parsed string)? and then keep it in a struct
Yes, but the length should be a type parameter. Obviously, with a tuple input that length is very easy to obtain as a type parameter. I was wondering if that was possible to also do with a string.
I thought it might be possible with a macro by doing the computation of the length during compilation.
julia> struct BitStrFun{L} # L is the parameter which gets the string length
value::UInt
function BitStrFun(str::String) where {L}
value = parse(UInt, string("0b", str))
nbits = length(str)
return new{nbits}(value)
end
end
julia> a = BitStrFun("11011")
BitStrFun{5}(0x000000000000001b)
julia> a.value
0x000000000000001b
julia> a = BitStrFun("0000000000000101")
BitStrFun{16}(0x0000000000000005)
julia> struct BitStrFun2{L} # L is the parameter which gets the string length
value::Int
function BitStrFun2(str::String) where {L}
value = parse(Int, string("0b", str))
nbits = length(str)
return new{nbits}(value)
end
end
julia>
julia> a = BitStrFun2("0000000000000101")
BitStrFun2{16}(5)
julia> a.value
5
julia> nbits(x::BitStrFun2{L}) where {L} = L
nbits (generic function with 1 method)
julia> nbits(a)
16
note: the above presupposes your strings have only ones and zeros (no leading 0b); if the incoming strings are formatted with a leading 0b just replace value = parse(Int, string(.. with value = parse(Int, str)
julia> struct Bits{L}
value::Int
end
julia> macro bits_str(bits::String)
quote
Bits{$(length(bits))}($(parse(Int, bits, 2)))
end
end
@bits_str (macro with 1 method)
julia> bits"1001"
Bits{4}(9)
Since the length computation happens when the macro is expanded, the length is essentially baked into the resulting expression, and the result is type-stable:
julia> f() = bits"1001"
f (generic function with 1 method)
julia> @code_warntype f()
Variables:
#self# <optimized out>
Body:
begin
# meta: location REPL[1] # line 3:
SSAValue(0) = $(Expr(:new, Bits{4}, 9))
# meta: pop location
return SSAValue(0)
end::Bits{4}