Creating a mask with N least significant bits set

前端 未结 6 1702
离开以前
离开以前 2021-01-18 01:00

I would like to create a macro or function1 mask(n) which given a number n returns an unsigned integer with its n least sig

6条回答
  •  被撕碎了的回忆
    2021-01-18 01:18

    #include 
    
    uint64_t mask_n_bits(const unsigned n){
      uint64_t ret = n < 64;
      ret <<= n&63; //the &63 is typically optimized away
      ret -= 1;
      return ret;
    }
    

    Results:

    mask_n_bits:
        xor     eax, eax
        cmp     edi, 63
        setbe   al
        shlx    rax, rax, rdi
        dec     rax
        ret
    

    Returns expected results and if passed a constant value it will be optimized to a constant mask in clang and gcc as well as icc at -O2 (but not -Os) .

    Explanation:

    The &63 gets optimized away, but ensures the shift is <=64.

    For values less than 64 it just sets the first n bits using (1<. 1< sets the nth bit (equivalent pow(2,n)) and subtracting 1 from a power of 2 sets all bits less than that.

    By using the conditional to set the initial 1 to be shifted, no branch is created, yet it gives you a 0 for all values >=64 because left shifting a 0 will always yield 0. Therefore when we subtract 1, we get all bits set for values of 64 and larger (because of 2s complement representation for -1).

    Caveats:

    • 1s complement systems must die - requires special casing if you have one
    • some compilers may not optimize the &63 away

提交回复
热议问题