Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C/++/# Bitwise Operators C++

  1. Mar 24, 2017 #1

    ChrisVer

    User Avatar
    Gold Member

    Hi guys, I have the following piece of code but I am not sure I understand if I get what it does correctly.

    Code (C):

    static const unsigned int m_nBits = 6;
    static const unsigned int m_nRanges = 4;
    max = SOMENUMBER;
    if( max >= (1 << (m_nBits + m_nRanges - 1) )   ){
       doStuff()
    }
     
    In fact I'm trying to understand the conditional. It says that if max is greater or equal to (1 <<9) it should do something. right?
    1<<9 = (01) << 9 = (1000000000) = 29= 512 right?
    (i bolded the binary numbers).

    So the if statement will be executed if the value of max is larger or equal to 512?
     
  2. jcsd
  3. Mar 24, 2017 #2
    You have it right!
     
  4. Mar 24, 2017 #3

    ChrisVer

    User Avatar
    Gold Member

    this looks like one of the worst possible piece of codes in terms of reading... how can one get used and even understand the reason behind those stuff?
     
  5. Mar 24, 2017 #4
    That's standard C code. Once you work with it for a while, you will improve your fluency.
    It's important to be able to express simple stuff like this concisely.
     
  6. Mar 24, 2017 #5

    jedishrfu

    Staff: Mentor

    They should have added comments to this statement to explain the meaning of the m_nRanges and m_nBits to make it more obvious. The naming convention does help some the m_ usually means
    member-of the class and the nBits means there's likely an array or structure of some sort named Bits in the class too.

    Too many programmers generate write only code that even they can't read after six months.
     
  7. Mar 24, 2017 #6

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    Out of context, the meaning of m_nBits and m_nRanges is mysterious. But there may be a context that makes it obvious. The individual bits of SOMENUMBER must have a meaning. That is why it is being compared in terms of bits instead of in terms of the integer 512. There may be documentation somewhere that explains it. Often the explanation is only one place and then it is used without explanation several places. That can't be avoided. The alternative is to explain it over and over again in several places, which is a nightmare to keep up to date.

    Isn't there some explanation in the code where m_nBits and m_nRanges are given values? If not, that is bad. But some people put all their documentation in a document and the code itself has very little.
     
    Last edited: Mar 24, 2017
  8. Mar 24, 2017 #7
    Put the entire bitshift and additions in their own static const unsigned int. Compiler will remove it for you and it'll make it much easier to read.

    Or replace it. Everything in there is constant, so the compiler will precalculate it for you. So it makes no different if you use a bitshift or a multiplier. Once compiled, it'll just be a number.
     
  9. Mar 24, 2017 #8

    jim mcnamara

    User Avatar

    Staff: Mentor

    In systems with limited memory and slow cpus, bithacks were used often. In fact see:
    https://graphics.stanford.edu/~seander/bithacks.html -- You can see what bit twiddling code looks like and what it does.

    I did extensive work on 16bit and 8bit machines. We had to do some of this kind of thing to improve performance with ancient compilers. Modern compilers don't need very much of this kind of code for performance. It mostly ends up in OS code now - where objects (usually flags or options) are bit strings.
     
  10. Mar 25, 2017 #9

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    Transmitted messages that have discretes and data compacted into bytes are often encoded and decoded with code that is full of this type of bit manipulation. That code is usually so methodical that there hundreds of similar lines. You get used to it and they are not hard to interpret.
     
  11. Mar 25, 2017 #10

    ChrisVer

    User Avatar
    Gold Member

    Hmmm this sounds more like it... in fact there are comments but I don't quite understand them either, mainly because I don't understand them.
     
  12. Mar 25, 2017 #11

    Mark44

    Staff: Mentor

    Or data compacted into multibyte memory locations...
    An example of what I mean is how the bits are packed into, say, a 32-bit floating point number. Per the IEE 754 standard for floating point numbers, a single-precision floating point number is divided into three parts:
    bit 31 is the sign bit, with 0 for a positive number and 1 for a negative number
    bits 23 through 30 hold the exponent, biased by 127 (meaning that the stored value is larger by 127 than the actual exponent of the number)
    bits 0 through 22 hold the mantissa, or fractional part of the number.

    The float value 4.125 in binary form would be 100.0012, meaning 1 X 2^2 + 0 X 2^1 + 0 X 2^0 + 0 X 2^(-1) + 0 X 2^(-2) + 1 X 2^(-3). In normalized form (a sort of "scientific notation") this would be 1.000012 X 22. Note that in normalized form, the digit to the left of the "binary point" is always 1, so it doesn't need to be stored.
    Since this number is positive, bit 31 would be 0.
    Bits 23 through 30 would hold the exponent, which would be stored as the binary form of 129 (= 2 + 127).
    Bits 0 through 22 would hold the mantissa, the part to the right of the "binary" point. For my example, the bit pattern would be 00001000000000000000000. Notice that this bit pattern agrees with what I showed as the normalized form, except for the leading 1 digit in the normalized form, which is implied.

    To extract the various sections of numbers such as these, you need to use the binary AND operator to mask out any bits you don't want, and then you need to shift the resulting bit pattern to the right. To extract bits 23 through 30, you need a bit pattern with those bits set to 1 and all other bits set to 0. A hexadecimal number that does this is 0x07F800000. After ANDing with this mask, the resulting number needs to be shifted right by 23 bits.

    Pretty low level stuff...
     
  13. Mar 25, 2017 #12

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    (Note: information in a message to me should be included in the thread so that others can help)
    I don't know what this subject matter is, but apparently there are some x and y errors in m_nRanges = 4 possible ranges and the error values must fit into m_nBits = 6 bits.

    From http://acode-browser.usatlas.bnl.go...Interfaces/TrigT1Interfaces/L1METvalue.h#0049
    Code (Text):

    0046   /** Number of bits in range */
    0047   static const unsigned int m_nBits = 6;
    0048   /** Number of ET ranges to encode in */
    0049   static const unsigned int m_nRanges = 4;
    0050   /** Mask to select Ex/Ey bits */
    0051   static const unsigned int m_mask = 0x3F;
     
    This code finds the largest absolute X,Y error (line 39) and checks if it can fit into the bits for the error (line 43). If not, it returns an overflow flag and sets METQ to a huge number (line 45).
    Otherwise, it calculates the total squared error METQ (line 57) after removing least significant bits (lines 47-56). I don't really understand lines 47-56, but if you know what these ranges and error values are, you should be able to figure out what it is doing with those bits.

    From http://acode-browser.usatlas.bnl.go...er/TrigT1/TrigT1Interfaces/src/L1METvalue.cxx
    Code (Text):

    0034 void LVL1::L1METvalue::calcL1METQ(int Ex, int Ey, int& METQ, bool& Overflow) {
    0035
    0036   /** Greater of 2 values determines range of bits used */
    0037   unsigned int absEx = std::abs(Ex);
    0038   unsigned int absEy = std::abs(Ey);
    0039   int max = (absEx > absEy ? absEx : absEy);
    0040
    0041   /** If Ex/Ey overflows the LUT input range, trigger fires all thresholds.
    0042       Indicate this with overflow flag and an out of range ETmiss value */
    0043   if ( max >= (1<<(m_nBits+m_nRanges-1)) )  {
    0044     METQ = 16777216; // 4096**2
    0045     Overflow = true;
    0046   }
    0047   /** Otherwise, emulate precision by checking which ET range we are in and
    0048       zeroing bits below that. */
    0049   else {
    0050     for (unsigned int range = 0; range < m_nRanges; ++range) {
    0051       if ( max < (1<<(m_nBits+range)) ) {
    0052         absEx &= (m_mask<<range);
    0053         absEy &= (m_mask<<range);
    0054         break;
    0055       }
    0056     }
    0057     METQ = absEx*absEx + absEy*absEy;
    0058     Overflow = false;
    0059   }
    0060  
    0061 }
     
     
  14. Mar 25, 2017 #13

    ChrisVer

    User Avatar
    Gold Member

    This code calculates the value of missing transverse momentum at the L1-trigger decision.

    in this code it takes the values of etmiss on the x and y axis. There are some cases when the trigger overflows giving extremely large output to the missing energy values- this is dealt in the first if, where they set a default missing energy value at L1 (~4.1TeV) and flag the trigger as overflow (so the trigger fires!). Here for example, this is done when max(|ex|,|ey|)>512GeV.

    In the else, I don't understand what they do either, mainly because I don't have a good intuition of what are those member attributes. That's why I asked whether I understood what happens in the first if-condition and try to understand why someone would use the operators <<, >> in general (so I could try and figure a reason for them to exist- and ultimately get a physical meaning of what this m_* are) instead of the actual numbers they represent...
     
  15. Mar 25, 2017 #14

    FactChecker

    User Avatar
    Science Advisor
    Gold Member

    For some reason the discretes indicating ranges and the ex values are stored in the same variable. Likewise for ey. That's possibly due to them being transmitted together in a compact, encoded data package. So to separate the range information from the ex, ey values, it is necessary to shift the bits left and right to get the data of interest in a good location (also to shift ignored information away). That type of process is easiest to understand using <<, >>, and other bitwise operations.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Bitwise Operators C++
  1. Ternary operator in C (Replies: 13)

Loading...