Fix overflow issues when converting float to int
32-bit floats can only reach between -16777215...+16777215 (25 bits) before it starts losing whole-number accuracy. Some compiler optimizations may break trying to multiply a float by 2147483647.0 when the result is given right to a float parameter, causing it instead to multiply by the nearest representable float value, 2147483648.0.
This commit is contained in:
@@ -912,24 +912,27 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
|
||||
}
|
||||
|
||||
|
||||
static __inline ALfloat aluF2F(ALfloat val)
|
||||
{ return val; }
|
||||
static __inline ALint aluF2I(ALfloat val)
|
||||
static __inline ALint aluF2I25(ALfloat val)
|
||||
{
|
||||
/* Clamp the value between -1 and +1. This handles that with only a single branch. */
|
||||
if(fabsf(val) > 1.0f)
|
||||
val = (ALfloat)((0.0f < val) - (val < 0.0f));
|
||||
/* Convert to a signed integer, between -2147483647 and +2147483647. */
|
||||
return fastf2i((ALfloat)(val*2147483647.0));
|
||||
/* Convert to a signed integer, between -16777215 and +16777215. */
|
||||
return fastf2i(val*16777215.0f);
|
||||
}
|
||||
|
||||
static __inline ALfloat aluF2F(ALfloat val)
|
||||
{ return val; }
|
||||
static __inline ALint aluF2I(ALfloat val)
|
||||
{ return aluF2I25(val)<<7; }
|
||||
static __inline ALuint aluF2UI(ALfloat val)
|
||||
{ return aluF2I(val)+2147483648u; }
|
||||
static __inline ALshort aluF2S(ALfloat val)
|
||||
{ return aluF2I(val)>>16; }
|
||||
{ return aluF2I25(val)>>9; }
|
||||
static __inline ALushort aluF2US(ALfloat val)
|
||||
{ return aluF2S(val)+32768; }
|
||||
static __inline ALbyte aluF2B(ALfloat val)
|
||||
{ return aluF2I(val)>>24; }
|
||||
{ return aluF2I25(val)>>17; }
|
||||
static __inline ALubyte aluF2UB(ALfloat val)
|
||||
{ return aluF2B(val)+128; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user