1
#define XL     33           
#define OR      113          
#define NOR     313     
#define TN     344  

int to_bits(int critn,char *mask)
{
       unsigned int x;
       int begin;

       if (critn < XL)           begin = 1;
       else if (critn < OR)      begin = XL;
       else if (critn < NOR)     begin = OR;
       else if (critn <= TN)    begin = NOR;
       else                        begin = 0;
       x = critn - begin;

       *mask = (char)(0x80 >> (x % 8));

       return (int)(x >> 3);    // fast divide by 8  
}

I don't have any knowledge of C++ code. Can any one explain what this method is doing in the last 2 lines?

Thanks

JavaBits
  • 2,005
  • 11
  • 36
  • 40

4 Answers4

2

The last two lines are bit shifting.

mask is taking 0x80 and shifting it (x to the mod of 8) positions eg 5 >> 2 will give you 1.

x >> 3 is as it says, dividing it by 8, its taking x and moving all the bits 3 positions to the right (so thats 1,2,4), as a result, 8 will become 1 etc. its a little like integer div, but would be faster (as the comment says, fast divide by 8)

BugFinder
  • 17,474
  • 4
  • 36
  • 51
  • 1
    *x to the mod of 8*? This is new to me. I always use *x modulo 8*. – Björn Pollex Apr 06 '11 at 07:02
  • 1
    However, the "faster" divide by 8 is a nice case of premature optimization - the compiler will figure out the fastest way to divide by 8, you shouldn't try to do things like that for it. – adam_0 Apr 06 '11 at 07:03
  • @adam_0 maybe its just a bad description of doing what they're doing, but I guess in short, it does achieve the same thing. I know people can get stuck on things like this where the idea of /2 /4 /8 people get told somewhere along the lines that bit shifting is quicker and it sticks with them even if its not really true – BugFinder Apr 06 '11 at 07:07
2
  *mask = (char)(0x80 >> (x % 8));  

The value x is masked so that only the lower three bits remain. The value 0x80 is shifted to right by the remaining number. The result is assigned to the value where mask points to.

   return (int)(x >> 3);    // fast divide by 8     

x is divided by eight. The result is the reutrn value of the method.

harper
  • 13,345
  • 8
  • 56
  • 105
2

>> is right shift operator.

for e.g 8 > 3 will give you 1, right shift binary value of 8 by 3 places

1000(binary of 8) right shift by 3 places = 0001 (1 in decimal)
Gaurav
  • 28,447
  • 8
  • 50
  • 80
1

In C++, just like most programming languages, you can only return one value. To "return" two values, it's a common C/C++ practice to return one and pass a pointer to an object and modify that object via the pointer (mask in this case).

The object that mask point to will be assigned a bitmask with exactly one bit set. This is done be taking the hexadecimal value 0x80 (1000 0000 in binary form) and right shift it 0 to 7 steps. The exact number of steps is decided by x, which is computer using some application-specific logic.

The value returned is the x / 8.

You can see the routine as a division routine that returns x/8 and the remainder (like x modulo 8, but expressed as a bit mask rather than an integer value).

Lindydancer
  • 25,428
  • 4
  • 49
  • 68
  • thanks but can u please give an example. if critn = 63 then x= 63-33= 30. then what is the value of mask? – JavaBits Apr 06 '11 at 10:08
  • As *30 modulo 8* is 6, the operation is (expressed in binary) `10000000>>6` resulting in `00000010`. The value returned will be `30/8` or `3`. – Lindydancer Apr 06 '11 at 10:12
  • So will it be 00000010 (as you have mentioned) or 11111110. As in the following link http://stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting it says that arithmatic right shift (>>) will do like that. I am getting confused. thanks for ur help. – JavaBits Apr 06 '11 at 10:18
  • Right shift can either be *signed* or *unsigned*. If it's signed, it will replicate the sign bit of the mask in question. In this case, the value `0x80` is an integer, on a 32 bit machine this is really the value `0x00000080` (i.e. the sign bit is zero), so the result is `0x00000002` (or `....0010` in binary). If the code would have read `((signed char)0x80) >> x` the resulting bit mask would have been `11111110`. – Lindydancer Apr 06 '11 at 10:33