Date: Fri, 27 Jun 2025 09:29:31 +0200
One more idea (I believe signed integers are not defined as two's
complement and overflow is not undefined behavior):
int32_t filled = (((test_var >> 31) & 0x01) ^ 0x01) + 0xFFFFFFFF;
1. Right shift to get the sign
2. Invert the sign with XOR ^
3. Add the maximum number which either overflows and yields 0 or the
inverted number was already 0, so we get 0xFFFFFFFF
You are right about one thing: The discussion and the different proposals
of how to implement sign_fill show that it is not trivial to find a high
performance general solution to the problem. (But, we have seen simple
solutions that most programmers should be able to come up with which is
sufficient if it is not performance critical.)
On Fri, Jun 27, 2025 at 9:22 AM Simon Schröder <dr.simon.schroeder_at_[hidden]>
wrote:
> Most of the time I know the number of bits and I'd just use the proper hex
> mask:
>
> uint32_t filled = (test_var & 0x80000000) ? 0xFFFFFFFF : 0;
>
> Or if you want to avoid branches and are okay with a few extra cycles:
> uint32_t filled = ((test_var >> 31) & 0x01) * 0xFFFFFFFF;
> (That's just from the top of my head. Maybe there's something better than
> multiplication?)
>
> On Fri, Jun 27, 2025 at 9:11 AM Tiago Freire via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Isn't sign_fill just:
>>
>> //preparation
>> using u_t = std::make_unsigned_t<T>;
>> constexpr u_t mask = u_t{1} << (std::numeric_limits<u_t>::digits - 1);
>>
>> //actual conversion
>> T filled = ( std::bit_cast<u_t>(test_var) & mask ) ? T{-1} : T{0};
>>
>>
>> -----Original Message-----
>> From: Jan Schultke <janschultke_at_[hidden]>
>> Sent: Friday, June 27, 2025 08:50
>> To: Tiago Freire <tmiguelf_at_[hidden]>
>> Cc: std-proposals_at_[hidden]
>> Subject: Re: [std-proposals] More C++ bit manipulation utilities
>>
>> > I’ve used a version of all of these, semi-regularly.
>> > However, they are so trivial to implement that it has never occurred to
>> me to write a function to do those.
>>
>> How do you write sign_fill usually then? Do you just use ">>
>> (std::numeric_limits<T>::digits - 1)" in every place where you sign-fill?
>>
>> > It might be easier to sell these by packaging them with a set of bit
>> > operations, like a shift out (i.e. left or right shift overflow bits
>> > goes into a separate integer), mask multiple bits, bit order swaps,
>> > etc…
>>
>> I'm not sure what you mean by "mask multiple bits"; that sounds much like
>> bit_mask, which is on the list.
>>
>> bit_reverse (bit order swaps) is design-approved for C++29 as part of Bit
>> permutations already.
>>
>> obtaining the shifted-out bits sounds interesting. That's useful for
>> bit-shifting numbers in multi-precision arithmetic.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
complement and overflow is not undefined behavior):
int32_t filled = (((test_var >> 31) & 0x01) ^ 0x01) + 0xFFFFFFFF;
1. Right shift to get the sign
2. Invert the sign with XOR ^
3. Add the maximum number which either overflows and yields 0 or the
inverted number was already 0, so we get 0xFFFFFFFF
You are right about one thing: The discussion and the different proposals
of how to implement sign_fill show that it is not trivial to find a high
performance general solution to the problem. (But, we have seen simple
solutions that most programmers should be able to come up with which is
sufficient if it is not performance critical.)
On Fri, Jun 27, 2025 at 9:22 AM Simon Schröder <dr.simon.schroeder_at_[hidden]>
wrote:
> Most of the time I know the number of bits and I'd just use the proper hex
> mask:
>
> uint32_t filled = (test_var & 0x80000000) ? 0xFFFFFFFF : 0;
>
> Or if you want to avoid branches and are okay with a few extra cycles:
> uint32_t filled = ((test_var >> 31) & 0x01) * 0xFFFFFFFF;
> (That's just from the top of my head. Maybe there's something better than
> multiplication?)
>
> On Fri, Jun 27, 2025 at 9:11 AM Tiago Freire via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Isn't sign_fill just:
>>
>> //preparation
>> using u_t = std::make_unsigned_t<T>;
>> constexpr u_t mask = u_t{1} << (std::numeric_limits<u_t>::digits - 1);
>>
>> //actual conversion
>> T filled = ( std::bit_cast<u_t>(test_var) & mask ) ? T{-1} : T{0};
>>
>>
>> -----Original Message-----
>> From: Jan Schultke <janschultke_at_[hidden]>
>> Sent: Friday, June 27, 2025 08:50
>> To: Tiago Freire <tmiguelf_at_[hidden]>
>> Cc: std-proposals_at_[hidden]
>> Subject: Re: [std-proposals] More C++ bit manipulation utilities
>>
>> > I’ve used a version of all of these, semi-regularly.
>> > However, they are so trivial to implement that it has never occurred to
>> me to write a function to do those.
>>
>> How do you write sign_fill usually then? Do you just use ">>
>> (std::numeric_limits<T>::digits - 1)" in every place where you sign-fill?
>>
>> > It might be easier to sell these by packaging them with a set of bit
>> > operations, like a shift out (i.e. left or right shift overflow bits
>> > goes into a separate integer), mask multiple bits, bit order swaps,
>> > etc…
>>
>> I'm not sure what you mean by "mask multiple bits"; that sounds much like
>> bit_mask, which is on the list.
>>
>> bit_reverse (bit order swaps) is design-approved for C++29 as part of Bit
>> permutations already.
>>
>> obtaining the shifted-out bits sounds interesting. That's useful for
>> bit-shifting numbers in multi-precision arithmetic.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
Received on 2025-06-27 07:30:12