Home AMX User Forum NetLinx Studio

Bitwise Operation Help

I am writing a module for an Integra Tun-3.7 and I have a question about how to process one of the responses.

The response is !6 HTS 01 01 03 $1A (the spaces were added to seperate the chunks of data)

I am fine seperating out the first chunk [01] = HD or Not HD
I am fine with the second chunk [01] = current HD stream

Its the third that I need help with [03] = available HD streams. There are 8 possible streams and 03 is a hex representation of an 8-bit binary number where each bit is 1 or 0 representing the available streams.

In the example it is [03] = 11000000 which equates to Streams 1 and 2 are available, but 3-8 are not.

I want to then turn on feedback on the touch screen for the streams that are available and put the available streams into an array so I can toggle through the available streams.

Thanks for any help you can give.

Comments

  • TonyAngeloTonyAngelo Posts: 315
    the8thst wrote: »
    In the example it is [03] = 11000000 which equates to Streams 1 and 2 are available, but 3-8 are not.

    I want to then turn on feedback on the touch screen for the streams that are available and put the available streams into an array so I can toggle through the available streams.

    Thanks for any help you can give.

    $03 should read 00000011.

    if sMyChar = $03 (or whatever hex code you get)

    one way would be to individually check each channel for a one or zero

    sMyChar BAND $01 (00000001) will return an $01 if there is a stream present and $00 if there's none

    sMyChar BAND $02 (00000010) will return an $02 if there is a stream present and $00 if there's none

    sMyChar BAND $04 (00000100) will return an $04 if there is a stream present and $00 if there's none

    same for $08 (00001000)

    same for $10 (00010000)

    and so on.

    There may be a better way, that's the first one that came to mind.
  • mpullinmpullin Posts: 949
    I think you got it backwards. 00000011 = 3. But as I understand it, the problem is to isolate which bits are on and which are off. There's a pretty good guide that I got on an AMX.com Tech Note called Bitwise Operations. But I'll summarize how you'd do this anyway.

    First write a function that gets passed an integer n and finds 2^n. This is a pretty easy task, you could even do it recursively if you want.

    Then go through a loop for(i=0;i<8;i++). This will run the loop 8 times, one for each bit.

    If ( 2^i & Chunk3 ) then you know stream (i+1) is available. How? Because you compared the bits of the two numbers using the bitwise AND (&).

    00000011 = 3
    00000001 = 1 = 2^0
    00000001 = 3&1 ... Stream 1 is available

    00000011 = 3
    00000010 = 2 = 2^1
    00000010 = 3&2 ... Stream 2 is available.

    00000011 = 3
    00000100 = 4 = 2^2
    00000000 = 3&4 .... Stream 3 is not available. (because the two numbers had no bits in common)

    and so on.
  • jjamesjjames Posts: 2,908
    TonyAngelo wrote: »
    $03 should read 00000011.

    if sMyChar = $03 (or whatever hex code you get)

    one way would be to individually check each channel for a one or zero

    sMyChar BAND $01 (00000001) will return an $01 if there is a stream present and $00 if there's none

    sMyChar BAND $02 (00000010) will return an $02 if there is a stream present and $00 if there's none

    sMyChar BAND $04 (00000100) will return an $04 if there is a stream present and $00 if there's none

    same for $08 (00001000)

    same for $10 (00010000)

    and so on.

    There may be a better way, that's the first one that came to mind.
    That'd work for me . . . I'd just throw it in a loop and fix it to an array.

    And thanks, I never liked working with binary, and thus far have been able to stay away from it. Now, even I might not be afraid to tackle it! :D
  • ColzieColzie Posts: 470
    I'd skin the cat this way:
    define_function integer fn_bits_of_hex(integer i_hex)
    {
    	stack_var integer i, iBits[8]
    	
    	for(i = 1; i <= 8; i++)
    	{
    		iBits[i] = i_hex BAND $01
    		i_hex = type_cast (i_hex >> 1)
    	}
    	
    	//do something with iBits!
    }
    
    
  • TonyAngeloTonyAngelo Posts: 315
    jjames wrote: »
    Now, even I might not be afraid to tackle it! :D

    Are you trying to imply that if I can figure it out it must not be too hard? :p

    If you're scared of binary then pray you never have to parse feedback from a Krell.
  • jjamesjjames Posts: 2,908
    TonyAngelo wrote: »
    Are you trying to imply that if I can figure it out it must not be too hard? :p

    If you're scared of binary then pray you never have to parse feedback from a Krell.
    Oh I needed a good laugh! Thanks! :p

    Well, the only time I might encounter a Krell is if I'm doing a job for someone else. But thanks for the heads up, I'll be sure that we don't sell any! :D
  • Joe HebertJoe Hebert Posts: 2,159
    One more way:
    Here is a one line function that given a number and a bit position will return the value of the bit. The least most significant bit is bit 0.
    DEFINE_FUNCTION CHAR fnIsBitSet (integer number, char bit) {
         RETURN number & (1<<bit) = 1<<bit
    }
    
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    One more way:
    Here is a one line function that given a number and a bit position will return the value of the bit. The least most significant bit is bit 0.
    DEFINE_FUNCTION CHAR fnIsBitSet (integer number, char bit) {
         RETURN number & (1<<bit) = 1<<bit
    }
    


    You will have to explain that one Joe, as I don't follow but would like to understand. Why is the bit argument a char?
    Not sure what you mean by "least most significant bit". Is that a typo?
    Thanks,
    Paul
  • TonyAngeloTonyAngelo Posts: 315
    Joe Hebert wrote: »
    RETURN number & (1<<bit) = 1<<bit

    This is the bit that I don't get.
  • jjamesjjames Posts: 2,908
    TonyAngelo wrote: »
    This is the bit that I don't get.
    Haha! No pun intended? :p
  • AMXJeffAMXJeff Posts: 450
    Joe's coding is the correct way to do this function. However this may help to explain it better....
    // number value: 0- 65535
    //
    // bit value: 0 - 7
    //7654 3210
    //xxxx xxxx
    DEFINE_FUNCTION CHAR isBitSet (integer number, char bit) 
    {
    	STACK_VAR CHAR cBitValue;
    	
    	// make the bit value, 
    	// Bit 7 = $80 MSB
    	// Bit 6 = $40
    	// Bit 5 = $20
    	// Bit 4 = $10
    	// Bit 3 = $08
    	// Bit 2 = $04
    	// Bit 1 = $02
    	// Bit 0 = $01 LSB
    
    	cBitValue = 1 << bit;	
    
    	IF ((number & cBitValue) == cBitValue)
    		RETURN TRUE;
    	ELSE
    		RETURN FALSE;
    }
    
  • the8thstthe8thst Posts: 470
    Got it.

    Thanks for all the quick replies.
  • jweatherjweather Posts: 320
    a_riot42 wrote: »
    You will have to explain that one Joe, as I don't follow but would like to understand. Why is the bit argument a char?
    Not sure what you mean by "least most significant bit". Is that a typo?
    Thanks,
    Paul

    char is a 8-bit numeric datatype, which is smaller than the 16-bit integer. It can represent values 0-255, which is enough to tell which bit you want out of a 16-bit integer. Also called a byte, short, or uint8 in other programming languages.

    Typo, he meant least significant bit.

    Also, you can simplify the test to "number & (1<<bit) != 0" since it doesn't matter what value it has as long as it isn't zero.

    << is the left-shift operator. 1<<0 = $01 (b00000001). 1<<1 = $02 (b00000010). 1<<7 = $80 (b10000000) The expression (1<<bit) lets you easily mask out the single bit you're interested in.
  • a_riot42a_riot42 Posts: 1,624
    jweather wrote: »
    char is a 8-bit numeric datatype, which is smaller than the 16-bit integer. It can represent values 0-255, which is enough to tell which bit you want out of a 16-bit integer. Also called a byte, short, or uint8 in other programming languages.

    Typo, he meant least significant bit.

    Also, you can simplify the test to "number & (1<<bit) != 0" since it doesn't matter what value it has as long as it isn't zero.

    << is the left-shift operator. 1<<0 = $01 (b00000001). 1<<1 = $02 (b00000010). 1<<7 = $80 (b10000000) The expression (1<<bit) lets you easily mask out the single bit you're interested in.

    Thanks for the explanation. It looked a little odd to me for a couple of reasons, one of which you mentioned (!= 0). The other is that the precedence of & is weaker than != so number will be anded with the result of (1<<bit) != 0 (which will always be 1) rather than having (number & (1<<bit)) compared against 0. Is this not the case? It is in C++ but I don't have a master to test against.

    It may need mentioning to anyone using this function that the value of 'bit' starts at 0 not 1, as in the zeroth bit. So for it to return true for the number 1, bit would have to have a value of 0. I would use an int rather than a char for the argument just for clarity.
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    I didn?t realize one short line of code could swell to such controversy. :)
    a_riot42 wrote:
    It may need mentioning to anyone using this function that the value of 'bit' starts at 0 not 1
    Correct. I mentioned that in my original post and AMXJeff reiterated it. Starting with 0 instead of 1 is the mathematically correct way to do it.
    a_riot42 wrote:
    So for it to return true for the number 1, bit would have to have a value of 0.
    It?s not returning true or false for a number. The function returns the value of a bit of the number passed in. If you pass in any odd number with bit 0 then the function will always return 1 (TRUE) since b0 is always set for an odd number.
    a_riot42 wrote:
    I would use an int rather than a char for the argument just for clarity.
    Curious as to why you feel increasing the memory space of the bit parameter to an INT adds clarity. The only ?legal? values for bit are 0-15 since the integer number passed in is 16 bits wide. But as with many things in the programming world, to each their own. An INT will work just as well as a CHAR. You can also use an INT for the RETURN instead of a CHAR. The data types of the function best suited my needs at at the time.
    a_riot42 wrote:
    It looked a little odd to me for a couple of reasons, one of which you mentioned (!= 0).The other is that the precedence of & is weaker than != so number will be anded with the result of (1<<bit) != 0 (which will always be 1) rather than having (number & (1<<bit)) compared against 0. Is this not the case?
    Yes, that?s not the case. If you test it, you will find the function works exactly as expected and intended.
    TonyAngelo wrote:
    This is the bit that I don't get.
    You?re a very punny guy. (Where did I hear that before?) :D
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    Yes, that?s not the case. If you test it, you will find the function works exactly as expected and intended.

    That puzzles me. I tested it with a C++ compiler and it doesn't work correctly without the added parentheses and the operator precedence in Netlinx is the same as C++. I don't have a master to try it out on though to confirm until Monday.

    Using 9 as the number and 1 as the bit with this code:
    bool isBitSet (int number, int bit) {
         return number & (1<<bit) == 1<<bit;
    }
    

    The result is 1 which is wrong. However, it is right if (1<<bit) == 1<<bit gets evaluated first since that would be 1, and then 9 anded with 1 is of course 1.

    Using 9 as the number and 1 as the bit with this code
    bool isBitSet (int number, int bit) {
         return (number & (1<<bit)) == 1<<bit;
    }
    

    The result is 0 which is correct, since (number & (1<<bit)) gets evaluated first which is 0, and then 0 compared with 1 will return 0.

    I don't understand why it would work with Netlinx code and not C when the operator precedence is the same but I will figure it out Monday I guess.
    Joe Hebert wrote: »
    Curious as to why you feel increasing the memory space of the bit parameter to an INT adds clarity. The only ?legal? values for bit are 0-15 since the integer number passed in is 16 bits wide. But as with many things in the programming world, to each their own. An INT will work just as well as a CHAR. You can also use an INT for the RETURN instead of a CHAR. The data types of the function best suited my needs at at the time.

    Yes it is just a quirk of mine to use an int if you are returning an int value (1 or 0 as you mentioned) and to use a char if you are returning an ascii character. Obviously you can interchange them, but I will generally always sacrifice memory (especially if its only one byte like in this case) for clarity. For instance I will never write:
    char num = 2
    char num2 = 3
    char num3 = num + num2
    

    even though it saves me three bytes as opposed to:
    int num = 2
    int num2 = 3
    int num3 = num + num2
    
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote:
    I don't have a master to try it out on though to confirm until Monday.
    I?ll give you a head start. The following code:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_VARIABLE
    
    DEFINE_FUNCTION INTEGER fnIsBitSet (integer number, integer bit) {
         
         RETURN number & (1<<bit) == 1<<bit
    }
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          INTEGER number
          INTEGER bit
                
          FOR (number=0; number<16; number++) {
    	 SEND_STRING 0,"'Testing number ',ITOA(number),FORMAT(' ($%02X) ',number),'bits 0-15'"
    	 FOR (bit=0; bit<16; bit++) {
    	    SEND_STRING 0, "ITOA(number),FORMAT(' ($%02X) ',number),' bit ',ITOA(bit),' = ',ITOA(fnIsBitSet(number,bit))"
    	 }
    	 SEND_STRING 0,"'---'"
          }
       }
    }
    

    ?produces the following output when button 1 is pushed:
    Line      1 :: Testing number 0 ($00) bits 0-15 - 18:33:15
    Line      2 :: 0 ($00)  bit 0 = 0 - 18:33:15
    Line      3 :: 0 ($00)  bit 1 = 0 - 18:33:15
    Line      4 :: 0 ($00)  bit 2 = 0 - 18:33:15
    Line      5 :: 0 ($00)  bit 3 = 0 - 18:33:15
    Line      6 :: 0 ($00)  bit 4 = 0 - 18:33:15
    Line      7 :: 0 ($00)  bit 5 = 0 - 18:33:15
    Line      8 :: 0 ($00)  bit 6 = 0 - 18:33:15
    Line      9 :: 0 ($00)  bit 7 = 0 - 18:33:15
    Line     10 :: 0 ($00)  bit 8 = 0 - 18:33:15
    Line     11 :: 0 ($00)  bit 9 = 0 - 18:33:15
    Line     12 :: 0 ($00)  bit 10 = 0 - 18:33:15
    Line     13 :: 0 ($00)  bit 11 = 0 - 18:33:15
    Line     14 :: 0 ($00)  bit 12 = 0 - 18:33:15
    Line     15 :: 0 ($00)  bit 13 = 0 - 18:33:15
    Line     16 :: 0 ($00)  bit 14 = 0 - 18:33:15
    Line     17 :: 0 ($00)  bit 15 = 0 - 18:33:15
    Line     18 :: --- - 18:33:15
    Line     19 :: Testing number 1 ($01) bits 0-15 - 18:33:15
    Line     20 :: 1 ($01)  bit 0 = 1 - 18:33:15
    Line     21 :: 1 ($01)  bit 1 = 0 - 18:33:15
    Line     22 :: 1 ($01)  bit 2 = 0 - 18:33:15
    Line     23 :: 1 ($01)  bit 3 = 0 - 18:33:15
    Line     24 :: 1 ($01)  bit 4 = 0 - 18:33:15
    Line     25 :: 1 ($01)  bit 5 = 0 - 18:33:15
    Line     26 :: 1 ($01)  bit 6 = 0 - 18:33:15
    Line     27 :: 1 ($01)  bit 7 = 0 - 18:33:15
    Line     28 :: 1 ($01)  bit 8 = 0 - 18:33:15
    Line     29 :: 1 ($01)  bit 9 = 0 - 18:33:15
    Line     30 :: 1 ($01)  bit 10 = 0 - 18:33:15
    Line     31 :: 1 ($01)  bit 11 = 0 - 18:33:15
    Line     32 :: 1 ($01)  bit 12 = 0 - 18:33:15
    Line     33 :: 1 ($01)  bit 13 = 0 - 18:33:15
    Line     34 :: 1 ($01)  bit 14 = 0 - 18:33:15
    Line     35 :: 1 ($01)  bit 15 = 0 - 18:33:15
    Line     36 :: --- - 18:33:15
    Line     37 :: Testing number 2 ($02) bits 0-15 - 18:33:15
    Line     38 :: 2 ($02)  bit 0 = 0 - 18:33:15
    Line     39 :: 2 ($02)  bit 1 = 1 - 18:33:15
    Line     40 :: 2 ($02)  bit 2 = 0 - 18:33:15
    Line     41 :: 2 ($02)  bit 3 = 0 - 18:33:15
    Line     42 :: 2 ($02)  bit 4 = 0 - 18:33:15
    Line     43 :: 2 ($02)  bit 5 = 0 - 18:33:15
    Line     44 :: 2 ($02)  bit 6 = 0 - 18:33:15
    Line     45 :: 2 ($02)  bit 7 = 0 - 18:33:15
    Line     46 :: 2 ($02)  bit 8 = 0 - 18:33:15
    Line     47 :: 2 ($02)  bit 9 = 0 - 18:33:15
    Line     48 :: 2 ($02)  bit 10 = 0 - 18:33:15
    Line     49 :: 2 ($02)  bit 11 = 0 - 18:33:15
    Line     50 :: 2 ($02)  bit 12 = 0 - 18:33:15
    Line     51 :: 2 ($02)  bit 13 = 0 - 18:33:15
    Line     52 :: 2 ($02)  bit 14 = 0 - 18:33:15
    Line     53 :: 2 ($02)  bit 15 = 0 - 18:33:15
    Line     54 :: --- - 18:33:15
    Line     55 :: Testing number 3 ($03) bits 0-15 - 18:33:15
    Line     56 :: 3 ($03)  bit 0 = 1 - 18:33:15
    Line     57 :: 3 ($03)  bit 1 = 1 - 18:33:15
    Line     58 :: 3 ($03)  bit 2 = 0 - 18:33:15
    Line     59 :: 3 ($03)  bit 3 = 0 - 18:33:15
    Line     60 :: 3 ($03)  bit 4 = 0 - 18:33:15
    Line     61 :: 3 ($03)  bit 5 = 0 - 18:33:15
    Line     62 :: 3 ($03)  bit 6 = 0 - 18:33:15
    Line     63 :: 3 ($03)  bit 7 = 0 - 18:33:15
    Line     64 :: 3 ($03)  bit 8 = 0 - 18:33:15
    Line     65 :: 3 ($03)  bit 9 = 0 - 18:33:15
    Line     66 :: 3 ($03)  bit 10 = 0 - 18:33:15
    Line     67 :: 3 ($03)  bit 11 = 0 - 18:33:15
    Line     68 :: 3 ($03)  bit 12 = 0 - 18:33:15
    Line     69 :: 3 ($03)  bit 13 = 0 - 18:33:15
    Line     70 :: 3 ($03)  bit 14 = 0 - 18:33:15
    Line     71 :: 3 ($03)  bit 15 = 0 - 18:33:15
    Line     72 :: --- - 18:33:15
    Line     73 :: Testing number 4 ($04) bits 0-15 - 18:33:15
    Line     74 :: 4 ($04)  bit 0 = 0 - 18:33:15
    Line     75 :: 4 ($04)  bit 1 = 0 - 18:33:15
    Line     76 :: 4 ($04)  bit 2 = 1 - 18:33:15
    Line     77 :: 4 ($04)  bit 3 = 0 - 18:33:15
    Line     78 :: 4 ($04)  bit 4 = 0 - 18:33:15
    Line     79 :: 4 ($04)  bit 5 = 0 - 18:33:15
    Line     80 :: 4 ($04)  bit 6 = 0 - 18:33:15
    Line     81 :: 4 ($04)  bit 7 = 0 - 18:33:15
    Line     82 :: 4 ($04)  bit 8 = 0 - 18:33:15
    Line     83 :: 4 ($04)  bit 9 = 0 - 18:33:15
    Line     84 :: 4 ($04)  bit 10 = 0 - 18:33:15
    Line     85 :: 4 ($04)  bit 11 = 0 - 18:33:15
    Line     86 :: 4 ($04)  bit 12 = 0 - 18:33:15
    Line     87 :: 4 ($04)  bit 13 = 0 - 18:33:15
    Line     88 :: 4 ($04)  bit 14 = 0 - 18:33:15
    Line     89 :: 4 ($04)  bit 15 = 0 - 18:33:15
    Line     90 :: --- - 18:33:15
    Line     91 :: Testing number 5 ($05) bits 0-15 - 18:33:15
    Line     92 :: 5 ($05)  bit 0 = 1 - 18:33:15
    Line     93 :: 5 ($05)  bit 1 = 0 - 18:33:15
    Line     94 :: 5 ($05)  bit 2 = 1 - 18:33:15
    Line     95 :: 5 ($05)  bit 3 = 0 - 18:33:15
    Line     96 :: 5 ($05)  bit 4 = 0 - 18:33:15
    Line     97 :: 5 ($05)  bit 5 = 0 - 18:33:15
    Line     98 :: 5 ($05)  bit 6 = 0 - 18:33:15
    Line     99 :: 5 ($05)  bit 7 = 0 - 18:33:15
    Line    100 :: 5 ($05)  bit 8 = 0 - 18:33:15
    Line    101 :: 5 ($05)  bit 9 = 0 - 18:33:15
    Line    102 :: 5 ($05)  bit 10 = 0 - 18:33:15
    Line    103 :: 5 ($05)  bit 11 = 0 - 18:33:15
    Line    104 :: 5 ($05)  bit 12 = 0 - 18:33:15
    Line    105 :: 5 ($05)  bit 13 = 0 - 18:33:15
    Line    106 :: 5 ($05)  bit 14 = 0 - 18:33:15
    Line    107 :: 5 ($05)  bit 15 = 0 - 18:33:15
    Line    108 :: --- - 18:33:15
    Line    109 :: Testing number 6 ($06) bits 0-15 - 18:33:15
    Line    110 :: 6 ($06)  bit 0 = 0 - 18:33:15
    Line    111 :: 6 ($06)  bit 1 = 1 - 18:33:15
    Line    112 :: 6 ($06)  bit 2 = 1 - 18:33:15
    Line    113 :: 6 ($06)  bit 3 = 0 - 18:33:15
    Line    114 :: 6 ($06)  bit 4 = 0 - 18:33:15
    Line    115 :: 6 ($06)  bit 5 = 0 - 18:33:15
    Line    116 :: 6 ($06)  bit 6 = 0 - 18:33:15
    Line    117 :: 6 ($06)  bit 7 = 0 - 18:33:15
    Line    118 :: 6 ($06)  bit 8 = 0 - 18:33:15
    Line    119 :: 6 ($06)  bit 9 = 0 - 18:33:15
    Line    120 :: 6 ($06)  bit 10 = 0 - 18:33:15
    Line    121 :: 6 ($06)  bit 11 = 0 - 18:33:15
    Line    122 :: 6 ($06)  bit 12 = 0 - 18:33:15
    Line    123 :: 6 ($06)  bit 13 = 0 - 18:33:15
    Line    124 :: 6 ($06)  bit 14 = 0 - 18:33:15
    Line    125 :: 6 ($06)  bit 15 = 0 - 18:33:15
    Line    126 :: --- - 18:33:15
    Line    127 :: Testing number 7 ($07) bits 0-15 - 18:33:15
    Line    128 :: 7 ($07)  bit 0 = 1 - 18:33:15
    Line    129 :: 7 ($07)  bit 1 = 1 - 18:33:15
    Line    130 :: 7 ($07)  bit 2 = 1 - 18:33:15
    Line    131 :: 7 ($07)  bit 3 = 0 - 18:33:15
    Line    132 :: 7 ($07)  bit 4 = 0 - 18:33:15
    Line    133 :: 7 ($07)  bit 5 = 0 - 18:33:15
    Line    134 :: 7 ($07)  bit 6 = 0 - 18:33:15
    Line    135 :: 7 ($07)  bit 7 = 0 - 18:33:15
    Line    136 :: 7 ($07)  bit 8 = 0 - 18:33:15
    Line    137 :: 7 ($07)  bit 9 = 0 - 18:33:15
    Line    138 :: 7 ($07)  bit 10 = 0 - 18:33:15
    Line    139 :: 7 ($07)  bit 11 = 0 - 18:33:15
    Line    140 :: 7 ($07)  bit 12 = 0 - 18:33:15
    Line    141 :: 7 ($07)  bit 13 = 0 - 18:33:15
    Line    142 :: 7 ($07)  bit 14 = 0 - 18:33:15
    Line    143 :: 7 ($07)  bit 15 = 0 - 18:33:15
    Line    144 :: --- - 18:33:15
    Line    145 :: Testing number 8 ($08) bits 0-15 - 18:33:15
    Line    146 :: 8 ($08)  bit 0 = 0 - 18:33:15
    Line    147 :: 8 ($08)  bit 1 = 0 - 18:33:15
    Line    148 :: 8 ($08)  bit 2 = 0 - 18:33:15
    Line    149 :: 8 ($08)  bit 3 = 1 - 18:33:15
    Line    150 :: 8 ($08)  bit 4 = 0 - 18:33:15
    Line    151 :: 8 ($08)  bit 5 = 0 - 18:33:15
    Line    152 :: 8 ($08)  bit 6 = 0 - 18:33:15
    Line    153 :: 8 ($08)  bit 7 = 0 - 18:33:15
    Line    154 :: 8 ($08)  bit 8 = 0 - 18:33:15
    Line    155 :: 8 ($08)  bit 9 = 0 - 18:33:15
    Line    156 :: 8 ($08)  bit 10 = 0 - 18:33:15
    Line    157 :: 8 ($08)  bit 11 = 0 - 18:33:15
    Line    158 :: 8 ($08)  bit 12 = 0 - 18:33:15
    Line    159 :: 8 ($08)  bit 13 = 0 - 18:33:15
    Line    160 :: 8 ($08)  bit 14 = 0 - 18:33:15
    Line    161 :: 8 ($08)  bit 15 = 0 - 18:33:15
    Line    162 :: --- - 18:33:15
    Line    163 :: Testing number 9 ($09) bits 0-15 - 18:33:15
    Line    164 :: 9 ($09)  bit 0 = 1 - 18:33:15
    Line    165 :: 9 ($09)  bit 1 = 0 - 18:33:15
    Line    166 :: 9 ($09)  bit 2 = 0 - 18:33:15
    Line    167 :: 9 ($09)  bit 3 = 1 - 18:33:15
    Line    168 :: 9 ($09)  bit 4 = 0 - 18:33:15
    Line    169 :: 9 ($09)  bit 5 = 0 - 18:33:15
    Line    170 :: 9 ($09)  bit 6 = 0 - 18:33:15
    Line    171 :: 9 ($09)  bit 7 = 0 - 18:33:15
    Line    172 :: 9 ($09)  bit 8 = 0 - 18:33:15
    Line    173 :: 9 ($09)  bit 9 = 0 - 18:33:15
    Line    174 :: 9 ($09)  bit 10 = 0 - 18:33:15
    Line    175 :: 9 ($09)  bit 11 = 0 - 18:33:15
    Line    176 :: 9 ($09)  bit 12 = 0 - 18:33:15
    Line    177 :: 9 ($09)  bit 13 = 0 - 18:33:15
    Line    178 :: 9 ($09)  bit 14 = 0 - 18:33:15
    Line    179 :: 9 ($09)  bit 15 = 0 - 18:33:15
    Line    180 :: --- - 18:33:15
    Line    181 :: Testing number 10 ($0A) bits 0-15 - 18:33:15
    Line    182 :: 10 ($0A)  bit 0 = 0 - 18:33:15
    Line    183 :: 10 ($0A)  bit 1 = 1 - 18:33:15
    Line    184 :: 10 ($0A)  bit 2 = 0 - 18:33:15
    Line    185 :: 10 ($0A)  bit 3 = 1 - 18:33:15
    Line    186 :: 10 ($0A)  bit 4 = 0 - 18:33:15
    Line    187 :: 10 ($0A)  bit 5 = 0 - 18:33:15
    Line    188 :: 10 ($0A)  bit 6 = 0 - 18:33:15
    Line    189 :: 10 ($0A)  bit 7 = 0 - 18:33:15
    Line    190 :: 10 ($0A)  bit 8 = 0 - 18:33:15
    Line    191 :: 10 ($0A)  bit 9 = 0 - 18:33:15
    Line    192 :: 10 ($0A)  bit 10 = 0 - 18:33:15
    Line    193 :: 10 ($0A)  bit 11 = 0 - 18:33:15
    Line    194 :: 10 ($0A)  bit 12 = 0 - 18:33:15
    Line    195 :: 10 ($0A)  bit 13 = 0 - 18:33:15
    Line    196 :: 10 ($0A)  bit 14 = 0 - 18:33:15
    Line    197 :: 10 ($0A)  bit 15 = 0 - 18:33:15
    Line    198 :: --- - 18:33:15
    Line    199 :: Testing number 11 ($0B) bits 0-15 - 18:33:15
    Line    200 :: 11 ($0B)  bit 0 = 1 - 18:33:15
    Line    201 :: 11 ($0B)  bit 1 = 1 - 18:33:15
    Line    202 :: 11 ($0B)  bit 2 = 0 - 18:33:15
    Line    203 :: 11 ($0B)  bit 3 = 1 - 18:33:15
    Line    204 :: 11 ($0B)  bit 4 = 0 - 18:33:15
    Line    205 :: 11 ($0B)  bit 5 = 0 - 18:33:15
    Line    206 :: 11 ($0B)  bit 6 = 0 - 18:33:15
    Line    207 :: 11 ($0B)  bit 7 = 0 - 18:33:15
    Line    208 :: 11 ($0B)  bit 8 = 0 - 18:33:15
    Line    209 :: 11 ($0B)  bit 9 = 0 - 18:33:15
    Line    210 :: 11 ($0B)  bit 10 = 0 - 18:33:15
    Line    211 :: 11 ($0B)  bit 11 = 0 - 18:33:15
    Line    212 :: 11 ($0B)  bit 12 = 0 - 18:33:15
    Line    213 :: 11 ($0B)  bit 13 = 0 - 18:33:15
    Line    214 :: 11 ($0B)  bit 14 = 0 - 18:33:15
    Line    215 :: 11 ($0B)  bit 15 = 0 - 18:33:15
    Line    216 :: --- - 18:33:15
    Line    217 :: Testing number 12 ($0C) bits 0-15 - 18:33:15
    Line    218 :: 12 ($0C)  bit 0 = 0 - 18:33:15
    Line    219 :: 12 ($0C)  bit 1 = 0 - 18:33:15
    Line    220 :: 12 ($0C)  bit 2 = 1 - 18:33:15
    Line    221 :: 12 ($0C)  bit 3 = 1 - 18:33:15
    Line    222 :: 12 ($0C)  bit 4 = 0 - 18:33:15
    Line    223 :: 12 ($0C)  bit 5 = 0 - 18:33:15
    Line    224 :: 12 ($0C)  bit 6 = 0 - 18:33:15
    Line    225 :: 12 ($0C)  bit 7 = 0 - 18:33:15
    Line    226 :: 12 ($0C)  bit 8 = 0 - 18:33:15
    Line    227 :: 12 ($0C)  bit 9 = 0 - 18:33:15
    Line    228 :: 12 ($0C)  bit 10 = 0 - 18:33:15
    Line    229 :: 12 ($0C)  bit 11 = 0 - 18:33:15
    Line    230 :: 12 ($0C)  bit 12 = 0 - 18:33:15
    Line    231 :: 12 ($0C)  bit 13 = 0 - 18:33:15
    Line    232 :: 12 ($0C)  bit 14 = 0 - 18:33:15
    Line    233 :: 12 ($0C)  bit 15 = 0 - 18:33:15
    Line    234 :: --- - 18:33:15
    Line    235 :: Testing number 13 ($0D) bits 0-15 - 18:33:15
    Line    236 :: 13 ($0D)  bit 0 = 1 - 18:33:15
    Line    237 :: 13 ($0D)  bit 1 = 0 - 18:33:15
    Line    238 :: 13 ($0D)  bit 2 = 1 - 18:33:15
    Line    239 :: 13 ($0D)  bit 3 = 1 - 18:33:15
    Line    240 :: 13 ($0D)  bit 4 = 0 - 18:33:15
    Line    241 :: 13 ($0D)  bit 5 = 0 - 18:33:15
    Line    242 :: 13 ($0D)  bit 6 = 0 - 18:33:15
    Line    243 :: 13 ($0D)  bit 7 = 0 - 18:33:15
    Line    244 :: 13 ($0D)  bit 8 = 0 - 18:33:15
    Line    245 :: 13 ($0D)  bit 9 = 0 - 18:33:15
    Line    246 :: 13 ($0D)  bit 10 = 0 - 18:33:15
    Line    247 :: 13 ($0D)  bit 11 = 0 - 18:33:15
    Line    248 :: 13 ($0D)  bit 12 = 0 - 18:33:15
    Line    249 :: 13 ($0D)  bit 13 = 0 - 18:33:15
    Line    250 :: 13 ($0D)  bit 14 = 0 - 18:33:15
    Line    251 :: 13 ($0D)  bit 15 = 0 - 18:33:15
    Line    252 :: --- - 18:33:15
    Line    253 :: Testing number 14 ($0E) bits 0-15 - 18:33:15
    Line    254 :: 14 ($0E)  bit 0 = 0 - 18:33:15
    Line    255 :: 14 ($0E)  bit 1 = 1 - 18:33:15
    Line    256 :: 14 ($0E)  bit 2 = 1 - 18:33:15
    Line    257 :: 14 ($0E)  bit 3 = 1 - 18:33:15
    Line    258 :: 14 ($0E)  bit 4 = 0 - 18:33:15
    Line    259 :: 14 ($0E)  bit 5 = 0 - 18:33:15
    Line    260 :: 14 ($0E)  bit 6 = 0 - 18:33:15
    Line    261 :: 14 ($0E)  bit 7 = 0 - 18:33:15
    Line    262 :: 14 ($0E)  bit 8 = 0 - 18:33:15
    Line    263 :: 14 ($0E)  bit 9 = 0 - 18:33:15
    Line    264 :: 14 ($0E)  bit 10 = 0 - 18:33:15
    Line    265 :: 14 ($0E)  bit 11 = 0 - 18:33:15
    Line    266 :: 14 ($0E)  bit 12 = 0 - 18:33:15
    Line    267 :: 14 ($0E)  bit 13 = 0 - 18:33:15
    Line    268 :: 14 ($0E)  bit 14 = 0 - 18:33:15
    Line    269 :: 14 ($0E)  bit 15 = 0 - 18:33:15
    Line    270 :: --- - 18:33:15
    Line    271 :: Testing number 15 ($0F) bits 0-15 - 18:33:15
    Line    272 :: 15 ($0F)  bit 0 = 1 - 18:33:15
    Line    273 :: 15 ($0F)  bit 1 = 1 - 18:33:15
    Line    274 :: 15 ($0F)  bit 2 = 1 - 18:33:15
    Line    275 :: 15 ($0F)  bit 3 = 1 - 18:33:15
    Line    276 :: 15 ($0F)  bit 4 = 0 - 18:33:15
    Line    277 :: 15 ($0F)  bit 5 = 0 - 18:33:15
    Line    278 :: 15 ($0F)  bit 6 = 0 - 18:33:15
    Line    279 :: 15 ($0F)  bit 7 = 0 - 18:33:15
    Line    280 :: 15 ($0F)  bit 8 = 0 - 18:33:15
    Line    281 :: 15 ($0F)  bit 9 = 0 - 18:33:15
    Line    282 :: 15 ($0F)  bit 10 = 0 - 18:33:15
    Line    283 :: 15 ($0F)  bit 11 = 0 - 18:33:15
    Line    284 :: 15 ($0F)  bit 12 = 0 - 18:33:15
    Line    285 :: 15 ($0F)  bit 13 = 0 - 18:33:15
    Line    286 :: 15 ($0F)  bit 14 = 0 - 18:33:15
    Line    287 :: 15 ($0F)  bit 15 = 0 - 18:33:15
    Line    288 :: --- - 18:33:15
    
  • a_riot42a_riot42 Posts: 1,624
    Interesting. Thanks for running the test. The = was changed to == though. I wonder if that made a difference. Can you run the same test using = like the original post?
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    It doesn?t make a difference in Netlinx. I ran the tests and the results are the same either way.
    a_riot42 wrote: »
    Interesting. Thanks for running the test. The = was changed to == though. I wonder if that made a difference. Can you run the same test using = like the original post?
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    And for the record, the simplified version that jweather suggested returns exactly the same results also.
    RETURN number & (1<<bit) != 0
  • jweatherjweather Posts: 320
    a_riot42 is correct about precedence in C++, and the NetLinx programming manual shows operator precedence in approximately the same order (Principles of Programming page 41), with =, ==, and <> at level 5 and & at level 6. However, it doesn't seem to actually be implemented that way (anybody else shocked? no?)

    Extra parens never hurt anything... if you're worried about it, just write (number & (1<<bit)) != 0 to ensure it evaluates the way you intended it.
  • a_riot42a_riot42 Posts: 1,624
    jweather wrote: »
    a_riot42 is correct about precedence in C++, and the NetLinx programming manual shows operator precedence in approximately the same order (Principles of Programming page 41), with =, ==, and <> at level 5 and & at level 6. However, it doesn't seem to actually be implemented that way (anybody else shocked? no?)

    Extra parens never hurt anything... if you're worried about it, just write (number & (1<<bit)) != 0 to ensure it evaluates the way you intended it.

    This does shock me. It's not that I am worried about it or being pedantic (not saying you are saying that) but if something as basic as operator precedence can't be relied upon it is a concern. Since Netlinx operator precedence is the same as most other languages I assume its a bug and not a mistake in the docs.
    Paul
  • DHawthorneDHawthorne Posts: 4,584
    I've never relied on precedence rules, because I can't rely on someone else reading my code to know them enough to figure out what's going on. So I always "force" precedence with parentheses when it's not just a simple operation.

    There was a time in my early programming days that I went out of my way to write terse, ultra-tight code, and relied heavily on precedence rules to minimize the source footprint. But I've long since decided that it's just not worth it in this day of large memory pools.
  • a_riot42a_riot42 Posts: 1,624
    DHawthorne wrote: »
    I've never relied on precedence rules, because I can't rely on someone else reading my code to know them enough to figure out what's going on. So I always "force" precedence with parentheses when it's not just a simple operation.

    There was a time in my early programming days that I went out of my way to write terse, ultra-tight code, and relied heavily on precedence rules to minimize the source footprint. But I've long since decided that it's just not worth it in this day of large memory pools.

    I couldn't agree more, but that is no excuse for the compiler to compile code incorrectly. You have to be able to rely on the compiler to do what the docs say and not behave in an undefined way. Using parentheses is supposed to be for making the code more readable to humans, not for forcing the compiler to do what the docs say it should do, especially about something so basic as operator precedence.
    Paul
  • DHawthorneDHawthorne Posts: 4,584
    a_riot42 wrote: »
    I couldn't agree more, but that is no excuse for the compiler to compile code incorrectly. You have to be able to rely on the compiler to do what the docs say and not behave in an undefined way. Using parentheses is supposed to be for making the code more readable to humans, not for forcing the compiler to do what the docs say it should do, especially about something so basic as operator precedence.
    Paul

    You are right, of course. I just thought that a good opening to share that particular viewpoint. I suppose it was a left-handed way of saying I never saw that particular bug because of my "readability" habit.
  • viningvining Posts: 4,368

    I'm just adding to this post since I found it and it helped me sort out what I wanted. In my case I wanted to create an array of the bits in a byte and the code posted above will just let you know if a particular bit is set.

    These are the variations I came up with:

    DEFINE_FUNCTION CHAR[8]fnConvByteBitsToArray(CHAR iByte)//w/ $FF returns 1,1,1,1,1,1,1,1 (decimal or hex, won't see in ascii)
    
         {
         STACK_VAR INTEGER i;
         STACK_VAR CHAR cTmpArry[8];
    
         for(i=0;i<=7;i++)
          {
          cTmpArry = "TYPE_CAST((iByte >> i ) & $01),cTmpArry";
          }
         RETURN cTmpArry;
         }
    
    DEFINE_FUNCTION INTEGER[8]fnConvByteBitsToArray_1(CHAR iByte)//w/ $FF returns 1,1,1,1,1,1,1,1
    
         {
         STACK_VAR INTEGER i;
         STACK_VAR INTEGER nTmpArry[8];
    
         for(i=0;i<=7;i++)
          {
          nTmpArry[8-i] = TYPE_CAST((iByte >> i ) & $01);
          }
         RETURN nTmpArry;
         }
    
    DEFINE_FUNCTION INTEGER[8]fnConvByteBitsToArray_2(CHAR iByte)//w/ $FF returns 1,1,1,1,1,1,1,1
    
         {
         STACK_VAR INTEGER i;
         STACK_VAR INTEGER nTmpArry[8];
    
         for(i=0;i<=7;i++)
          {
          nTmpArry[8-i] = (iByte & ($01 << i) != 0);
          }
         RETURN nTmpArry;
         }
    
    DEFINE_FUNCTION INTEGER[8]fnConvByteBitsToArray_3(CHAR iByte)//w/ $FF returns 128,64,32,16,8,4,2,1 //returns the vlaue of its bit position if set
    
         {
         STACK_VAR INTEGER i;
         STACK_VAR INTEGER nTmpArry[8];
    
         for(i=0;i<=7;i++)
          {
          nTmpArry[8-i] = TYPE_CAST(iByte & ($01 << i));
          }
         RETURN nTmpArry;
         }
    

    For testing I just drop these else if's in my code and set the var values in debug which is why they're local var except for the nRunTest which is a global

    else if(nRunTest==7)
          {
          LOCAL_VAR CHAR cCheckByte;
          LOCAL_VAR CHAR cBitArray[8];
    
          cBitArray = fnConvByteBitsToArray(cCheckByte);
          }
         else if(nRunTest==8)
          {
          LOCAL_VAR CHAR cCheckByte1;
          LOCAL_VAR INTEGER nBitArray1[8];
    
          nBitArray1 = fnConvByteBitsToArray_1(cCheckByte1);
          }
         else if(nRunTest==9)
          {
          LOCAL_VAR CHAR cCheckByte2;
          LOCAL_VAR INTEGER nBitArray2[8];
    
          nBitArray2 = fnConvByteBitsToArray_2(cCheckByte2);
          }
         else if(nRunTest==10)
          {
          LOCAL_VAR CHAR cCheckByte3;
          LOCAL_VAR INTEGER nBitArray3[8];
    
          nBitArray3 = fnConvByteBitsToArray_3(cCheckByte3);
          }
         if(nRunTest)
          {
          nRunTest=0;
          }
    
  • And while this thread is resurrected, an AMX library posted by David Vine on GitHub:

    https://github.com/AMXAUNZ/amx-util-library

    Contains some functions for converting between "typical" data and ASCII strings containing binary representations of the data values. There's more in the library, but it's unfinished.
    Could be worth to have a look.

Sign In or Register to comment.