# Convert UInt16 to two UInt8

**URL:** https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115
**Category:** New to Julia
**Created:** [November 17, 2017, 8:20am UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115 "2017-11-17T08:20:27Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![wrgr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wrgr/32/2796_2.png) [@wrgr](https://discourse.julialang.org/u/wrgr)
#### Post date: [November 17, 2017, 8:20am UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/1 "2017-11-17T08:20:27Z")

</div>

Could anybody help to figure out this seemingly simple problem:

```julia
# UInt16 number
a = 0xabcd
# imaginary function split()
b, c = split(a)
# b = 0xab
# c = 0xcd

```

I’ve tried to use `reinterpret` with bits shifting, but got

```julia
bitcast: argument size does not match size of target typ

```

Doing something like

```julia
UInt8(a)

```

yields `InexactError`. How do I need to write this function?

```julia
split(a::UInt16)::Tuple{UInt8, UInt8} = ...

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 17, 2017, 9:05am UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/2 "2017-11-17T09:05:16Z")

</div>

```julia
UInt8(a >> 8)
UInt8(a & 0xff)

```

---

<div class="post-metadata">

### Author: ![wrgr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wrgr/32/2796_2.png) [@wrgr](https://discourse.julialang.org/u/wrgr)
#### Post date: [November 17, 2017, 12:27pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/3 "2017-11-17T12:27:22Z")

</div>

Excellent, so if every other bit is 0, no `InexactError`. Is it possible to do the same using some low-level functions, to remove the checking for 0 overhead?

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [November 17, 2017, 12:39pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/4 "2017-11-17T12:39:10Z")

</div>

On 0.7 this works:

```julia
julia> function test(x::UInt16)
       unsafe_load(Ptr{NTuple{2, UInt8}}(Base.unsafe_convert(Ptr{UInt16}, Ref(x))))
       end
test (generic function with 3 methods)

julia> test(UInt16(2))
(0x02, 0x00)

julia> @btime test(UInt16(2))
  1.263 ns (0 allocations: 0 bytes)
(0x02, 0x00)

```

A bit ugly for my taste, since reinterpret doesn’t work on Ref… Maybe I miss some function that works on Ref which would make this nicer.

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [November 17, 2017, 12:40pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/5 "2017-11-17T12:40:44Z")

</div>

I think that the following may work better:

```julia
(a>>>8)%UInt8
a%UInt8

```

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [November 17, 2017, 12:41pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/6 "2017-11-17T12:41:00Z")

</div>

Explanation: you should only take a pointer from a ref in Julia code, but on 0.6 this allocates the Ref. Since the ref doesn’t escape the function and escape analysis got a lot better on 0.7, this generates pretty optimal code on 0.7, though 🙂

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 17, 2017, 12:41pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/7 "2017-11-17T12:41:38Z")

</div>

Not sure what checking you are talking about:

```julia
julia> f(a) = UInt8(0xff & a)
f (generic function with 1 method)

julia> @code_llvm f(0xabcd)

define i8 @julia_f_63099(i16) #0 !dbg !5 {
pass:
  %1 = trunc i16 %0 to i8
  ret i8 %1
}
julia> g(a) = UInt8(a >> 8)
g (generic function with 1 method)

julia> @code_llvm g(0xabcd)

define i8 @julia_g_63104(i16) #0 !dbg !5 {
pass:
  %1 = lshr i16 %0, 8
  %2 = trunc i16 %1 to i8
  ret i8 %2
}

```

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [November 17, 2017, 1:42pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/8 "2017-11-17T13:42:18Z")

</div>

This code is not well defined.

---

<div class="post-metadata">

### Author: ![wrgr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wrgr/32/2796_2.png) [@wrgr](https://discourse.julialang.org/u/wrgr)
#### Post date: [November 17, 2017, 7:46pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/9 "2017-11-17T19:46:18Z")

</div>

Do I understand this right: so the compiler matches the `&` mask pattern, looks at the value of constant `0x00ff` (I’ve tried it with `UInt16` mask), makes inference at compile time that the leading are 0s, and reduces it to `trunc` LLVM command? This looks like magic, but this is actually true (?). For `0x01ff` mask it produces completely another code. Wow, thanks for showing me this snippet.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [November 17, 2017, 8:27pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/10 "2017-11-17T20:27:36Z")

</div>

Yes, the inference of value range/bit pattern is a pretty standard low level optimization, the kind of optimization that LLVM is really good at.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [November 17, 2017, 8:28pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/11 "2017-11-17T20:28:12Z")

</div>

Also, if you don’t want those to start with use `v % UInt8` instead.

---

<div class="post-metadata">

### Author: ![tuckermcclure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tuckermcclure/32/1187_2.png) [@tuckermcclure](https://discourse.julialang.org/u/tuckermcclure)
#### Post date: [November 17, 2017, 8:58pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/12 "2017-11-17T20:58:23Z")

</div>

Alternate solution:

```julia
split(a) = (reinterpret(UInt8, [a])...)

c, b = split(0xabcd)
# Yields (0xcd, 0xab)

```

Note that `c` is output first; you could swap if you like.

I’m not sure why we need an array for the `reinterpret` call to work. There are a bunch of arguments in some thread somewhere, but by the end, there doesn’t seem to be any consensus about whether `reinterpret` should work on a scalar.

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [November 17, 2017, 9:52pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/13 "2017-11-17T21:52:23Z")

</div>

Note: you might want to change the “solution” to using %UInt8, as I’d suggested below, it makes a rather large difference in the generated code (tested on master built today):

> julia\> splitit(x) = (x\>\>\>8)%UInt8, x%UInt8  
> splitit (generic function with 1 method)
> 
> julia\> splitit(0x1234)  
> (0x12, 0x34)
> 
> julia\> @code\_native splitit(0x1234)  
> .section \_\_TEXT,\_\_text,regular,pure\_instructions  
> ; Function splitit {  
> ; Location: REPL[1]:1  
> movl %edi, %eax  
> shrl $8, %eax  
> movl %edi, %edx  
> retq  
> nopl (%rax,%rax)  
> ;}
> 
> julia\> split2(x) = UInt8(x\>\>8), UInt8(x & 0xff)  
> split2 (generic function with 1 method)
> 
> julia\> @code\_native split2(0x1234)  
> .section \_\_TEXT,\_\_text,regular,pure\_instructions  
> ; Function split2 {  
> ; Location: REPL[4]:1  
> pushq %rbx  
> movl %edi, %ebx  
> movabsq $jl\_get\_ptls\_states\_fast, %rax  
> callq \*%rax  
> movabsq $jl\_gc\_pool\_alloc, %rcx  
> movl $1376, %esi ## imm = 0x560  
> movl $16, %edx  
> movq %rax, %rdi  
> callq \*%rcx  
> movabsq $jl\_system\_image\_data, %rcx  
> movq %rcx, -8(%rax)  
> movbew %bx, (%rax)  
> popq %rbx  
> retq  
> nopl (%rax)  
> ;}

I am rather concerned by the huge amount of code produced for a trivial function, simply by using `UInt8(x)` instead of `x%UInt8`, I wonder if this is a regression on master?

Update: this is definitely a serious regression on master: on v0.6.1, both functions generate identical LLVM IR and (not as optimized) native code.

> julia\> @code\_llvm split2(b)
> 
> define [2 x i8] @julia\_split2\_62803(i16) #0 !dbg !5 {  
> pass2:  
> %1 = lshr i16 %0, 8  
> %2 = trunc i16 %1 to i8  
> %3 = trunc i16 %0 to i8  
> %4 = insertvalue [2 x i8] undef, i8 %2, 0  
> %5 = insertvalue [2 x i8] %4, i8 %3, 1  
> ret [2 x i8] %5  
> }
> 
> julia\> @code\_native split2(b)  
> .section \_\_TEXT,\_\_text,regular,pure\_instructions  
> Filename: REPL[1]  
> pushq %rbp  
> movq %rsp, %rbp  
> Source line: 1  
> movl %edi, %eax  
> shrl $8, %eax  
> movl %edi, %edx  
> popq %rbp  
> retq  
> nopl (%rax)

---

<div class="post-metadata">

### Author: ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)
#### Post date: [November 17, 2017, 10:04pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/14 "2017-11-17T22:04:15Z")

</div>

IIUC that behavior is a bug `@code_llvm` and should be fixed by [https://github.com/JuliaLang/julia/pull/24642/files](https://github.com/JuliaLang/julia/pull/24642/files)

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [November 17, 2017, 10:13pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/15 "2017-11-17T22:13:06Z")

</div>

Thanks very much! I’ll retest as soon as that’s merged then. This is the sort of low-level bit twiddling that I do in a lot of my code, so I was rather nervous! I also am very happy to see that the `push %ebp ; mov %esp, %ebp ; ... ; pop %ebp` stuff has finally been eliminated on master! 🙂

---

<div class="post-metadata">

### Author: ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)
#### Post date: [November 20, 2017, 3:28pm UTC](https://discourse.julialang.org/t/convert-uint16-to-two-uint8/7115/16 "2017-11-20T15:28:03Z")

</div>

It now looks fine on master, with that bug fix merged, thanks for the pointer to what was going on!
