PCSX2 Documentation/What's clamping? And why do we need it?: Difference between revisions
PCSX2 Documentation/What's clamping? And why do we need it? (view source)
Revision as of 18:53, 19 July 2015
, 19 July 2015no edit summary
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
''Originally written by cottonvibes'' | ''Originally written by cottonvibes'' | ||
Line 8: | Line 7: | ||
Basically there's something called the "The IEEE Standard for Floating-Point Arithmetic" (or IEEE 754), which defines floating point representation; and most systems abide by those rules (of course not our wonderful PS2). | Basically there's something called the "The IEEE Standard for Floating-Point Arithmetic" (or IEEE 754), which defines floating point representation; and most systems abide by those rules (of course not our wonderful PS2). | ||
There's 32-bit "Single Precision Floats" (commonly referred to as 'float'), 64-bit "Double Precision Floats" (commonly referred to as 'double'), and there's even 128-bit floats called Quads (most processors don't support these natively). | There's 32-bit "Single Precision Floats" (commonly referred to as 'float'), 64-bit "Double Precision Floats" (commonly referred to as 'double'), and there's even 128-bit floats called Quads (most processors don't support these natively). | ||
Line 14: | Line 12: | ||
The one we're concerned about is the Single Precision Float, which is 32bits and has a format like this | The one we're concerned about is the Single Precision Float, which is 32bits and has a format like this | ||
S x 1bit | E x 8bits | M x 23bits | <code>S x 1bit | E x 8bits | M x 23bits</code> | ||
S = Sign Bit (0 = Positive Number; 1 = Negative Number) | S = Sign Bit (0 = Positive Number; 1 = Negative Number) | ||
Line 34: | Line 32: | ||
Example: | Example: | ||
<source lang="text"> | |||
NaN + 500 = NaN (generally the same NaN, since it propagates) | NaN + 500 = NaN (generally the same NaN, since it propagates) | ||
INF - 19999999999 = INF | INF - 19999999999 = INF | ||
</source> | |||
This is how the IEEE 754 standard defined this stuff (I honestly don't like it, but w/e) | This is how the IEEE 754 standard defined this stuff (I honestly don't like it, but w/e) | ||
Line 44: | Line 44: | ||
For comparison of what your x86-32 CPU does VS the ps2 we have: | For comparison of what your x86-32 CPU does VS the ps2 we have: | ||
Your PC: | '''Your PC:''' | ||
<source lang="cpp"> | |||
1/0 = NaN | 1/0 = NaN | ||
sqrt (-4) = NaN | sqrt (-4) = NaN | ||
INF - 1000 = INF | INF - 1000 = INF | ||
</source> | |||
The PS2: | '''The PS2:''' | ||
<source lang="cpp"> | |||
1/0 = Greatest Positive Float Number (0x7ffffffff) | 1/0 = Greatest Positive Float Number (0x7ffffffff) | ||
sqrt (-4) = sqrt(abs(-4)) = 2 | sqrt (-4) = sqrt(abs(-4)) = 2 | ||
INF - 1000 = Some Large Value - 100 | INF - 1000 = Some Large Value - 100 | ||
</source> | |||
And there's many more combinations, but the point is that the results are not the same between PC and the PS2. | And there's many more combinations, but the point is that the results are not the same between PC and the PS2. | ||
Line 68: | Line 72: | ||
Let me give you a quick example of something clamping can solve: | Let me give you a quick example of something clamping can solve: | ||
<source lang="cpp"> | |||
int main() { | int main() { | ||
float value = INF; | float value = INF; | ||
Line 75: | Line 79: | ||
if (value <= 1) { print("Hello World"); break; } | if (value <= 1) { print("Hello World"); break; } | ||
} while (true); | } while (true); | ||
}</ | } | ||
</source> | |||
If the above code was ran on the ps2, it will eventually print "Hello World", because INF is treated as a regular large number, and will continue to be divided by 2 until its less than 1. | If the above code was ran on the ps2, it will eventually print "Hello World", because INF is treated as a regular large number, and will continue to be divided by 2 until its less than 1. | ||
Line 84: | Line 89: | ||
Clamping can solve this problem like this: | Clamping can solve this problem like this: | ||
<source lang="cpp"> | |||
int main() { | int main() { | ||
float value = INF; | float value = INF; | ||
Line 92: | Line 97: | ||
if (value <= 1) { print("Hello World"); break; } | if (value <= 1) { print("Hello World"); break; } | ||
} while (true); | } while (true); | ||
}</ | } | ||
</source> | |||
The clamping will convert the INF into a normal (ordered) number. Then that normal number can be divided by 2 repetitively until its less than 1. Then it will eventually satisfy (value less or equal 1), and print "Hello World". | The clamping will convert the INF into a normal (ordered) number. Then that normal number can be divided by 2 repetitively until its less than 1. Then it will eventually satisfy (value less or equal 1), and print "Hello World". | ||
Line 103: | Line 109: | ||
Also clamping is SLOW if done a lot, so different clamp modes are faster than others ('None' is the fastest of course Razz) | Also clamping is SLOW if done a lot, so different clamp modes are faster than others ('None' is the fastest of course Razz) | ||
I also should mention that in earlier examples i said: | |||
<source lang="cpp"> | |||
sqrt(-4) = NaN; // on your PC | sqrt(-4) = NaN; // on your PC | ||
sqrt(-4) = 2; // on the ps2 | sqrt(-4) = 2; // on the ps2 | ||
</source> | |||
In this case, we simulate the ps2's sqrt instruction by doing this | In this case, we simulate the ps2's sqrt instruction by doing this | ||
<source lang="cpp"> | |||
float ps2_sqrt(float value) { | float ps2_sqrt(float value) { | ||
value = clamp(value); // Clamp Value if NaN or Inf to an ordered/normal number | value = clamp(value); // Clamp Value if NaN or Inf to an ordered/normal number | ||
Line 116: | Line 124: | ||
value = sqrt(value); // Get sqrt of now-positive value | value = sqrt(value); // Get sqrt of now-positive value | ||
return value; | return value; | ||
}</ | } | ||
</source> | |||
so: | so: | ||
<source lang="cpp"> | |||
ps2_sqrt(-4) = 2; | ps2_sqrt(-4) = 2; | ||
</source> | |||
Now this post is getting really large, and I tried to simplify things a lot (which may have made things more confusing). | Now this post is getting really large, and I tried to simplify things a lot (which may have made things more confusing). | ||
Anyways I hope some of this info was useful/interesting | Anyways I hope some of this info was useful/interesting | ||
{{PCSX2 Developers Blog Navbox}} | {{PCSX2 Developers Blog Navbox}} |