Aller au contenu

Photo

Neat Little Trick


  • Veuillez vous connecter pour répondre
8 réponses à ce sujet

#1
Tarot Redhand

Tarot Redhand
  • Members
  • 2 693 messages
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

#2
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages
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.

#3
420

420
  • Members
  • 190 messages
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

#4
the.gray.fox

the.gray.fox
  • Members
  • 127 messages
^ 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 .


#5
FunkySwerve

FunkySwerve
  • Members
  • 1 308 messages
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

#6
Tarot Redhand

Tarot Redhand
  • Members
  • 2 693 messages
@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 .


#7
the.gray.fox

the.gray.fox
  • Members
  • 127 messages
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 .


#8
Lightfoot8

Lightfoot8
  • Members
  • 2 535 messages

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.  




                    

#9
the.gray.fox

the.gray.fox
  • Members
  • 127 messages
Oops. I mistyped that 1's complement. Good thing you noticed.

-fox

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