gdkrmr
March 14, 2018, 11:45am
1
I have the following function that takes a tuple and converts it to an unsigned integer:
function f(::Type{UInt16}, x::NTuple{2, UInt8})
x1 = 0x0001 * x[1]
x2 = 0x0100 * x[2]
x1 + x2
end
What would be the right name for f
? It used to be Base.convert
, but I think that fits the definition of type piracy, Base.reinterpret
probably too. I named it to_unsigned
for now and removed the first argument.
mauro3
March 14, 2018, 12:26pm
2
Can’t you encode your x::NTuple{2, UInt8}
in your own type:
struct TwoUInt8
x1::UInt8
x2::UInt8
end
and then define the appropriate Base.convert
method? That avoids type piracy.
gdkrmr
March 14, 2018, 1:06pm
3
that is not really an option here, because I have tuples of various lengths and want to make UInts from them. Haven’t thought about declaring my own type though, I could simply declare const NBytes{N} = NTuple{N, UInt8} where N
.
That wouldn’t solve the type piracy, that’s just an alias
If you’re using a type alias, it’s still type piracy if you’re extending a function from Base.
I kind of like mauro3
’s idea. Why is having tuples of various lengths a problem? You could just parameterize the type on N
.
Just a wild thought: what you’re doing is kind of like Base.read
, so you could do something like
struct StaticByteStream{N}
tup::NTuple{N, UInt8}
end
Base.read(s::StaticByteStream{2}, ::Type{UInt16}) = ...
Another option would be to just call your function combine
.
gdkrmr
March 14, 2018, 1:40pm
7
I was just toying around with this and found the following weird performance issue (Julia Version 0.7.0-DEV.4570):
function f(::Type{UInt16}, x::NTuple{2, UInt8})
x1 = 0x0001 * x[1]
x2 = 0x0100 * x[2]
x1 + x2
end
const NBytes{N} = NTuple{N, UInt8}
function f(::Type{UInt16}, x::NBytes{2})
x1 = 0x0001 * x[1]
x2 = 0x0100 * x[2]
x1 + x2
end
julia> @btime f(UInt16, (0x01, 0x02))
0.017 ns (0 allocations: 0 bytes)
0x0201
julia> x = NBytes((0x01, 0x02))
(0x01, 0x02)
julia> @btime f(UInt16, $x)
1.690 ns (0 allocations: 0 bytes)
0x0201
gdkrmr
March 14, 2018, 1:42pm
8
Seeing that there is no one best solution I will probably give it a separate name.
The “fast” one isn’t doing anything. The compiler can see the input and just optimized everything out.
gdkrmr
March 14, 2018, 5:37pm
10
I tried several versions of this function and it is pretty impressive what the compiler can optimize out in Julia 0.7 compared to 0.6.
Why does reinterpret not work on tuples, for me this would seem like the most obvious choice for something like this?
gdkrmr
March 17, 2018, 5:14pm
11
Is there a zero overhead way to do this the other way round? the best I could come up with is the following:
function to_byte_tuple(x::T) where T <: Unsigned
ntuple(i -> (x >> (8 * (i - 1))) % UInt8, sizeof(T))
end