Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {
- // Branch-less SSE-less Flush-Denormals/NaNs/INFs-to-Zero
- // By Benjamin 'BeRo' Rosseaux - benjamin[at]rosseaux[dot]com
- ///////////////////////////////////////////
- // ObjectPascal data types for C/C++lers //
- ///////////////////////////////////////////
- // //
- // longword=32-bit unsigned int //
- // longint=32-bit signed int //
- // single=32-bit float //
- // //
- ///////////////////////////////////////////
- How the trick does work:
- }
- // The exponent of a float is 8-bit width (the 9-bit would be the sign bit). So:
- var Value:single;
- Exponent:longword;
- longword(Exponent):=(longword(pointer(@Value)^) shr 23) and $ff;
- // longword(Exponent) is now 0 for Denormals and 255 for NaNs/INFs and 1-254 for all other values, so:
- longword(Exponent):=(longword(Exponent)+1) and $ff;
- // longword(Exponent) is now 1 for Denormals and 0 for NaNs/INFs and 2-255 for all other values, so:
- longword(Exponent):=longword(Exponent)-2;
- // longint(Exponent) is now -2 for Denormals and -1 for NaNs/INFs and 0-253 for all other values, so
- // extract the sign bit:
- longword(Exponent):=longword(Exponent) shr 31;
- // longint(Exponent) is now 1 for Denormals and 1 for NaNs/INFs and 0 for all other values, so:
- longword(Exponent):=$ffffffff+longword(Exponent);
- // longint(Exponent) is now 0 for Denormals and 0 for NaNs/INFs and $ffffffff for all other other, so
- // apply it simply as bitwise-and-mask to the float value:
- longword(pointer(@Value)^):=longword(pointer(@Value)^) and longword(Exponent);
- // Optimized without the bloated shift-right-by-23-stuff etc. the code will get it so:
- longword(pointer(@Value)^):=longword(pointer(@Value)^) and longword($ffffffff+longword(((((longword(pointer(@Value)^) and $7f800000)+$800000) and $7f800000)-$1000000) shr 31));
- // or as x86-ASM code:
- asm
- mov eax,dword ptr Value
- and eax,$7f800000
- add eax,$00800000
- and eax,$7f800000
- sub eax,$01000000
- shr eax,31
- dec eax
- and dword ptr Value,eax
- end;
- // or as handly drop-in ready-to-use function: (define caninline, if you do use FreePascal or a Delphi version, which supports function-inlining)
- function KillDenormal(const Value:single):single; {$ifdef caninline}inline;{$endif}
- begin
- // Branch-less SSE-less Flush-Denormals/NaNs/INFs-to-Zero function
- // By Benjamin 'BeRo' Rosseaux - benjamin[at]rosseaux[dot]com
- longword(pointer(@result)^):=longword(pointer(@Value)^) and longword($ffffffff+longword(((((longword(pointer(@Value)^) and $7f800000)+$800000) and $7f800000)-$1000000) shr 31));
- end;
Advertisement
Add Comment
Please, Sign In to add comment