# Is there a way to reinterpret a Float64 to 2 Int32?

**URL:** https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596
**Category:** Performance
**Created:** [July 23, 2020, 11:33pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596 "2020-07-23T23:33:56Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [July 23, 2020, 11:33pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596/1 "2020-07-23T23:33:56Z")

</div>

I’m writing some manually vectorize some code (for computing `exp`), and I was looking for a way to view the memory as 2 int32s (if it helps, I only need the lower one). Is there a way to do this? The reason I want Int32 rather than int64 is because I want the integer stuff to work with avx2.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [July 23, 2020, 11:57pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596/2 "2020-07-23T23:57:03Z")

</div>

```julia
julia> x = 3.0
3.0

julia> reinterpret(Int32, [x])
2-element reinterpret(Int32, ::Array{Float64,1}):
          0
 1074266112

```

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [July 24, 2020, 12:21am UTC](https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596/3 "2020-07-24T00:21:56Z")

</div>

> [@Oscar\_Smith](#):
>
> (if it helps, I only need the lower one).

```julia
julia> x = rand()
0.22542595261993403

julia> bitstring(x)
"0011111111001100110110101100000111110011000101100000110010110000"

julia> reinterpret(Int, x) % Int32
-216658768

julia> bitstring(ans)
"11110011000101100000110010110000"

```

Similarly, you can:

```julia
julia> using VectorizationBase, SIMDPirates

julia> sx = SVec(ntuple(VectorizationBase.pick_vector_width_val(Float64)) do _ Core.VecElement(10randn(Float64)) end)
SVec{8,Float64}<11.591414148467251, -16.471476122659084, -5.030081855765106, -8.60206169897962, -17.824076876082163, -12.363521352234141, 1.0686657131481578, 7.031664824493625>

julia> reinterpret(SVec{length(sx),Int}, sx) % Int32
SVec{8,Int32}<-707518984, -1463834008, -953492670, 1851168085, -1279252055, 2021555350, 939867877, -1100576536>

```

AVX2 doesn’t have instructions for SIMD

- Int64 multiplication
- Int64 → Float64 conversion
- Float64 → Int64 conversion

So you could use `Int32` if it helps you avoid these.  
But reinterpreting between SIMD vectors of `Int64` and `Float64` is perfectly fine, because it doesn’t require any operations at all.

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [July 24, 2020, 11:24pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-reinterpret-a-float64-to-2-int32/43596/4 "2020-07-24T23:24:46Z")

</div>

> [@dpsanders](#):
>
> `julia> reinterpret(Int32, [x])`

This is A way, but I find it doubtful it’s the best way, and possibly it’s buggy. I extended Elrod’s code to (his SIMD code doesn’t have the shift issue, but it (currently) ties you to x86, my code should work everywere):

```julia
other_half(x) = (reinterpret(Int, x) >> 32) % Int32

julia> @code_native other_half(x) # ok, I'm doubt the shift can be avoided.

This might be alternative code to consider:
julia> f(x) = (reinterpret(UInt64, x) & typemax(UInt32) << 32) % Int32

```

I have two concerns with your code. a) `[x]` assumes x is in memory? I guess the compiler is careful either way, but if your value is in a register it would force it stored in memory? b) It seems it depends on endianness, and the order you get is for little-endian. It could be reversed, in some theoretical (not yet supported) big-endian platform?

> **[IBM Developer](https://developer.ibm.com/articles/l-power-little-endian-faq-trs/)**
>
> IBM Developer is your one-stop location for getting hands-on training and learning in-demand skills on relevant technologies such as generative AI, data science, AI, and open source.

> [@Packing and unpacking binary data](https://discourse.julialang.org/t/packing-and-unpacking-binary-data/1638/7):
>
> Converting the UInt8 array to a string is done by String(). I tried string() before but that was not the right one. So now I am playing around with reinterpret but I need a way to deal with different endianness. So I guess I have to reverse the array if needed confused julia\> a[9:12] 4-element Array{UInt8,1}: 0x00 0x00 0x00 0x04 julia\> reinterpret(Int32, a[9:12]) 1-element Array{Int32,1}: 67108864 julia\> reinterpret(Int32, reverse(a[9:12])) 1-element Array{Int32,1}: 4

I used `@code_native` on your code, and it seems longer than I would want, and `@code_lowered` is way longer.

Similar for splitting Float32:

```julia
julia> both_half(x::Float32) = ((reinterpret(UInt32, x) >> 16), reinterpret(UInt32, x) % Int16)

```

Julia still does a shift, here by 16, and it should be avoidable, as x86 assembly has access to lower 16 bits, and higher 16 bits of the same register (but not higher 32-bits of 64 bit register without shifting), so Julia’s code generator could in theory do something slightly better (doesn’t not even on `-O3`). [I don’t see a way around it otherwise, except maybe with injecting LLVM code.] I’m assuming x86 register set and not SIMD, I just don’t recall, such likely might avoid generating a shift on x86 (in case Julia’s code generator tried to exploit such SIMD feature), even for 32-bit, and probably even ARM, without ARM would need a shift.
