----- Original Message -----
From: "Ross Bencina" <rossb@audiomulch.com>
To: "Robin Davies" <rerdavies@msn.com>; "Saol-dev" <saol-dev@media.mit.edu>
Sent: Tuesday, September 05, 2000 4:41 AM
Subject: Re: definition of t in comb and allpass
> Robin Davies <rerdavies@msn.com> wrote:
> >Floor is a very expensive operation on intel processors as it requires
> >reloading of the Floating Point Status word, which, among other things
> >creates horrendous stalls, and incurs a very heavy execution penalty.
>
> This is not strictly true. Floor (and assigning a float to an int for that
> matter) is expensive _in C_ on Intel processors because the C language
> specification requires specific rounding behaviour, and the compiler
cannot
> guarantee this without explicitly setting/resetting the fpu status word in
> such situations, which as you say _is_ very expensive.
This isn't quite true. Direct compilers will experience the same problem
(actually slightly worse, but rounding is even faster if you can use the
FISTP instruction directly).
The same bits within the machine status word on the Intel FPUs control
rounding behaviour for both general floating point operations, and
float-to-integer conversions. So, unless you are always going to run with
floating-point operations that round downward always (which you should not),
you are still going to have to reload the machine status word twice to
perform a floor operation, even if you are generating pure assembler output.
In C, there is actually an intel-advocated hack that will round integers
quickly and efficiently (although not *quite* as efficiently as an FISTP
instruction). This technique does actually work on most processors that have
IEEE-conformant floating point as well, although the magic constant would
have to be derived from constants in FLOAT.H to work. The rand48 function in
linux provides a demonstration of a very similar technique (including
correct derivation from the float.h constants) that runs successfully on a
wide variety of processors.
inline int Round(double val) {
double v;
// Place the result in the low 16 bits
// of the double value.
v = val + MagicConstant;
// Take the low 16 bits out of the
// IEEE floating point storage.
return *(int*)&v;
}
I can't quite remember the exact magic constant. Roughly, I think it's 2^51
+ 2^52 or thereabouts (give or take a power of two).
This archive was generated by hypermail 2b29 : Mon Jan 28 2002 - 12:03:58 EST