# How to define an efficient \`bswap\_int\` for user defined primitive types?

**URL:** https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051
**Category:** Performance
**Created:** [December 28, 2017, 11:05pm UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051 "2017-12-28T23:05:17Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)
#### Post date: [December 28, 2017, 11:05pm UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/1 "2017-12-28T23:05:17Z")

</div>

I am trying to define my own primitive type of bit-length `8*n` for some `n`, e.g. below I have `n=3`.  
The functions `lshr_int` and `shl_int` works directly on the newly-defined type but not `bswap_int`. I tried to check its definition using `@which bswap_int(UInt(888))` and I see that it’s an intrinsic function so I can’t look at its implementation for `UInt` and try to adapt it.

I can build my own `bswap_int` using `lshr_int` and `shl_int` and `|` but is there a more efficient way?

```julia
primitive type UInt24 <: Unsigned 24 end
x = unsafe_load(Ptr{UInt24}(pointer("abc")))

# bitshifts work fine
Base.lshr_int(x, 8)
Base.shl_int(x, 8)

# this will crash 
Base.bswap_int(x)

```

The background is that I am trying to build a more efficient string radixsort so being able to load the underlying bits of various length efficiently is key.

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [January 4, 2018, 5:07pm UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/2 "2018-01-04T17:07:39Z")

</div>

The fastest way to do it is using shifts:  
`((x & 0xff) << 16) | (x & 0xff00) | ((x & 0xff0000) >> 16)`

---

<div class="post-metadata">

### Author: ![gdkrmr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdkrmr/32/2791_2.png) [@gdkrmr](https://discourse.julialang.org/u/gdkrmr)
#### Post date: [January 4, 2018, 8:24pm UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/3 "2018-01-04T20:24:08Z")

</div>

I get the following error:

```julia
julia> x & 0xff
ERROR: no promotion exists for UInt24 and UInt8
Stacktrace:

```

---

<div class="post-metadata">

### Author: ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)
#### Post date: [January 4, 2018, 8:31pm UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/4 "2018-01-04T20:31:55Z")

</div>

Actually if I define a type whose length is a multiple of word size then bitswap\_int works fine. E.g.

```julia
primitive type Bits192 192 end
tmp = "abcdefedghiklmnopqrstuvwz"
a = unsafe_load(Ptr{Bits192}(pointer(tmp)))
Base.bswap_int(a)

```

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [January 5, 2018, 6:34am UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/5 "2018-01-05T06:34:03Z")

</div>

I’m kind of unclear on what the benefit of a 24-bit integer type is. It doesn’t save space in registers and doesn’t save storage on disk unless you sacrifice decent alignment altogether which doesn’t seem worth it.

---

<div class="post-metadata">

### Author: ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)
#### Post date: [January 5, 2018, 6:51am UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/6 "2018-01-05T06:51:31Z")

</div>

it was just an example. i was trying to make a type that can load 3 bytes  
at once from a string using unsafe\_load. Also SAS has a 24bit numeric type  
of for reading sas data this might become helpful.

the other examples i tried were 192 bits type.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [January 5, 2018, 6:53am UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/7 "2018-01-05T06:53:36Z")

</div>

It’s certainly doable but it would probably be easier to load bytes individually and put them into a standard integer type like you would in C.

---

<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: [January 5, 2018, 7:02am UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/8 "2018-01-05T07:02:37Z")

</div>

A number of people have brought up their use cases for 24-bit numbers (such as representing RGB colors)  
Using 33% more space (in memory or on disk) can end up affecting performance more than alignment issues (which generally aren’t even issues on most processors these days).

Better to actually get real evidence rather than stating opinions without the data to back them up.

---

<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: [January 5, 2018, 7:05am UTC](https://discourse.julialang.org/t/how-to-define-an-efficient-bswap-int-for-user-defined-primitive-types/8051/9 "2018-01-05T07:05:48Z")

</div>

If you can guarantee that reading one byte past the end is safe (which isn’t that hard to do, by simply allocating a buffer one byte larger than needed), then you can simply do an unaligned 32-bit read and a mask faster than doing loading 3 bytes individually.  
Even when you can’t, I’ve seen that LLVM optimizes a 24-bit load or store into two operations, a 16-bit one and an 8-bit one.
