diff --git a/src/RageTypes.h b/src/RageTypes.h index ddfc3e88ec..40af928dc3 100644 --- a/src/RageTypes.h +++ b/src/RageTypes.h @@ -265,18 +265,31 @@ public: * incorrect, the first and/or last values may be biased. */ inline unsigned char FTOC(float a) { - /* lfintf is much faster than C casts. We don't care which way negative values - * are rounded, since we'll clamp them to zero below. Be sure to truncate (not - * round) positive values. The highest value that should be converted to 1 is - * roughly (1/256 - 0.00001); if we don't truncate, values up to (1/256 + 0.5) - * will be converted to 1, which is wrong. */ - int ret = lrintf(a*256.f - 0.5f); + //This value is 2^52 * 1.5. + const double INT_MANTISSA = 6755399441055744.0; - /* Benchmarking shows that clamping here, as integers, is much faster than clamping - * before the conversion, as floats. */ - if( ret<0 ) return 0; - else if( ret>255 ) return 255; - else return (unsigned char) ret; + /* Be sure to truncate (not round) positive values. The highest value that + * should be converted to 1 is roughly(1 / 256 - 0.00001); if we don't + * truncate, values up to (1/256 + 0.5) will be converted to 1, which is + * wrong. */ + double base = double(a * 256.f - 0.5f); + + /* INT_MANTISSA is chosen such that, when added to a sufficiently small + * double, the mantissa bits of that double can be reinterpreted as that + * number rounded to an integer. This is done to improve performance. */ + base += INT_MANTISSA; + int ret = reinterpret_cast(base); + + /* Benchmarking shows that clamping here, as integers, is much faster than clamping + * before the conversion, as floats. */ + if (ret < 0) { + return 0; + } + if (ret > 255) { + return 255; + } + + return static_cast(ret); } /* Color type used only in vertex lists. OpenGL expects colors in