Embedding unsigned int in unsigned short int with bit operator

I would like to use unsigned int (32 bit) A for an unsigned short int (16 bit) B as follows:

  • if A <= 2 ^ 16-1, then B = A
  • if A> 2 ^ 16-1, then B = 2 ^ 16-1

In other words, to distinguish A, but if it is> the maximum allowed value for 16bit, set it as the maximum value.

How can this be achieved using bitwise operations or another non-branching method ?

+3
source share
4 answers

Find a minimum of two integers without branching:

http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax

, , , r = (x < y)? x: y, . ( , , .)

, , . 50/50 "":

#include <iostream>
#include <stdint.h>

int main() {
    uint32_t total = 0;
    uint32_t n = 27465;
    for (int i = 0; i < 1000*1000*500; ++i) {
        n *= 30029; // worst PRNG in the world
        uint32_t a = n & 0x1ffff;
        #ifdef EMPTY
            uint16_t b = a; // gives the wrong total, of course.
        #endif
        #ifdef NORMAL
            uint16_t b = (a > 0xffff) ? 0xffff : a;
        #endif
        #ifdef RUSLIK
            uint16_t b = (-(a >> 16) >> 16) | a;
        #endif
        #ifdef BITHACK
            uint16_t b = a ^ ((0xffff ^ a) & -(0xffff < a));
        #endif
        total += b;
    }
    std::cout << total << "\n";
}

(gcc 4.3.4 cygwin -O3), NORMAL , RUSLIK, BITHACK, 0,3, 0,5 0,9 , . , , , , -. ruslik.

+2

:

b = -!!(a >> 16) | a;

, - :

static inline unsigned short int fn(unsigned int a){
    return (-(a >> 16) >> 16) | a;
};
+5

1) , .

2) , , , :

c = a >> 16; /* previously declared as a short */
/* Saturate 'c' with 1s if there are any 1s, by first propagating
1s rightward, then leftward. */
c |= c >> 8;
c |= c >> 4;
c |= c >> 2;
c |= c >> 1;
c |= c << 1;
c |= c << 2;
c |= c << 4;
c |= c << 8;
b = a | c; /* implicit truncation */
0

-, " " C; "" C , , , , ( , , ).

, :

uint16_t b = a > UINT16_MAX ? UINT16_MAX : a;

" ", - ( ) ( ARM Intel ).

, . , ( ), , , , () (b) .

, , , ruslik ( , /).

0

Source: https://habr.com/ru/post/1778168/


All Articles