if it's a simple case like dealing with a variable in a single function like this, it makes things kinda easier, otherwise i make use of case within records too, everything has its purpose
if it's a simple case like dealing with a variable in a single function like this, it makes things kinda easier, otherwise i make use of case within records too, everything has its purpose
This is my game project - Top Down City:
http://www.pascalgamedevelopment.com...y-Topic-Reboot
My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
http://www.pascalgamedevelopment.com...source+manager
Be wary it doesn't always work. If you have register variables optimization on, the compiler sometimes gets confused.I wasn't aware of the 'absolute' keyword
Example: my attempt to implement Carmack's fast inverse square root.
- it failed craptacularly. The compiler did not give an error but generated totally rubbish code seqence (I turned on ASM output to check).Code:function FastInverseSquareRoot(a: float): float; inline; var i: longint absolute Result; begin Result:= a; i:= $5f3759df - (i shr 1); Result*= 1.5 - (a * 0.5 * Result * Result); Result*= 1.5 - (a * 0.5 * Result * Result); end;
So I had to settle on
P.S. So I'd group absolute together with goto: necessary for backward compatibility but not recommended to use unless you have a very good understanding of processes involved.Code:// https://en.wikipedia.org/wiki/Fast_inverse_square_root function FastInverseSquareRoot(a: float): float; inline; var i: longint;// absolute Result; //code generator FAILS to marry SSE2 and general-purpose registers begin //Result:= a; i:= longint(pointer(@a)^); i:= $5f3759df - (i shr 1); Result:= float(pointer(@i)^); Result*= 1.5 - (a * 0.5 * Result * Result); Result*= 1.5 - (a * 0.5 * Result * Result); end;
Last edited by Chebmaster; 13-03-2018 at 08:28 AM.
I have my own variant of that:
Perhaps not as optimal, but look at how 2 variables are on same absolute variable address, iirc this version works with optimizations on.function NSQRT(X: single): single; {$ifdef fpc} inline; {$endif}
var
XHalf: single;
I: integer Absolute X;
X2: single Absolute I;
XB: single;
begin
XB := X;
XHalf := 0.5 * X;
I := $5f375a86 - (I shr 1);
// ($5f375a86 for best range, $5F375A84 for whole fpu range, 5F3759DF for carmacks range)
X := X2 * (1.5 - XHalf * X2 * X2);
Result := XB * X;
end;
This is my game project - Top Down City:
http://www.pascalgamedevelopment.com...y-Topic-Reboot
My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
http://www.pascalgamedevelopment.com...source+manager
I'd not come across this approximation either - thanks very much for the info both! exactly the kind of esoteric little trick I love to explore
Reading up, it was apparently used before our lord and saviour Carmack did, as was the famous 'Carmack's Reverse' technique for shadow volumes.
But John is a master of applied mathematics in the field of 3D - had he been born 10 years earlier we'd probably of seen Doom on the Amiga at full speed because he found some trick you could pull with the floppy drive
When the moon hits your eye like a big pizza pie - that's an extinction level impact event.
Just don't forget: on modern hardware this vintage method has the same speed(x86) or is three times *slower*(Raspberry Pi) than honest 1/sqrt(x) while the dedicated SSE instruction RSQRTPS leaves it in the dust, being more than 8 times faster (although it is not deterministic) because it does that trick *in hardware* operating on 4 floats in parallel.exactly the kind of esoteric little trick I love to explore
See my research results @ http://openarena.ws/board/index.php?topic=5379.0
So, be wary of stale methodologies and remember: modern hardware demands different optimizations!
This is my game project - Top Down City:
http://www.pascalgamedevelopment.com...y-Topic-Reboot
My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
http://www.pascalgamedevelopment.com...source+manager
Bookmarks