### Author Topic: Tricky Bools!  (Read 2173 times)

0 Members and 1 Guest are viewing this topic.

#### z64555

• 210
• Self-proclaimed controls expert
##### Tricky Bools!
We've been doing a bit of maintenance with the flags system in FSO, and something interesting came up that made me stop and think.

Specifically, this:

Code: [Select]
`#define VM_PADLOCK_UP    (1 << 7)#define VM_PADLOCK_REAR  (1 << 8)#define VM_PADLOCK_LEFT  (1 << 9)#define VM_PADLOCK_RIGHT (1 << 10)#define VM_PADLOCK_ANY   (VM_PADLOCK_UP|VM_PADLOCK_REAR|VM_PADLOCK_LEFT|VM_PADLOCK_RIGHT)int Viewer_mode;// Version Aif (Viewer_mode & ~VM_PADLOCK_ANY) {}// Version Bif (~Viewer_mode & VM_PADLOCK_ANY) {}`
Note versions A and B, which differ only by the location of operator~, which is the bitwise NOT operator (makes all 0's into 1's and 1's into 0's). When placed in an if{} statement, C and C++ regards a non-boolean value (ints, floats, etc.) as TRUE if any bits in the value are 1's (that is, if the value is nonzero, it is TRUE). This little quirk will make things difficult for us as you'll soon see.

Code: [Select]
`// Version ALHS  RHS00 & ~00 -> 00 & 11 -> 00 -> FALSE  // A right-hand operand of 00 makes no sense for flag checking, so we don't use it01 & ~00 -> 01 & 11 -> 01 -> TRUE10 & ~00 -> 10 & 11 -> 10 -> TRUE11 & ~00 -> 11 & 11 -> 11 -> TRUE00 & ~01 -> 00 & 10 -> 00 -> FALSE01 & ~01 -> 01 & 10 -> 00 -> FALSE10 & ~01 -> 10 & 10 -> 10 -> TRUE11 & ~01 -> 11 & 10 -> 10 -> TRUE00 & ~10 -> 00 & 01 -> 00 -> FALSE01 & ~10 -> 01 & 01 -> 01 -> TRUE10 & ~10 -> 10 & 01 -> 00 -> FALSE11 & ~10 -> 11 & 01 -> 01 -> TRUE00 & ~11 -> 00 & 00 -> 00 -> FALSE01 & ~11 -> 01 & 00 -> 00 -> FALSE10 & ~11 -> 10 & 00 -> 00 -> FALSE11 & ~11 -> 11 & 00 -> 00 -> FALSE//Version BLHS  RHS~00 & 00 -> 11 & 00 -> 00 -> FALSE~01 & 00 -> 10 & 00 -> 00 -> FALSE~10 & 00 -> 01 & 00 -> 00 -> FALSE~11 & 00 -> 00 & 00 -> 00 -> FALSE~00 & 01 -> 11 & 01 -> 01 -> TRUE~01 & 01 -> 10 & 01 -> 00 -> FALSE~10 & 01 -> 01 & 01 -> 01 -> TRUE~11 & 01 -> 00 & 01 -> 00 -> FALSE      ~00 & 10 -> 11 & 10 -> 10 -> TRUE~01 & 10 -> 10 & 10 -> 10 -> TRUE~10 & 10 -> 01 & 10 -> 00 -> FALSE~11 & 10 -> 00 & 10 -> 00 -> FALSE      ~00 & 11 -> 11 & 11 -> 11 -> TRUE~01 & 11 -> 10 & 11 -> 10 -> TRUE~10 & 11 -> 01 & 11 -> 01 -> TRUE~11 & 11 -> 00 & 11 -> 00 -> FALSE`

As you can see from the snippet, the two versions are not the same.

Version A seems to check if any of the flags that are 0's in the RHS operand are 1's in the LHS.

Version B seems to check if any flags that are 1's in the RHS operand are 0's in the LHS.

Let's toss in another bit to see if these general rules hold up:

Code: [Select]
`// Version A000 & ~001 -> 000 & 110 -> 000 -> FALSE001 & ~001 -> 001 & 110 -> 000 -> FALSE010 & ~001 -> 010 & 110 -> 010 -> TRUE011 & ~001 -> 011 & 110 -> 010 -> TRUE100 & ~001 -> 100 & 110 -> 100 -> TRUE101 & ~001 -> 101 & 110 -> 100 -> TRUE110 & ~001 -> 110 & 110 -> 110 -> TRUE111 & ~001 -> 111 & 110 -> 110 -> TRUE000 & ~010 -> 000 & 101 -> 000 -> FALSE001 & ~010 -> 001 & 101 -> 001 -> TRUE010 & ~010 -> 010 & 101 -> 000 -> FALSE011 & ~010 -> 011 & 101 -> 001 -> TRUE100 & ~010 -> 100 & 101 -> 100 -> TRUE101 & ~010 -> 101 & 101 -> 101 -> TRUE110 & ~010 -> 110 & 101 -> 100 -> TRUE111 & ~010 -> 111 & 101 -> 101 -> TRUE000 & ~011 -> 000 & 100 -> 000 -> FALSE001 & ~011 -> 001 & 100 -> 000 -> FALSE010 & ~011 -> 010 & 100 -> 000 -> FALSE011 & ~011 -> 011 & 100 -> 000 -> FALSE100 & ~011 -> 100 & 100 -> 100 -> TRUE101 & ~011 -> 101 & 100 -> 100 -> TRUE110 & ~011 -> 110 & 100 -> 100 -> TRUE111 & ~011 -> 111 & 100 -> 100 -> TRUE000 & ~111 -> 000 & 000-> 000 -> FALSE001 & ~111 -> 001 & 000-> 000 -> FALSE010 & ~111 -> FALSE011 & ~111 -> FALSE100 & ~111 -> FALSE101 & ~111 -> FALSE110 & ~111 -> FALSE111 & ~111 -> FALSE//Version B~000 & 001 -> 111 & 001 -> 001 -> TRUE~001 & 001 -> 110 & 001 -> 000 -> FALSE~010 & 001 -> 101 & 001 -> 001 -> TRUE~011 & 001 -> 100 & 001 -> 000 -> FALSE~100 & 001 -> 011 & 001 -> 001 -> TRUE~101 & 001 -> 010 & 001 -> 000 -> FALSE~110 & 001 -> 001 & 001 -> 001 -> TRUE~111 & 001 -> 000 & 001 -> 000 -> FALSE~000 & 010 -> 111 & 010 -> 010 -> TRUE~001 & 010 -> 110 & 010 -> 010 -> TRUE~010 & 010 -> 101 & 010 -> 000 -> FALSE~011 & 010 -> 100 & 010 -> 000 -> FALSE~100 & 010 -> 011 & 010 -> 010 -> TRUE~101 & 010 -> 010 & 010 -> 010 -> TRUE~110 & 010 -> 001 & 010 -> 000 -> FALSE~111 & 010 -> 000 & 010 -> 000 -> FALSE~000 & 011 -> 111 & 011 -> 011 -> TRUE~001 & 011 -> 110 & 011 -> 010 -> TRUE~010 & 011 -> 101 & 011 -> 001 -> TRUE~011 & 011 -> 100 & 011 -> 000 -> FALSE~100 & 011 -> 011 & 011 -> 011 -> TRUE~101 & 011 -> 010 & 011 -> 010 -> TRUE~110 & 011 -> 001 & 011 -> 001 -> TRUE~111 & 011 -> 000 & 011 -> 000 -> FALSE~100 & 111 -> 111 & 111 -> 111 -> TRUE~001 & 111 -> 110 & 111 -> 110 -> TRUE~010 & 111 -> 101 & 111 -> 101 -> TRUE~011 & 111 -> 100 & 111 -> 100 -> TRUE~100 & 111 -> 011 & 111 -> 011 -> TRUE~101 & 111 -> 010 & 111 -> 010 -> TRUE~110 & 111 -> 001 & 111 -> 001 -> TRUE~111 & 111 -> 000 & 111 -> 000 -> FALSE`
Looks like our general rule seems to hold up. Version A makes less sense than version B, because usually when we do a check against flags, we're concerned about the ones that are set rather than the ones that are clear.

"But what if you wanted to check if all bits of the flag where set, or clear?"

Code: [Select]
`//Checks if all bits set(Viewer_mode & VM_PADLOCK_ANY) == VM_PADLOCK_ANY;// Checks if all bits clear(Viewer_mode & VM_PADLOCK_ANY) == 0;`
« Last Edit: August 17, 2016, 04:11:22 pm by z64555 »
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

#### z64555

• 210
• Self-proclaimed controls expert
##### Re: Tricky Bools!
As MageKing17 on IRC pointed out, it's preferred to do

Code: [Select]
`!(Viewer_mode & VM_PADLOCK_ANY)`
when checking if a single bit is clear. This notation also seems to check if all bits are clear.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

• 211
• The Cthulhu programmer himself!
##### Re: Tricky Bools!
when checking if a single bit is clear.
what

I didn't say that
Ph'nglui mglw'nafh Codethulhu GitHub wgah'nagl fhtagn.

schrĂ¶dinbug (noun) - a bug that manifests itself in running software after a programmer notices that the code should never have worked in the first place.

When you gaze long into BMPMAN, BMPMAN also gazes into you.

"I am one of the best FREDders on Earth" -General Battuta

<Aesaar> literary criticism is vladimir putin

<MageKing17> "There's probably a reason the code is the way it is" is a very dangerous line of thought.
<MageKing17> Because the "reason" often turns out to be "nobody noticed it was wrong".
(the very next day)
<MageKing17> this ****ing code did it to me again
<MageKing17> "That doesn't really make sense to me, but I'll assume it was being done for a reason."
<MageKing17> **** ME
<MageKing17> THE REASON IS PEOPLE ARE STUPID
<MageKing17> ESPECIALLY ME

<MageKing17> God damn, I do not understand how this is breaking.
<MageKing17> Everything points to "this should work fine", and yet it's clearly not working.
<MjnMixael> 2 hours later... "God damn, how did this ever work at all?!"
(...)
<MageKing17> so
<MageKing17> more than two hours
<MageKing17> but once again we have reached the inevitable conclusion
<MageKing17> How did this code ever work in the first place!?

<@The_E> Welcome to OpenGL, where standards compliance is optional, and error reporting inconsistent

<MageKing17> It was all working perfectly until I actually tried it on an actual mission.

<IronWorks> I am useful for FSO stuff again. This is a red-letter day!
* z64555 erases "Thursday" and rewrites it in red ink

<MageKing17> TIL the entire homing code is held up by shoestrings and duct tape, basically.

#### z64555

• 210
• Self-proclaimed controls expert
##### Re: Tricky Bools!
Quote
4:34:08 PM - z64555: checking if a bit is clear. probably will go with !(Viewer_mode & VM_CAMERA_LOCKED)
4:34:21 PM - MageKing17: yes, that's how you should check that
4:34:36 PM - MageKing17: put a "not" in front of a check if a bit is set

Well, that's how I interpreted that.
Secure the Source, Contain the Code, Protect the Project
chief1983

------------
funtapaz: Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Juche.
z64555: s/J/Do
BotenAlfred: <funtapaz> Hunchon University biologists prove mankind is evolving to new, higher form of life, known as Homopithecus Douche.

• 211
• The Cthulhu programmer himself!
##### Re: Tricky Bools!
yes, but the way you wrote it implied that I'd said you should do something else for multiple bits when your question just hadn't been about multiple bits
Ph'nglui mglw'nafh Codethulhu GitHub wgah'nagl fhtagn.

schrĂ¶dinbug (noun) - a bug that manifests itself in running software after a programmer notices that the code should never have worked in the first place.

When you gaze long into BMPMAN, BMPMAN also gazes into you.

"I am one of the best FREDders on Earth" -General Battuta

<Aesaar> literary criticism is vladimir putin

<MageKing17> "There's probably a reason the code is the way it is" is a very dangerous line of thought.
<MageKing17> Because the "reason" often turns out to be "nobody noticed it was wrong".
(the very next day)
<MageKing17> this ****ing code did it to me again
<MageKing17> "That doesn't really make sense to me, but I'll assume it was being done for a reason."
<MageKing17> **** ME
<MageKing17> THE REASON IS PEOPLE ARE STUPID
<MageKing17> ESPECIALLY ME

<MageKing17> God damn, I do not understand how this is breaking.
<MageKing17> Everything points to "this should work fine", and yet it's clearly not working.
<MjnMixael> 2 hours later... "God damn, how did this ever work at all?!"
(...)
<MageKing17> so
<MageKing17> more than two hours
<MageKing17> but once again we have reached the inevitable conclusion
<MageKing17> How did this code ever work in the first place!?

<@The_E> Welcome to OpenGL, where standards compliance is optional, and error reporting inconsistent

<MageKing17> It was all working perfectly until I actually tried it on an actual mission.

<IronWorks> I am useful for FSO stuff again. This is a red-letter day!
* z64555 erases "Thursday" and rewrites it in red ink

<MageKing17> TIL the entire homing code is held up by shoestrings and duct tape, basically.