Author Topic: Neat Little Trick  (Read 676 times)

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
Neat Little Trick
« on: January 05, 2011, 11:00:25 am »


               I don't know how relevant it is to nwn, but here is a neat little 'trick' that I thought I'd share.  It's just a very small function. So what does it do? It swaps the values held in 2 integer variables without the need for a local variable. Due to the way it works, this method cannot be used with variables of other types.

void SwapInts(int a, int 'B)'
{
a ^= b;
b ^= a;
a ^= b;
}

Because there are no local variables it is slightly more efficient than 'normal' methods. Anyway, I hope someone has a use for it.

TR
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Neat Little Trick
« Reply #1 on: January 05, 2011, 12:56:41 pm »


               Neet little function.  The logic is correct, you just have one little problem, At least with the nwn compiler.   The problem is that NWN passes all interger arguments by value.  In order to be able to get your arguments back out to the main body of the code you would have to be able to pass your arguments by refferance.



You could of cource not pass any arguments and just use a couple global ints.  But at that point it would be simpler to just enter your code into the main body of the code and not use it as a function.
               
               

               
            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Neat Little Trick
« Reply #2 on: January 05, 2011, 06:31:31 pm »


               I'm confused, what does the ^= operator do exactly?

Also, if you wanted to return multiple variables from a function you could use a struct.

-420
               
               

               
            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Neat Little Trick
« Reply #3 on: January 05, 2011, 06:36:01 pm »


               ^ is the XOR (eXclusive OR) operator.
It is a bitwise operator (works on bits).
Its truth table is as follow:

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0


[edit]
The trick is well known to programmers. However, swapping two variables like that is still slower than using a temporary storage variable.

By the way:
the above code can be inlined as: a ^= b ^= a ^= b;
thus producing less instructions once compiled.

-fox
               
               

               


                     Modifié par the.gray.fox, 05 janvier 2011 - 06:39 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Neat Little Trick
« Reply #4 on: January 05, 2011, 08:46:33 pm »


               This trick was in the intro C programming book I picked up when teaching myself C. Like fox says, though, I'm not sure it has much application in nwn. I haven't profilied it, and bitwise ops are fast enough that we use them for a number of things, but any time saving would be negligible. I think this trick is used more often when memory is at a premium.



Funky
               
               

               
            

Legacy_Tarot Redhand

  • Hero Member
  • *****
  • Posts: 4165
  • Karma: +0/-0
Neat Little Trick
« Reply #5 on: January 05, 2011, 10:31:58 pm »


               @Lightfoot8 - My bad. I should have realised that because in c (which nwn script appears to be based upon) you have to pass a pointer to a variable. Still the body is small enough to be used in place of a function call.

@the.gray.fox - I just double checked my copy of the lexicon and I can find no mention of that type of inline assignment. As far as efficiency goes it depends on the code produced by the nwn compiler.

The thing is I know how it works, I can just about understand why it works and yet it still seems almost like magic to me.':wizard:'

TR
               
               

               


                     Modifié par Tarot Redhand, 05 janvier 2011 - 10:32 .
                     
                  


            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Neat Little Trick
« Reply #6 on: January 11, 2011, 02:44:47 pm »


               Sorry for the late reply. I was away.
At any rate you have posted a bit of useful knowledge.
Knowledge that many ignore, and that many others once knew but have forgot.

Allow me to contribute to your thread.
Another nice trick:


int GetIsPow2 (int nValue)
{
    return (nValue & -nValue == nValue);
}

This returns false if the number is not a power of 2.
It will return true if the number is a power of 2.
Be sure to feed to the function only a positive integer (nwscript has no meaning of "unsigned", so the function may not be secured in that sense -- assuming you do not want to introduce a call to abs() ).

The trick is simple. An integer number is a power of 2 if 1 and only 1 bit of it is set.
Two examples:

--------------------
With nValue=8

Bit pattern of +8 is: 00001000
Bit pattern of -8 is: 11111110

AND-ing them produces 00001000.
The comparison between 00001000 and 00001000 produces TRUE.
In fact 8 is a power of 2.

--------------------
With nValue=250

Bit pattern of +250 is: 11111010
Bit pattern of -250 is: 00000110

AND-ing them produces 00000010.
The comparison between 11111010 and 00000010 produces FALSE.
In fact 250 is not a power of 2.

-fox
               
               

               


                     Modifié par the.gray.fox, 11 janvier 2011 - 02:51 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Neat Little Trick
« Reply #7 on: January 11, 2011, 05:38:14 pm »


               

the.gray.fox wrote...


int GetIsPow2 (int nValue)
{
    return (nValue & -nValue == nValue);
}


--------------------
With nValue=8

Bit pattern of +8 is: 00001000
Bit pattern of -8 is: 11111110


-fox


For any one trying to figure out how this works It my help to know that the bit pattern for -8 is not 1111 1110.
It is in fact  1111 1000

To make any number negtive you take the bitwize not of the number then add 1
so the bit pattern for 8 is 0000 1000
~8    =  1111 0111 ( '~' is the symbole for the bitwize not.
~8+1 = 1111 1000
~8+1 & 8 = 0000 1000

If you follow the patern here what is being returned by the (nValue & -nValue ) is the value the lowers bit set in the number.   this tell you the greatest power of two that the number can be evenly devided by.  




                    
               
               

               
            

Legacy_the.gray.fox

  • Full Member
  • ***
  • Posts: 214
  • Karma: +0/-0
Neat Little Trick
« Reply #8 on: January 12, 2011, 02:14:15 pm »


               Oops. I mistyped that 1's complement. Good thing you noticed.

-fox
               
               

               


                     Modifié par the.gray.fox, 12 janvier 2011 - 02:15 .