diff options
author | José Fonseca <[email protected]> | 2014-11-07 21:20:25 +0000 |
---|---|---|
committer | José Fonseca <[email protected]> | 2014-11-08 10:32:39 +0000 |
commit | b238c756da5b8c54437e58c2878ecae7467079eb (patch) | |
tree | 146327aeb91ac81e88e0f06f52e46d77b3026399 | |
parent | d268eac3a9c81febc5efcae7fe6854045bfc5144 (diff) |
util/format: Fix clamping to 32bit integers.
Use clamping constants that guarantee no integer overflows.
As spotted by Chris Forbes.
This causes the code to change as:
- value |= (uint32_t)CLAMP(src[0], 0.0f, 4294967295.0f);
+ value |= (uint32_t)CLAMP(src[0], 0.0f, 4294967040.0f);
- value |= (uint32_t)((int32_t)CLAMP(src[0], -2147483648.0f, 2147483647.0f));
+ value |= (uint32_t)((int32_t)CLAMP(src[0], -2147483648.0f, 2147483520.0f));
Reviewed-by: Roland Scheidegger <[email protected]>
-rw-r--r-- | src/gallium/auxiliary/util/u_format_pack.py | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py index 90f348ea580..d5138cc0577 100644 --- a/src/gallium/auxiliary/util/u_format_pack.py +++ b/src/gallium/auxiliary/util/u_format_pack.py @@ -207,9 +207,36 @@ def get_one_shift(type): assert False +def truncate_mantissa(x, bits): + '''Truncate an integer so it can be represented exactly with a floating + point mantissa''' + + assert isinstance(x, (int, long)) + + s = 1 + if x < 0: + s = -1 + x = -x + + # We can represent integers up to mantissa + 1 bits exactly + mask = (1 << (bits + 1)) - 1 + + # Slide the mask until the MSB matches + shift = 0 + while (x >> shift) & ~mask: + shift += 1 + + x &= mask << shift + x *= s + return x + + def value_to_native(type, value): '''Get the value of unity for this type.''' if type.type == FLOAT: + if type.size <= 32 \ + and isinstance(value, (int, long)): + return truncate_mantissa(value, 23) return value if type.type == FIXED: return int(value * (1 << (type.size/2))) |