Let’s say I have an array of 2 elements of UInt8.
I need to make it into a single element of UInt16.
How?
I thought about doing bit arithmetic (shifting/or’ing) but there’s got to be an easier way?
Let’s say I have an array of 2 elements of UInt8.
I need to make it into a single element of UInt16.
How?
I thought about doing bit arithmetic (shifting/or’ing) but there’s got to be an easier way?
You reinterpret
e.g.
reinterpret(UInt16, UInt8[1,2])
And if your source has a fixed endianness that might be different from the host byte order of your machine, you can use ntoh
, hton
, ltoh
, and htol
from base/io.jl
to convert. E.g. i use this to read a 16-bit big-endian scalar value from the UInt8 array x
:
ntoh(reinterpret(UInt16, x[1:2])[1])
Using arrays to do a little bit of bit manipulation is going to be very inefficient! This is not very hard to write with bit operations:
julia> bitcat(a::UInt8, b::UInt8) = (UInt16(a) << 8) | b
bitcat (generic function with 1 method)
julia> bitcat(0x12, 0x34)
0x1234
julia> @code_native bitcat(0x12, 0x34)
.section __TEXT,__text,regular,pure_instructions
; Function bitcat {
; Location: REPL[23]:1
shll $8, %edi
movzbl %sil, %eax
orl %edi, %eax
retq
nopw (%rax,%rax)
;}
Stefan’s remark proven
julia> bitcat(a::UInt8, b::UInt8) = (UInt16(a) << 8) | b
bitcat (generic function with 1 method)
julia> bitcat(x::Vector{UInt8}) = (UInt16(x[1]) << 8) | x[2]
bitcat (generic function with 2 methods)
Comparing reinterpret
, bitcat
taking individual arguments, and bitcat
taking an array:
julia> @btime reinterpret(UInt16, [0x12, 0x34])
78.048 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412
julia> @btime reinterpret(UInt16, [0x12, 0x34])
78.280 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412
julia> @btime reinterpret(UInt16, [0x12, 0x34])
77.307 ns (3 allocations: 176 bytes)
1-element Array{UInt16,1}:
0x3412
julia> @btime bitcat([0x12, 0x34])
39.327 ns (1 allocation: 96 bytes)
0x1234
julia> @btime bitcat([0x12, 0x34])
39.276 ns (1 allocation: 96 bytes)
0x1234
julia> @btime bitcat([0x12, 0x34])
39.401 ns (1 allocation: 96 bytes)
0x1234
julia> @btime bitcat(0x12, 0x34)
1.760 ns (0 allocations: 0 bytes)
0x1234
julia> @btime bitcat(0x12, 0x34)
1.759 ns (0 allocations: 0 bytes)
0x1234
julia> @btime bitcat(0x12, 0x34)
1.760 ns (0 allocations: 0 bytes)
0x1234
Actually I’m surprised that the array version is only 20x slower. If you’re using @btime
for timing I think you can just do it once since the whole purpose of that macro is to run something enough times for you automatically – and note that it seems to be working since the measurements of the same operation are all similar.
Do be careful with
@btime bitcat([0x12, 0x34])
Note that
julia> @btime bitcat($([0x12, 0x34]))
1.791 ns (0 allocations: 0 bytes)
0x1234
and
julia> @btime bitcat(x) setup = x = rand(UInt8, 2)
1.737 ns (0 allocations: 0 bytes)
0xd87b
See BenchmarkTools docs.