Re: Canonical way / best practice for 128-bit integers
- In reply to: Dimitry Andric : "Re: Canonical way / best practice for 128-bit integers"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 10 Jul 2022 04:24:47 UTC
On Sat, Jul 9, 2022 at 10:06 AM Dimitry Andric <dim@freebsd.org> wrote: > On 9 Jul 2022, at 18:26, Marc Veldman <marc@bumblingdork.com> wrote: > > > > I’m working on some bluetooth code, and that involves handling 128-bit > uuids. > > There are various ways to handle in the FreeBSD codebase, like in sdp.h: > > > > /* > > * SDP int128/uint128 parameter > > */ > > > > struct int128 { > > int8_t b[16]; > > }; > > typedef struct int128 int128_t; > > typedef struct int128 uint128_t; > > > > and in sys/dev/random/uint128.h > > > > #ifdef USE_REAL_UINT128_T > > typedef __uint128_t uint128_t; > > #define UINT128_ZERO 0ULL > > #else > > typedef struct { > > /* Ignore endianness */ > > uint64_t u128t_word0; > > uint64_t u128t_word1; > > } uint128_t; > > static const uint128_t very_long_zero = {0UL,0UL}; > > #define UINT128_ZERO very_long_zero > > #endif > > > > Is there any recommended / standard way to handle 128 bit integers in a > portable way? > > Of course recent compilers have built-in support for __int128_t and > __uint128_t, but it comes with a *lot* of caveats: not supported on all > architectures, definitely never on 32-bit ones, differences between > compilers, and even compiler versions, etc etc. > > If you want it portable, the only way is to handle them as two 64 bit > integers, and leave any arithmetic or conversion to library routines. > > I second this, especially if you want to use any of the underlying assembly code. For example, the Intel architecture supports the data type but does not support 128-bit instructions but instead requires you to shift the upper 64 bits to operate with a 64-bit instruction. I found this out when we needed to speed up the ability to walk a 128-bit bitmask (we were doing it the hard way). I wound up converting everything back to 64-bit and saw a tremendous speed up in our code. I mostly use it for defining the storage of an IP address (either IPv4 or IPv6) where storage does not need to be exceedingly tight. Also, I have only used it on Intel/AMD architectures. Back when I was working in MIPS architectures (mostly Cavium multi-core) we did not have this data type available. And I have only briefly looked at AArch64 so it may or may not be supported there. Patrick