summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2014-11-07 21:20:25 +0000
committerJosé Fonseca <[email protected]>2014-11-08 10:32:39 +0000
commitb238c756da5b8c54437e58c2878ecae7467079eb (patch)
tree146327aeb91ac81e88e0f06f52e46d77b3026399
parentd268eac3a9c81febc5efcae7fe6854045bfc5144 (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.py27
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)))