Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fast way to get integers 0, 1, and 2 when given a random one from the set

So basically

int num = rand(2); //random number from 0-2
int otherNum, otherOtherNum;
otherNum = implement this
otherOtherNum = implement this

For example, if num is 2, otherNum and otherOtherNum must be set to 0 and 1 (or 1 and 0).

How would you implement this? Assume you can't use branching or look up tables. Yes i'd like a bit manipulation solution. Yes i'd like the solution to be faster than a solution that uses modulus operator (as this is essentialy a division).

I think a lookup might be the fastest but not sure, I dont like that solution though.

like image 485
Thomas Avatar asked Apr 25 '15 18:04

Thomas


3 Answers

You can also do this with XOR and bit masking.

#include <stdio.h>

void
f(unsigned val, unsigned ary[3])
{
    ary[0] = val;
    ary[1] = (ary[0] ^ 1) & 1;
    ary[2] = (ary[0] ^ 2) & 2;
}

int
main()
{
    unsigned ary[3] = {0};

    f(0, ary);
    printf("f(0) = %d %d %d\n", ary[0], ary[1], ary[2]);

    f(1, ary);
    printf("f(1) = %d %d %d\n", ary[0], ary[1], ary[2]);

    f(2, ary);
    printf("f(2) = %d %d %d\n", ary[0], ary[1], ary[2]);

    return 0;
}

This will print:

f(0) = 0 1 2
f(1) = 1 0 2
f(2) = 2 1 0
like image 80
D.Shawley Avatar answered Nov 10 '22 19:11

D.Shawley


otherNum = (num + 1) % 3
otherOtherNum = (num + 2) % 3
like image 8
Xiaotian Pei Avatar answered Nov 10 '22 20:11

Xiaotian Pei


You could use an in-register lookup table, if the restriction on look-up tables means avoiding memory access. The in-register lookup-table is simply a compile-time constant.

const int tab = ((1 <<  0) | (2 <<  4) | 
                 (0 <<  8) | (2 << 12) | 
                 (0 << 16) | (1 << 20));
int num = rand(2); //random number from 0-2
int otherNum, otherOtherNum;
otherNum = (tab >> num*8) & 0xf;
otherOtherNum = (tab >> (num*8+4)) & 0xf;
like image 6
njuffa Avatar answered Nov 10 '22 18:11

njuffa