Seeking Endorsement: Boost.int128
Dear All, I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2]. A couple of questions that I anticipate: Why do we need this if we already have Boost.Multiprecision? An old compliant against Boost.Multiprecision is that the 128-bit integer types are not 16 bytes [3]. The 128-bit integer types are also incident to the arbitrary precision type rather than a dedicated implementation. This allows int128 to improve performance in places that Multiprecision can't or shouldn't which is reflected in the benchmarks [2]. Should this go in Core (or other existing lib)? I talked with Peter about this a while back, but int128 was already getting too big at the time. Now int128's include/ directory has a higher sloccount than core's, so it makes even less sense. I would rather it not go into Multiprecision, as int128 would have a module weight of up to 5 (optional dependencies), whereas Multiprecision has a module weight of 25 [4]. The design is fundamentally different than the types used in Multiprecision as well (All types are backends into a master template called number for compatibility) Why does the library have a low number of stars? This library started life as the backend for Boost.Decimal since we needed a cross platform 128-bit integer for the representation of decimal128_t as well as to perform fundamental operations with decimal64_t. You can still find a int128/ folder in Decimal that will be removed if this lib is accepted (it's a vendored version of the library now). I find these types useful for my own purposes, so I expect others will too. Please let me know if you have any questions as you take a look at the library. Thanks for your time, Matt [1] https://github.com/cppalliance/int128 [2] https://develop.int128.cpp.al/u128_benchmarks.html [3] https://stackoverflow.com/questions/41876253/boostmultiprecisionuint128-t-si... [4] https://pdimov.github.io/boostdep-report/develop/module-weights.html
Matt Borland wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128- bit integers, and built-ins, are available [2].
How does this relate to / interact with __(u)int128_t?
How does this relate to / interact with __(u)int128_t?
If __(u)int128_t exists, then all operators between those types and the boost.int128 types are defined: construction, conversion, add, sub, mul, div, etc. Same case if you have MSVC's std::_Unsigned128 or std::_Signed128 as the "builtin" 128-bit type. The alignment of the boost.int128 types is also set to match the builtin types when they exist. Internally, the boost.int128 types are a struct of two 64-bit integers regardless of the platform. Matt
Matt Borland wrote:
How does this relate to / interact with __(u)int128_t?
If __(u)int128_t exists, then all operators between those types and the boost.int128 types are defined: construction, conversion, add, sub, mul, div, etc. Same case if you have MSVC's std::_Unsigned128 or std::_Signed128 as the "builtin" 128-bit type. The alignment of the boost.int128 types is also set to match the builtin types when they exist. Internally, the boost.int128 types are a struct of two 64-bit integers regardless of the platform.
What do the operations actually do, though? Does adding boost::uint128, when __uint128_t exists, use __uint128_t addition, or does it continue to use the library implementation? Similarly, for mixed mode; what does adding boost::uint128 and __uint128_t do under the hood? (And what is the return type? I assume boost::uint128?)
Vinnie Falco wrote:
On Tue, Apr 28, 2026 at 11:07 AM Peter Dimov via Boost <boost@lists.boost.org <mailto:boost@lists.boost.org> > wrote:
...
Is there already a C++ Standards proposal for int128?
There is, yes. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3140r0.html
There is, yes.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3140r0.html
This is not active anymore. Jan's most recent proposal is the inclusion of C's _BitInt which would then reduce a 128-bit integer implementation to _BitInt(128). Matt
On Tuesday, April 28th, 2026 at 2:04 PM, Peter Dimov <pdimov@gmail.com> wrote:
Matt Borland wrote:
How does this relate to / interact with __(u)int128_t?
If __(u)int128_t exists, then all operators between those types and the boost.int128 types are defined: construction, conversion, add, sub, mul, div, etc. Same case if you have MSVC's std::_Unsigned128 or std::_Signed128 as the "builtin" 128-bit type. The alignment of the boost.int128 types is also set to match the builtin types when they exist. Internally, the boost.int128 types are a struct of two 64-bit integers regardless of the platform.
What do the operations actually do, though? Does adding boost::uint128, when __uint128_t exists, use __uint128_t addition, or does it continue to use the library implementation?
Similarly, for mixed mode; what does adding boost::uint128 and __uint128_t do under the hood? (And what is the return type? I assume boost::uint128?)
In all cases the return type is a boost::uint128 for consistency. Yes, this is typically implemented by casting both types to builtin and then casting the result back to uint128. Matt
On Tue, Apr 28, 2026 at 5:05 PM Matt Borland via Boost < boost@lists.boost.org> wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
Which Multiprecision backend did you use for the benchmarks (cpp, gmp, tom)?
A couple of questions that I anticipate:
Why do we need this if we already have Boost.Multiprecision?
An old compliant against Boost.Multiprecision is that the 128-bit integer types are not 16 bytes [3]. The 128-bit integer types are also incident to the arbitrary precision type rather than a dedicated implementation. This allows int128 to improve performance in places that Multiprecision can't or shouldn't which is reflected in the benchmarks [2].
Should this go in Core (or other existing lib)?
I talked with Peter about this a while back, but int128 was already getting too big at the time. Now int128's include/ directory has a higher sloccount than core's, so it makes even less sense. I would rather it not go into Multiprecision, as int128 would have a module weight of up to 5 (optional dependencies), whereas Multiprecision has a module weight of 25 [4]. The design is fundamentally different than the types used in Multiprecision as well (All types are backends into a master template called number for compatibility)
I appreciate the detailed explanations here. However, I can imagine users of Multiprecision might grumble about having to use two different libraries to get, for example, extended float and int28. I would emphasize the benefits in the docs to try to mitigate this.
Why does the library have a low number of stars?
This library started life as the backend for Boost.Decimal since we needed a cross platform 128-bit integer for the representation of decimal128_t as well as to perform fundamental operations with decimal64_t. You can still find a int128/ folder in Decimal that will be removed if this lib is accepted (it's a vendored version of the library now). I find these types useful for my own purposes, so I expect others will too.
Please let me know if you have any questions as you take a look at the library.
Thanks for your time, Matt
[1] https://github.com/cppalliance/int128
[2] https://develop.int128.cpp.al/u128_benchmarks.html
[3] https://stackoverflow.com/questions/41876253/boostmultiprecisionuint128-t-si...
[4] https://pdimov.github.io/boostdep-report/develop/module-weights.html _______________________________________________ Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/FTHD7S6D...
Which Multiprecision backend did you use for the benchmarks (cpp, gmp, tom)?
I used the fixed-precision cpp_int types as they are the most closely analogous, and they are portable for those that want to run the benchmarks themselves.
A couple of questions that I anticipate:
Why do we need this if we already have Boost.Multiprecision?
An old compliant against Boost.Multiprecision is that the 128-bit integer types are not 16 bytes [3]. The 128-bit integer types are also incident to the arbitrary precision type rather than a dedicated implementation. This allows int128 to improve performance in places that Multiprecision can't or shouldn't which is reflected in the benchmarks [2].
Should this go in Core (or other existing lib)?
I talked with Peter about this a while back, but int128 was already getting too big at the time. Now int128's include/ directory has a higher sloccount than core's, so it makes even less sense. I would rather it not go into Multiprecision, as int128 would have a module weight of up to 5 (optional dependencies), whereas Multiprecision has a module weight of 25 [4]. The design is fundamentally different than the types used in Multiprecision as well (All types are backends into a master template called number for compatibility)
I appreciate the detailed explanations here. However, I can imagine users of Multiprecision might grumble about having to use two different libraries to get, for example, extended float and int28. I would emphasize the benefits in the docs to try to mitigate this.
Can do. I actually have one convert from Multiprecision to int128 from a recent iteration of the issue asking about cpp_int being 24 bytes. Matt
Matt Borland wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128- bit integers, and built-ins, are available [2].
I endorse this library.
On Tuesday, April 28th, 2026 at 4:04 PM, Peter Dimov via Boost <boost@lists.boost.org> wrote:
Matt Borland wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128- bit integers, and built-ins, are available [2].
I endorse this library.
Thank you Peter. Arnaud Bechler has graciously offered to manage the review, so we will get this on the calendar in short order. Matt
> I am seeking endorsement for review of my> library int128 [1].
I endorse (u)int128.
It should be a library, on its own, and beseparate from Boost.Core.
Its purpose is to provide (u)int128_t forall platforms, and is seamless if theplatform already has 128.
It is not a Multiprecision type. In fact,it much more closely resembles (u)int64_t(which is also kind of new in my world)
Clients of Boost.Multiprecision willhopefully not confuse this with a synthesizedMultiprecision type. If confusion exists, it caneasily be cleared up in ensuing chats or issues.
This type (these types) is/are intendedto provide a native-like type.
- Christopher
On Tuesday, April 28, 2026 at 07:04:28 PM GMT+2, Matt Borland via Boost <boost@lists.boost.org> wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
A couple of questions that I anticipate:
Why do we need this if we already have Boost.Multiprecision?
An old compliant against Boost.Multiprecision is that the 128-bit integer types are not 16 bytes [3]. The 128-bit integer types are also incident to the arbitrary precision type rather than a dedicated implementation. This allows int128 to improve performance in places that Multiprecision can't or shouldn't which is reflected in the benchmarks [2].
Should this go in Core (or other existing lib)?
I talked with Peter about this a while back, but int128 was already getting too big at the time. Now int128's include/ directory has a higher sloccount than core's, so it makes even less sense. I would rather it not go into Multiprecision, as int128 would have a module weight of up to 5 (optional dependencies), whereas Multiprecision has a module weight of 25 [4]. The design is fundamentally different than the types used in Multiprecision as well (All types are backends into a master template called number for compatibility)
Why does the library have a low number of stars?
This library started life as the backend for Boost.Decimal since we needed a cross platform 128-bit integer for the representation of decimal128_t as well as to perform fundamental operations with decimal64_t. You can still find a int128/ folder in Decimal that will be removed if this lib is accepted (it's a vendored version of the library now). I find these types useful for my own purposes, so I expect others will too.
Please let me know if you have any questions as you take a look at the library.
Thanks for your time,
Matt
[1] https://github.com/cppalliance/int128
[2] https://develop.int128.cpp.al/u128_benchmarks.html
[3] https://stackoverflow.com/questions/41876253/boostmultiprecisionuint128-t-sizeof-is-24
[4] https://pdimov.github.io/boostdep-report/develop/module-weights.html_______________________________________________
Boost mailing list -- boost@lists.boost.org
To unsubscribe send an email to boost-leave@lists.boost.org
https://lists.boost.org/mailman3/lists/boost.lists.boost.org/
Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/FTHD7S6DHZFHRKVDFUVN7QOANA7P4E5U/
I endorse (u)int128.
Thank you Chris.
It should be a library, on its own, and be separate from Boost.Core.
Its purpose is to provide (u)int128_t for all platforms, and is seamless if the platform already has 128.
It is not a Multiprecision type. In fact, it much more closely resembles (u)int64_t (which is also kind of new in my world)
Clients of Boost.Multiprecision will hopefully not confuse this with a synthesized Multiprecision type. If confusion exists, it can easily be cleared up in ensuing chats or issues.
I've opened an issue to explain why this is separate, and should stay separate from Multiprecision. Matt
On 28 Apr 2026 20:02, Matt Borland via Boost wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
I would find this library useful. I have doubts regarding the signed/unsigned comparison behavior deviation described here: https://develop.int128.cpp.al/uint128_t.html#uint128_t_sign_compare_behavior... While I understand the reasons for wanting to implement comparison this way, I thing I would rather prefer to keep the behavior consistent with the rest of integer types. That is, make it the same as for built-in integer types. Yes, I understand this may produce surprising results to some, but IMHO, consistency is more important, as it eliminates a special case in the user's mental model. And the result is no longer surprising once you learn how comparisons work in C++, which you must learn anyway for built-in integer types. Also, I don't quite understand what you are saying in these two sections: https://develop.int128.cpp.al/uint128_t.html#u128_operator_behavior https://develop.int128.cpp.al/int128_t.html#i128_operator_behavior In one place you're saying you convert signed to unsigned to perform the operation, in the other - the other way around. Which way is it? I would expect the operators to work the same way regardless of the order of signed/unsigned arguments, and to follow the rules for the built-in integer types (i.e. to convert signed to unsigned).
I have doubts regarding the signed/unsigned comparison behavior deviation described here:
https://develop.int128.cpp.al/uint128_t.html#uint128_t_sign_compare_behavior...
While I understand the reasons for wanting to implement comparison this way, I thing I would rather prefer to keep the behavior consistent with the rest of integer types. That is, make it the same as for built-in integer types.
It is the same behavior as the built-in types have when you set -Werror -Wsign-conversion -Wconversion which I think is uncontroversial to say is best practice. If this is behavior is removed from the library, then when a user does set the aforementioned flags they will not apply to mixed library type - builtin type operations which I think is the bigger risk. All of the analysis is static; there is zero runtime overhead introduced by these checks.
Also, I don't quite understand what you are saying in these two sections:
https://develop.int128.cpp.al/uint128_t.html#u128_operator_behavior https://develop.int128.cpp.al/int128_t.html#i128_operator_behavior
In one place you're saying you convert signed to unsigned to perform the operation, in the other - the other way around. Which way is it?
For an operation between a builtin and a int128 type of opposite sign, the builtin will be cast to the int128 type. These sign conversions match the behavior of __(u)int128_t. I will edit these sections to make them more clear. Matt
Am 29.04.26 um 00:51 schrieb Matt Borland via Boost:
I have doubts regarding the signed/unsigned comparison behavior deviation described here:
https://develop.int128.cpp.al/uint128_t.html#uint128_t_sign_compare_behavior...
While I understand the reasons for wanting to implement comparison this way, I thing I would rather prefer to keep the behavior consistent with the rest of integer types. That is, make it the same as for built-in integer types.
It is the same behavior as the built-in types have when you set -Werror -Wsign-conversion -Wconversion which I think is uncontroversial to say is best practice. If this is behavior is removed from the library, then when a user does set the aforementioned flags they will not apply to mixed library type - builtin type operations which I think is the bigger risk. All of the analysis is static; there is zero runtime overhead introduced by these checks. I'm a bit confused about the relation of "behavior" to warning flags. My understanding of that would be that the library shows a compile-time error as it would with that warning flag(s) and Werror enabled. Is that the case?
The docs however say:
With |uint128_t| we have checks even in this case like so: ... if(rhs >= 0) ... else return true;
This contradicts (my understanding of) the stated behavior to fail compilation on mixed comparison and also the "zero runtime overhead". So what is it? While I see how this behavior is less surprising for beginners, advanced users might rely on the wrap-around (mod 2^N) behavior. Semi-contrived example: `operator[](signed_t idx) { if(size() > idx) return elements[idx]; }` So I'd rather have this not compile (e.g. via static_assert) to be similar to the Werror case, than silently deviate from "standard behavior". - Alex
On 29 Apr 2026 01:51, Matt Borland wrote:
I have doubts regarding the signed/unsigned comparison behavior deviation described here:
https://develop.int128.cpp.al/uint128_t.html#uint128_t_sign_compare_behavior...
While I understand the reasons for wanting to implement comparison this way, I thing I would rather prefer to keep the behavior consistent with the rest of integer types. That is, make it the same as for built-in integer types.
It is the same behavior as the built-in types have when you set -Werror -Wsign-conversion -Wconversion which I think is uncontroversial to say is best practice.
Personally, I never use -Werror and don't consider this a good practice.
If this is behavior is removed from the library, then when a user does set the aforementioned flags they will not apply to mixed library type - builtin type operations which I think is the bigger risk. All of the analysis is static; there is zero runtime overhead introduced by these checks.
You could try emitting a warning manually, if you want. There's this example, although I don't know how well it works: https://www.boost.org/doc/libs/1_91_0/libs/serialization/doc/static_warning.... Then you would provide user with a macro to disable the warning. This would be better than disabling the operators by default. However, my complaint was not about warnings but about the behavior when the operators are enabled by defining the BOOST_INT128_ALLOW_SIGN_COMPARE/BOOST_INT128_ALLOW_SIGN_CONVERSION macro. When the comparison operators are enabled, their behavior differs from the built-in ones, and I think this is a problem.
Also, I don't quite understand what you are saying in these two sections:
https://develop.int128.cpp.al/uint128_t.html#u128_operator_behavior https://develop.int128.cpp.al/int128_t.html#i128_operator_behavior
In one place you're saying you convert signed to unsigned to perform the operation, in the other - the other way around. Which way is it?
For an operation between a builtin and a int128 type of opposite sign, the builtin will be cast to the int128 type. These sign conversions match the behavior of __(u)int128_t. I will edit these sections to make them more clear.
Thanks, but do note that for an operation taking int128_t and uint128_t (in any order), int128_t is always expected to be converted to uint128_t. Is this expectation correct?
On 29 Apr 2026 12:16, Dennis Luehring via Boost wrote:
Am 29.04.2026 um 11:02 schrieb Andrey Semashev via Boost:
Personally, I never use -Werror and don't consider this a good practice.
rational for this? does it forces too much that people try to prevent warnings at any cost/without thinking about?
This topic has been beaten many times, but in short, compiler warnings are not portable and are often bogus and/or subjective. Even within the same compiler line, one version may not generate a warning and the next one will, for the same code. Requesting the compiler to fail in these conditions is counter-productive and hostile towards users. As a user, I have to deal with a number of libraries used in my projects. Some of these libraries enforce -Werror. And almost always this causes problems for me because, of course, compilation fails because of warnings on the target platforms I use. Some libraries are generous enough to allow me disable warnings-as-errors. Others I have to patch and then maintain the patches myself. The best case scenario is the build passes because it doesn't emit warnings and I don't have to do anything, but even then -Werror doesn't give me anything, as a user.
Am 29.04.26 um 13:34 schrieb Andrey Semashev via Boost:
On 29 Apr 2026 12:16, Dennis Luehring via Boost wrote:
Am 29.04.2026 um 11:02 schrieb Andrey Semashev via Boost:
Personally, I never use -Werror and don't consider this a good practice. rational for this? does it forces too much that people try to prevent warnings at any cost/without thinking about? This topic has been beaten many times, but in short, compiler warnings are not portable and are often bogus and/or subjective. Even within the same compiler line, one version may not generate a warning and the next one will, for the same code. Requesting the compiler to fail in these conditions is counter-productive and hostile towards users.
Obviously Werror should be the users choice, not be forced upon them. However I build the libraries I develop with Werror on CI and in the tests to enforce they are warning free. 1) Even if most warnings are false positives, those that are not help catch issues early. The rest is easy to suppress which is best done by the person how developed the code, not some user. 2) A user building my library won't be greeted with dozens or hundreds of warnings making them question if something is off. This has been recently observed to be an annoyance in the current release. 3) A user using my library and enabling Werror will likely not have any issues, as at least my headers are warning free. Mostly not an issue though as when installed to a "system" location no warnings will be generated by most compilers. I fully disagree with that they "are often bogus and/or subjective", or compiler implementers wouldn't have implemented them. - Alex
Alexander Grund wrote:
Obviously Werror should be the users choice, not be forced upon them. However I build the libraries I develop with Werror on CI and in the tests to enforce they are warning free. 1) Even if most warnings are false positives, those that are not help catch issues early. The rest is easy to suppress which is best done by the person how developed the code, not some user. 2) A user building my library won't be greeted with dozens or hundreds of warnings making them question if something is off. This has been recently observed to be an annoyance in the current release. 3) A user using my library and enabling Werror will likely not have any issues, as at least my headers are warning free. Mostly not an issue though as when installed to a "system" location no warnings will be generated by most compilers.
I fully disagree with that they "are often bogus and/or subjective", or compiler implementers wouldn't have implemented them.
That's true in principle, but -Werror with -Wconversion -Wsign-conversion is far from uncontroversial, especially on old compilers that insist that if( x > 0 ) is a horrible violation of propriety when x is unsigned. Newer compilers are much better, but if you implement the "equivalent" in a library, you'll be back to the stone age with the above being rejected.
On 29 Apr 2026 16:05, Alexander Grund via Boost wrote:
Am 29.04.26 um 13:34 schrieb Andrey Semashev via Boost:
On 29 Apr 2026 12:16, Dennis Luehring via Boost wrote:
Am 29.04.2026 um 11:02 schrieb Andrey Semashev via Boost:
Personally, I never use -Werror and don't consider this a good practice. rational for this? does it forces too much that people try to prevent warnings at any cost/without thinking about? This topic has been beaten many times, but in short, compiler warnings are not portable and are often bogus and/or subjective. Even within the same compiler line, one version may not generate a warning and the next one will, for the same code. Requesting the compiler to fail in these conditions is counter-productive and hostile towards users.
Obviously Werror should be the users choice, not be forced upon them.
Well, it started from Boost.int128 enforcing a -Werror-like behavior on users and claiming this was uncontroversial.
I fully disagree with that they "are often bogus and/or subjective", or compiler implementers wouldn't have implemented them.
That's just my experience with warnings. I think, most of the warnings I get are bogus; I can't remember the last time I got a useful one, apart from deprecation warnings after upgrading a library. Quite a few of the bogus ones are coming from the standard library and system headers, actually. And no, headers residing in a system directory doesn't silence these warnings, at least not in my case.
On 4/29/26 13:34, Andrey Semashev via Boost wrote:
This topic has been beaten many times, but in short, compiler warnings are not portable and are often bogus and/or subjective.
The obvious counterargument to this is that if you disagree with a warning, you should disable it. There's no point in the compiler generating warnings if you're just going to ignore them, piles of bogus warnings only make it more difficult to find the warnings you actually care about. I've recently started experimenting -Werror, mainly because my build process produces so much output that I'm likely to miss warnings entirely if I don't treat them as errors. The obvious problem with this approach is third party libraries that produce warnings, which is all the more reason for library authors to to keep their libraries completely warning-free. -- Rainer Deyke - rainerd@eldwood.com
You could try emitting a warning manually, if you want. There's this example, although I don't know how well it works:
https://www.boost.org/doc/libs/1_91_0/libs/serialization/doc/static_warning....
Thanks for that. Seems theres a reddit thread with an easy implementation: https://www.reddit.com/r/cpp/comments/66o1ju/does_a_static_warn_exist/.
Then you would provide user with a macro to disable the warning. This would be better than disabling the operators by default.
However, my complaint was not about warnings but about the behavior when the operators are enabled by defining the BOOST_INT128_ALLOW_SIGN_COMPARE/BOOST_INT128_ALLOW_SIGN_CONVERSION macro. When the comparison operators are enabled, their behavior differs from the built-in ones, and I think this is a problem.
Seems as though Alexander and Peter have both agreed with you since my last response. I'll make the changes, and see if the static warning can be made to work in some fashion.
For an operation between a builtin and a int128 type of opposite sign, the builtin will be cast to the int128 type. These sign conversions match the behavior of __(u)int128_t. I will edit these sections to make them more clear.
Thanks, but do note that for an operation taking int128_t and uint128_t (in any order), int128_t is always expected to be converted to uint128_t. Is this expectation correct?
Yes, that is correct. Matt
Matt Borland wrote:
I have doubts regarding the signed/unsigned comparison behavior deviation described here:
https://develop.int128.cpp.al/uint128_t.html#uint128_t_sign_compare_behavior...
While I understand the reasons for wanting to implement comparison this way, I thing I would rather prefer to keep the behavior consistent with the rest of integer types. That is, make it the same as for built-in integer types.
It is the same behavior as the built-in types have when you set -Werror - Wsign-conversion -Wconversion which I think is uncontroversial to say is best practice. If this is behavior is removed from the library, then when a user does set the aforementioned flags they will not apply to mixed library type - builtin type operations which I think is the bigger risk. All of the analysis is static; there is zero runtime overhead introduced by these checks.
This isn't a good idea and will inevitably be rolled back eventually. The behavior of the library types should match _exactly_ the behavior of the built-in types when they exist (and there should be tests for that.) Doing otherwise, however well intentioned, will cause more problems than it solves.
On 2026-04-28 19:02, Matt Borland via Boost wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
A couple of questions that I anticipate:
Why do we need this if we already have Boost.Multiprecision?
An old compliant against Boost.Multiprecision is that the 128-bit integer types are not 16 bytes [3]. The 128-bit integer types are also incident to the arbitrary precision type rather than a dedicated implementation. This allows int128 to improve performance in places that Multiprecision can't or shouldn't which is reflected in the benchmarks [2].
It would be good to have a more performant 128bit integer type. What is needed to use GMP mpz_powm() modular exponention on int128? Conversion to Boost.Multiprecision gmp_int, or directly to GMP? Would adding mpz_powm() like function to new library make sense? If such int128 powm would be faster than GMP mpz_powm I would say yes. Regards, Hermann.
What is needed to use GMP mpz_powm() modular exponention on int128? Conversion to Boost.Multiprecision gmp_int, or directly to GMP?
Would adding mpz_powm() like function to new library make sense? If such int128 powm would be faster than GMP mpz_powm I would say yes.
To convert to mpz_t you could do something like: boost::int128::uint128_t val; mpz_t z; mpz_init(z); uint64_t words[2] = { val.high, val.low }; mpz_import(z, 2, 1, sizeof(uint64_t), 0, 0, words); I don't have any special bindings for easy conversions to multiprecision types. Without measuring I will assume that a special case of a two word modular exponentiation in the library would be a good bit faster. I already have a way for 128 by 128 mul to result in a 256-bit array in the library (I use this for mul in decimal128_t). Same for the 256-bit by 128-bit reduction. I believe that GMP's small value optimization is 128-bits, so they would need to make at least one heap allocation for this operation. I can look into this in the next few days for you. Matt
On 4/28/26 19:02, Matt Borland via Boost wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
I have mixed feelings about this. What I really want is a true std::int128_t using native CPU instructions that is a true integral type and can be used in switch statements. The proposed library looks good from a performance perspective, but that could all change when true 128 bit integer CPU instructions arrive, and as a class type it can't be used with switch statements. Despite my reservations, I endorse this library. It's available now, it runs on current CPUs, and I can always hide it behind a typedef so that I can switch to another int128 implementation when a true native one becomes available. -- Rainer Deyke - rainerd@eldwood.com
On Wednesday, April 29th, 2026 at 1:59 AM, Rainer Deyke via Boost <boost@lists.boost.org> wrote:
On 4/28/26 19:02, Matt Borland via Boost wrote:
Dear All,
I am seeking endorsement for review of my library int128 [1]. The library requires only C++14, is header only, and has no mandatory dependencies. What does int128 provide? Two portable and performant types: a 128-bit signed integer and a 128-bit unsigned integer, as well as a standard library for them. The performance of these types have been tuned and tested on a variety of architectures to include: x64, x32, s390x, ARM64, ARM32, PPC64LE. Both of the types and most of their library functions also work inside CUDA kernels. Benchmarks against Boost.Multiprecision, Absl, MSVC's software 128-bit integers, and built-ins, are available [2].
I have mixed feelings about this. What I really want is a true std::int128_t using native CPU instructions that is a true integral type and can be used in switch statements. The proposed library looks good from a performance perspective, but that could all change when true 128 bit integer CPU instructions arrive, and as a class type it can't be used with switch statements.
Here is the paper that I referenced earlier about the std::int_least128_t proposal being replaced by _BitInt: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3666r3.html. Hopefully an unsigned _BitInt(128) does as you describe, but I have not looked at the existing implementations to see if that's true. The max required width is only 64-bits, so we may very well end up in a situation where 128-bit still is not cross-platform.
Despite my reservations, I endorse this library. It's available now, it runs on current CPUs, and I can always hide it behind a typedef so that I can switch to another int128 implementation when a true native one becomes available.
Thank you! Matt
Hello, I endorse the library, there's a real need for an int128 type as a standalone library. One thing I would note: Why C++14? What about C++11? Best, Amlal
I endorse the library, there's a real need for an int128 type as a standalone library. One thing I would note: Why C++14? What about C++11?
C++14 allows basically the entire library to be constexpr, which is quite useful for a numeric type. This goes back as far as GCC 5, Clang 5, and MSVC 14.1 which are about as old as I'd ever be interested in supporting really. Matt
Me as a python user for large numbers, I would also love to have int128 in C++ as well as float128, float256, float512 & float1024 ...
Thank you. For big floats have you tried boost::multiprecision::cpp_bin_float? https://www.boost.org/doc/libs/latest/libs/multiprecision/doc/html/boost_mul.... It may cover what you're looking for. Matt
On 4/29/26 21:24, Peter Taraba via Boost wrote:
Me as a python user for large numbers, I would also love to have int128 in C++ as well as float128, float256, float512 & float1024 ...
Huge integers I can understand (because sometimes you need results that are not just precise but exact), but what's the use for float1024? float256 would already have enough precision to represent measure the size of the observable universe at Planck length precision. I'm not saying there isn't a use for such a type, but I'm genuinely curious as to what that use is. -- Rainer Deyke - rainerd@eldwood.com
> Huge integers I can understand> (because sometimes you need> results that are not just precise> but exact), but what's the use> for float1024? float256
> Huge integers I can understand> (because sometimes you need results> that are not just precise but exact),> but what's the use for float1024?> float256
So far there have been severalinteresting reactions regarding:
* behavior of the (u)int128 typein relation to built-insand standards,
* documentation queries,
* concerns/ideas that even more "big"types could potentially be useful.
I'm very interested in "big number"types. Yet I feel that enlargingthe scope of this thread to othertypes may probably better left forfuture threads.
I can reaffirm need for (u)int128,as recently as we've used it inongoing specification work today.
Thanks for the enriching discussionso far.
- Christopher
On Wednesday, April 29, 2026 at 10:21:13 PM GMT+2, Peter Taraba via Boost <boost@lists.boost.org> wrote:
these two publications should explain it:
https://www.sciencedirect.com/science/article/pii/S2666827021000633?via%3Dihubhttps://www.frontiersin.org/journals/artificial-intelligence/articles/10.3389/frai.2023.1144886/full going wider with DNNs for higher accuracy. let me know if you have more questions. Best,
Peter Sent: Wednesday, April 29, 2026 at 1:14 PM
From: "Rainer Deyke via Boost" <boost@lists.boost.org>
To: boost@lists.boost.org
Cc: "Rainer Deyke" <rdeyke@gmail.com>
Subject: [boost] Re: Seeking Endorsement: Boost.int128On 4/29/26 21:24, Peter Taraba via Boost wrote:
> Me as a python user for large numbers, I would also love to have int128 in C++
> as well as float128, float256, float512 & float1024 ...
Huge integers I can understand (because sometimes you need results that
are not just precise but exact), but what's the use for float1024?
float256 would already have enough precision to represent measure the
size of the observable universe at Planck length precision.
I'm not saying there isn't a use for such a type, but I'm genuinely
curious as to what that use is.
--
Rainer Deyke - rainerd@eldwood.com
_______________________________________________
Boost mailing list -- boost@lists.boost.org
To unsubscribe send an email to boost-leave@lists.boost.org
https://lists.boost.org/mailman3/lists/boost.lists.boost.org/
Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/3KBA7AHE7ZOB6OQKTFHRDLXOSIGXC3ZJ/_______________________________________________
Boost mailing list -- boost@lists.boost.org
To unsubscribe send an email to boost-leave@lists.boost.org
https://lists.boost.org/mailman3/lists/boost.lists.boost.org/
Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/3PORE4XPNMOEMGPAD72ENF4PJSEYFR7B/
On 30 Apr 2026 02:11, Peter Taraba via Boost wrote:
Use? Imagine you have really hard decision and your models tell you 50% result... in that case you need higher precision so you know if you should do it or not. Some decisions are really hard...
Would it make a difference if a more precise model gave a 50.1% vs. 49.9% outcome? Not saying higher precision is not useful, just that the application in AI models seems questionable. My understanding is that having more parameters is generally more preferable to precision/quantization in terms of the model quality.
On 30 Apr 2026 03:29, Peter Taraba wrote:
imagine you are president of USA and you have to make decision. knowing answer is 50.000001% (decision is yes) is better than 50% (no clue if decision is yes or no).
50.000001% seems pretty much the same as 50% to me, no matter how important the decision is. What I'd be interested in is a deeper analysis, and a more capable (and not necessarily more precise) model could help with that. Although, as a president, I probably wouldn't rely on AI too much.
*Sent:* Wednesday, April 29, 2026 at 5:26 PM *From:* "Andrey Semashev via Boost" <boost@lists.boost.org> *To:* "Boost developers' mailing list" <boost@lists.boost.org> *Cc:* "Andrey Semashev" <andrey.semashev@gmail.com> *Subject:* [boost] Re: Seeking Endorsement: Boost.int128 On 30 Apr 2026 02:11, Peter Taraba via Boost wrote:
Use? Imagine you have really hard decision and your models tell you 50% result... in that case you need higher precision so you know if you should do it or not. Some decisions are really hard...
Would it make a difference if a more precise model gave a 50.1% vs. 49.9% outcome? Not saying higher precision is not useful, just that the application in AI models seems questionable. My understanding is that having more parameters is generally more preferable to precision/quantization in terms of the model quality.
On 4/30/26 02:29, Peter Taraba via Boost wrote:
imagine you are president of USA and you have to make decision. knowing answer is 50.000001% (decision is yes) is better than 50% (no clue if decision is yes or no).
Actually, I would interpret any result in the 35% to 65% range as "I don't know", and use my own judgement. AI is the last place I would expect big floats. Even 32 bits is often more than needed, hence the common use of 16 bit floats in AI. -- Rainer Deyke - rainerd@eldwood.com
participants (13)
-
Alan de Freitas -
Alexander Grund -
Amlal El Mahrouss -
Andrey Semashev -
Christopher Kormanyos -
Dennis Luehring -
hermann@stamm-wilbrandt.de -
Matt Borland -
Peter Dimov -
Peter Taraba -
Rainer Deyke -
Tim Haines -
Vinnie Falco