Is it possible to rewrite modulo (2^n - 1) using bitwise and restricted operators

后端 未结 3 1331
-上瘾入骨i
-上瘾入骨i 2021-02-05 20:48

For unsigned int x, is it possible to calculate x % 255 (or 2^n - 1 in general) using only the following operators (plus no loop, branch or function call)?

!

相关标签:
3条回答
  • 2021-02-05 21:27

    Just create an array with all the values (only either need 32 or 64 entries (i.e. 128 or 512 bytes). Then just do a look up.

    0 讨论(0)
  • 2021-02-05 21:40

    Sure. Just get out one of your old computer architecture textbooks and refresh your memory on boolean algebra. A CPU's ALU does it with ANDs and ORs; you can, too.

    But why?

    An academic exercise? Homework? Curiousity?

    0 讨论(0)
  • 2021-02-05 21:44

    Yes, it's possible. For 255, it can be done as follows:

    unsigned int x = 4023156861;
    
    x = (x & 255) + (x >> 8);
    x = (x & 255) + (x >> 8);
    x = (x & 255) + (x >> 8);
    x = (x & 255) + (x >> 8);
    
    //  At this point, x will be in the range: 0 <= x < 256.
    //  If the answer 0, x could potentially be 255 which is not fully reduced.
    
    //  Here's an ugly way of implementing: if (x == 255) x -= 255;
    //  (See comments for a simpler version by Paul R.)
    unsigned int t = (x + 1) >> 8;
    t = !t + 0xffffffff;
    t &= 255;
    x += ~t + 1;
    
    // x = 186
    

    This will work if unsigned int is a 32-bit integer.

    EDIT: The pattern should be obvious enough to see how this can be generalized to 2^n - 1. You just have to figure out how many iterations are needed. For n = 8 and a 32-bit integer, 4 iterations should be enough.

    EDIT 2:

    Here's a slightly more optimized version combined with Paul R.'s conditional subtract code:

    unsigned int x = 4023156861;
    
    x = (x & 65535) + (x >> 16);     //  Reduce to 17 bits
    x = (x & 255) + (x >> 8);        //  Reduce to 9 bits
    x = (x & 255) + (x >> 8);        //  Reduce to 8 bits
    x = (x + ((x + 1) >> 8)) & 255;  //  Reduce to < 255
    
    0 讨论(0)
提交回复
热议问题