Concatenate four 8-bit unsigned ints into one 32-bit unsigned int
Given an array of four 8-bit unsigned integers, such as a 32-bit RGBA color
rgba = [255, 255, 255, 255] # white
What's the most efficient way to combine these four Fixnums into one 32-bit Integer ?
I am currently using a package and unpacking:
rgba.pack('C*').unpack('L')[0] #=> 4294967295
# Check work: same value as corresponding hex literal
0xffffffff #=> 4294967295
but I'm wondering if there is a more efficient way. I found this question in C ++:
Cleanest way to combine two shorts into int
and I think that <<
is "shift" and a |
is "mask", but I don't know enough about these operators and have never used them in ruby.
source to share
Move each element by 24 - (index * 8), then OR all together:
rgba = [255, 255, 255, 255] rgba[0] << 24 | rgba[1] << 16 | rgba[2] << 8 | rgba[3]
I didn't shift rgba[3]
because offset by zero has no effect.
Some measurements:
Using unpack
Benchmark.measure do
100_000.times do
rgba = [255, 255, 255, 255]
rgba.pack('C*').unpack('L')[0]
end
end
Result:
=> #<Benchmark::Tms:0x007fe137005350
@cstime=0.0,
@cutime=0.0,
@label="",
@real=0.146899,
@stime=0.0,
@total=0.1399999999999999,
@utime=0.1399999999999999>
Using bitwise operators
Benchmark.measure do
100_100.times do
rgba = [255, 255, 255, 255]
rgba[0] << 24 | rgba[1] << 16 | rgba[2] << 8 | rgba[3]
end
end
Result:
=> #<Benchmark::Tms:0x007fd66438fd28
@cstime=0.0,
@cutime=0.0,
@label="",
@real=0.088995,
@stime=0.0,
@total=0.08000000000000007,
@utime=0.08000000000000007>
source to share