diff options
author | Karl Williamson <khw@cpan.org> | 2021-06-05 01:15:37 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2021-07-30 05:41:27 -0600 |
commit | 8a6ab0a2b6184deb2f9a99f0a9622e8f836de4bd (patch) | |
tree | 280de16102aa7509f90b7cba01c2cdabea4ed550 /inline.h | |
parent | 995a49544ee5d0b46679907f5ba9fe50be890438 (diff) | |
download | perl-8a6ab0a2b6184deb2f9a99f0a9622e8f836de4bd.tar.gz |
Perl_variant_byte_number: Generalize
The current mechanism doesn't work if the lowest bit is the one set. At
the moment that doesn't matter as we aren't looking at that bit anyway.
But a future commit will refactor things so that bit will be looked at.
So prepare for that. The new expression is simpler, besides.
Diffstat (limited to 'inline.h')
-rw-r--r-- | inline.h | 24 |
1 files changed, 10 insertions, 14 deletions
@@ -727,22 +727,18 @@ Perl_variant_byte_number(PERL_UINTMAX_T word) * https://stackoverflow.com/questions/757059/position-of-least-significant-bit-that-is-set * * The word will look like this, with a rightmost set bit in position 's': - * ('x's are don't cares) + * ('x's are don't cares, and 'y's are their complements) * s - * x..x100..0 - * x..xx10..0 Right shift (rightmost 0 is shifted off) - * x..xx01..1 Subtract 1, turns all the trailing zeros into 1's and - * the 1 just to their left into a 0; the remainder is - * untouched - * 0..0011..1 The xor with the original, x..xx10..0, clears that - * remainder, sets the bottom to all 1 - * 0..0100..0 Add 1 to clear the word except for the bit in 's' + * x..x100..00 + * y..y011..11 Complement + * y..y100..00 Add 1 + * 0..0100..00 AND with the original * - * Another method is to do 'word &= -word'; but it generates a compiler - * message on some platforms about taking the negative of an unsigned */ - - word >>= 1; - word = 1 + (word ^ (word - 1)); + * (Yes, complementing and adding 1 is just taking the negative on 2's + * complement machines, but not on 1's complement ones, and some compilers + * complain about negating an unsigned.) + */ + word &= (~word + 1); # elif BYTEORDER == 0x4321 || BYTEORDER == 0x87654321 |