Friday, July 9, 2010

Testing for NaN and Infinity values

From my work on pcsx2 I have had to deal extensively with the problem of NaN and Infinity values with floats.

The ps2's FPU and VU processors do not support NaN or Infinity values, so it is a pain to emulate them on a system that does support such values (x86-32/SSE processors).

There are a variety of ways to test for NaN and Infinity values, and I will list a few here.

The first is pretty well known.
If you compare a float for equality against itself, it should return True unless the float is a NaN.
So the typical approach is to do something like:

// Test for NaN
bool isNaN(float x) {
return x != x;
}


That will only test for NaN's, if you want to check for infinities you can do something like this:


#include <limits>
#include <math.h>

// Test for positive or negative infinity values
bool isInf(float x) {
return fabs(x) == numeric_limits<float>::infinity();
}



You can instead use bitwise logic to test for NaN's and Infinities.


// Test for NaN with bitwise logic
bool isNaN(float x) {
return ((int&)x & 0x7fffffff) >= 0x7f800001;
}

// Test for Inf with bitwise logic
bool isInf(float x) {
return ((int&)x & 0x7fffffff) == 0x7f800000;
}


You can even check for both NaN and Infinities with just one comparison:


// Test for NaN or Inf with bitwise logic
bool isNaNorInf(float x) {
return ((int&)x & 0x7fffffff) >= 0x7f800000;
}



Generally you probably don't want to use the bitwise version of these functions for the reason that the compiled code will end up having to switch from FPU to integer arithmetic, which will most likely end up being slower than sticking to the floating point comparisons.

Compare Optimization Tricks

Okay I invented these bitwise tricks myself, so they shouldn't be as well known as the last one I posted; well the first one is more obvious (so probably other people have used it), but the other one not so much.

If you're ever comparing an integer being in the range 0...n, you can normally do this:

// Normal Compare
bool compare(int x) {
return (x >= 0) && (x <= 10)
}


However, you can do that same operation with just one compare instruction:

// Optimized Compare
bool compare(int x) {
return (unsigned int)x <= 10;
}



Now this second trick is if you want to compare 2 different integers, and want to check if they're both in the range 0...2^n

Normally you could do this:

// Normal Compare
bool compare(int x, int y) {
return (x >= 0) && (x <= 16)
&& (y >= 0) && (y <= 16);
}


Using the trick mentioned before, we figured out you can optimize it to this:

// Optimized Compare
bool compare(int x, int y) {
return ((unsigned int)x <= 16)
&& ((unsigned int)y <= 16);
}


But now we can further optimize this to just one single compare!

// Very Optimized Compare!
bool compare(int x, int y) {
return ((unsigned int)(x|y) <= 16);
}


That ends up doing the work of 4 comparisons, with just 1!
(Although you now have the added OR instruction; but OR is very fast to compute on almost every processor).

I want to stress again that the last optimization only works when the value is a power of two (2^n).

Thursday, July 8, 2010

xor swap trick and add/sub swap trick

This is a pretty common bitwise trick most veteran coders know about, but its probably a good bitwise trick to start this section out with.

If you have 2 integers, x and y, you can swap their values normally by doing:

// Normal Swap Function
_f void swap(int& x, int& y) {
    int z = x;
    x = y;
    y = z;
}


But this requires a temporary variable/register to be used (the "int c").

You can do this same functionality without using a temporary variable at all, using the xor swap trick:

// XOR Swap Function
_f void swap(int& x, int& y) {
    assert(&x != &y);
    x ^= y;
    y ^= x;
    x ^= y;
}


The result ends up being the same as the first function, but notice now it doesn't use any temporary variables.
This trick can be useful if you're doing some low-level asm work, or reg-alloc in a recompiler, or for any reason you don't have an extra register to spare and your instruction set doesn't have an xchg opcode. Admittingly, if you're just sticking to c++ code, might just be better to use the normal swap routine instead.

Also beware! This trick has a big problem if &x == &y, that is, if x and y are the same exact variable. In that case instead of keeping the values the same, you end up zeroing out the value!
So the xor swap trick should only be used when you know you are dealing with 2 distinct 'x' and 'y' variables. That is why we put the assert(&x != &y) line in this function, so on debug builds we will get an error if the references of x and y point to the same exact variable.

Lastly I'll point out that you can do the same trick using add and sub operations, but its a bit messier and not as useful:

// Add/Sub Swap Function
_f void swap(int& x, int& y) {
    assert(&x != &y);
    x += y;
    y  = x - y;
    x -= y;
}


The problem with this code is the second instruction.
For many instruction sets (for example SSE, MMX, or x86-32), you're stuck with "dest, src" syntax for instructions.
This means that the compiled code for this will still end up having to use some type of temporary register or the stack to compute this.

If you're dealing with another architecture however that has 3-operand syntax "dest, src1, src2", then this is more useful since you can do the second line with just 1 instruction.

Notes:

I use "_f" as a macro for "__forceinline" so:
// Forceinline Macro for in-lining functions
#define _f __forceinline


Also note that this trick can be extended to be used with floats, doubles, and etc...
But you have to be sure to do the operations as 32bit integers or 64bit integers respectively.

Here's an example of swapping 2 floating point singles with this trick:

// Add/Sub Swap Function
_f void swap(int& x, int& y) {
    assert(&x != &y);
    x ^= y;
    y ^= x;
    x ^= y;
}

// Float Swap Function
_f void swap(float& x, float& y) {
    swap((int&)x, (int&)y);
}


Technically this isn't very useful when sticking with high-level c++, especially since floating point operations are generally compiled to use the x87 fpu (so the floats will be moved back into gprs, and end up being slower than a regular swap); also this will confuse the compiler more so that's another reason it won't generate as good code; but if you're dealing with SSE directly, the xor trick can be useful.

So...

I had an idea.

I was thinking of stuff I should post in this blog and then I came up with the idea of posting random code snippets/tricks that you can do (mostly will be c++/asm stuff).

Hopefully you guys like that idea; its at least its something kind-of fun :D

Tuesday, June 29, 2010

WTF

Woah its been over a year since my last blog update!?
I could have sworn it was only 6 months tops, damn the notion of time slips away when you're a hermit :o

Anyways, I'll probably try and revive this blog somewhat so its not dead :(

Tuesday, June 9, 2009

Man this was good



That's not one of my favorite FFVII songs, but the 'power' of that performance just made it sound awesome.

Saturday, May 2, 2009

I finally passed Discrete Mathematics!

On the final exam that I needed at least a 42 on, I got a 56.
After taking the class 4 times, I'm finally done with it and can forget everything I learned xD

The best part is I can finally take my advanced programming classes (which I couldn't take before because Discrete Math was a prerequisite).

The bad news is, the programming class I wanted to take for next semester was already full when I went to register, so I'll have to wait another semester to take it...


Technically I 'Passed' Discrete Math the second time I took it with a D+, but my university has some policy that I need to get a C or better for it to count...
Anyways, I finally got a C+, so I'm good to go..
(Its also funny how this class totally fucked up my high GPA to an 'average' GPA, and made me lose all my scholarships)

Friday, May 1, 2009

Greatest Man that Ever Lived

Leonardo Da Vinci was a brilliant man.
Probably the greatest man that ever lived.

Wikipedia describes him as "an Italian polymath, being a scientist, mathematician, engineer, inventor, anatomist, painter, sculptor, architect, botanist, musician and writer."

Considering he excelled in all those fields, that's extremely impressive.
He's "god-like" if you will.

I have to say I'm envious.

Friday, April 24, 2009

42

The grade I needed to get on my final exam to pass my Discrete Math class, just so happened to be the answer to the universe... 42.

If I got 42 or higher, then I can pass the class with a 70% C.
(I need a C or higher for it to count as passing)

I've been sick with the flu all week, so I didn't have a chance to study. I really fucking hope I got 42% or higher, I'll probably drop out of my University if I didn't... (I can't stand taking this class a 5th time!)

If I do drop out of Uni, I'll probably join one of those video-game colleges, and get a degree in "game and simulation programming."
The degree doesn't look as good as a "Computer Science" degree, but its better than nothing. And its probably a lot funner to achieve.
Also, my grades would be a lot higher if most my classes were about programing games (I think I've mentioned in a previous post, that I'm only good at stuff I enjoy).

Friday, April 10, 2009

Awesome Megaman Rap Video

One of my favorite video game series is the Megaman series.
A friend at work recommended me to watch this cool video on youtube:



I'm not too into rap music, but this song was pretty good.
Its got some awesome lines:
Heatman: "I got a face for radio and a box for a suit"
Megaman "Capcom really didn't spend much time on you..."

Windman and Airman's raps are my favorites, but they're all cool.
Any megaman fan should watch the video xD

Wednesday, April 8, 2009

Sleep is a double-edged sword.

Sleep is pretty awesome, it helps rest your mind and helps improve memory and all that good stuff.

But sadly sleep has its negatives, the main one being it takes away a lot of free time.
Or it can make you not want to wake-up, and you'll be late for work or school (happens to me every day xD)
Another problem is if you want to do something, but can't because you're too tired and need to sleep. Or if you just can't think straight because of lack of sleep.

So I've often pondered if life would be better without sleep.
The main problem that arises with this is that, if people didn't sleep, then work and school would most-likely be a lot longer. And that doesn't sound like a good thing xD

A compromise would be if the world rotated slower, and a day would be something like 27 hours instead of 24 hours.
This would allow for 3 more hours of sleep a day, and most people with busy lives would probably benefit from this.

Of course that also has negatives as well. For instance, if you're waiting for a certain day to happen, you'll have to wait longer. In fancy math terms the extra time you'd have to wait is (3 * n) hours longer where n is the number of days.

Furthermore, if you're having a bad day, and want the day to end, you'll have to endure that bad day for another 3 hours =D.


So really, I'm not sure what could be done to solve the problems of sleep. All options seem to have their ups and downs.... but that seems to be the case with most things in 'life'.

Saturday, March 28, 2009

Earth Day?

http://www.google.com/intl/en/earthhour/2009/

Heh this is pretty funny, they want us to turn off our lights for an hour? What for?

I'm all for cleaner sources of energy and a cleaner planet earth, however we need new technology that's more efficient, we shouldn't have to use technology less just because its inefficient.

Probably ~40% of the energy in the things we use daily is wasted due to inefficient technology (just my guess).

PSU's iirc are at-most like 80% efficient, and standard lightbulbs waste like 50% of their energy as heat (i've totally forgotten the exact statistics of these things, so they might be off).

But the point is, we don't need to use technology less to conserve energy, we need to make technology better!

Wednesday, March 25, 2009

Discrete Mathematics Sucks

I've taken Discrete Mathematics 3 times, and I'm on my 4th try ><
I feel pretty retarded taking the same class 4 times, and it especially hurts when I see people that are dumber than me passing the class :/

I'm one of those people that are only good at stuff they enjoy. If I don't enjoy doing something, or if I see no real-benefit from it, I won't apply myself and just half-ass it (or in the case of discrete math, just procrastinate and not study till the-day-of the test :o)

The class is basically a bunch of different advanced math courses/theories combined into 1 class. It needed for all Computer Science majors at my school, so it *should* have something to do with computers, but it really doesn't :/

Seriously, I spend most my days programming shit, and I really don't see much practical use for discrete mathematics. There may be some cases where you can use graph theory to help with stuff like shortest path algorithms, but there's a big difference between programming 'graph theory', and math graph theory.

Basically 'graph theory' or any other aspect of discrete mathematics to a mathematician is all about proving or showing something is true for all possible cases, regardless of the practicallity of actually implementing the algorithm. To a programmer its just "does this work good enough for what I need, and is it fast?"... See the difference? :p

Now, what good is an algorithm if its not practical to actually use? Or if you'll never use it? I love programming because I can create and view my creation. With mathematics you theorize and.... wait I guess that's it!? oO

Its funny, because back in high school I took Honors and Advanced Placement math courses, and got very good grades. I used to think math was pretty fun and easy... but then when I got to college I realized that the math in high school was "bullshit fake math."

College math was a punch in the face, I actually had to study!? wtf! The bullshit fake high school math courses only 'taught' me that I didn't have to study for math courses because they were easy... I got pretty pissed when I learned what 'real math' was after taking some university math classes :/

Anyways, the point of this blog-post is:
1) Discrete Mathematics is pretty useless, and shouldn't be mandatory for Computer Science Majors.
2) High School mathematics 'prepares' you badly for college-level math, by giving you false expectations that it will be easy.

Monday, March 23, 2009

Hmm

I realized that the default option for comments is that you need an account to leave them. So I just changed it so that anyone can leave a comment, and I also disabled the word verification since those things are so annoying!

The worst part about word verification is that the text they make you type in is usually sooo warped that it takes a couple tries to type in the correct word ><

Programming != Math

There's a big misconception a lot of people have where they think in order to be a programmer, you have to be excellent at math or be a mathematician. This is absolutely false for most types of programming, or at least very misleading.

Rather than saying you have to be good at math, its more correct to say you have to be good at thinking logically or procedurally. When you program you have to think about the goal you want to accomplish within the program you're writing, and then think of the step-by-step way to achieve that goal using the 'instructions' made accessible to you by the programming language.

But notice that 'thinking logically' and 'mathematics' aren't the same thing. Of course being good at math is definitely a benefit to programming; if you know certain mathematical rules you might be able to simplify or optimize parts of your program, but its not a necessity for most types of programming.

Now there are some fields of programming where math is more crucially used, a 3d game programmer for instance is going to use more math than a programmer developing a word processor. But if you take all the types of programmers in the world, most programmers rarely have need for any advanced-math in their applications.

Personally I believe programming is more practical than mathematics anyways. Programmers create things that are useful to people, whereas mathematicians come up with theories that 95% of the time don't have any practical value.

I always wonder why people want to be mathematicians, what the hell are they going to do with that mathematical knowledge? I guess that's why most of them just go on to be professors or teachers, since they can't find a real job that practically applies that knowledge :p

So bottom line is:
1) You don't have to be a mathematician to be a programmer.
2) Knowledge is useless if its not put to a practical use.