diff options
author | Elie Tournier <[email protected]> | 2017-08-09 14:22:47 +0100 |
---|---|---|
committer | Matt Turner <[email protected]> | 2019-01-09 16:42:40 -0800 |
commit | 773190f2816b77f815b7503ccd984daa81480bec (patch) | |
tree | 84787ac071d89ec316372b550f8ba5d7f9e2d155 /src/compiler | |
parent | cbf090b809bd8e74c0def50551b580585092d664 (diff) |
glsl: Add "built-in" functions to do fp64_to_int(fp64)
v2: use mix
Signed-off-by: Elie Tournier <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/glsl/float64.glsl | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/compiler/glsl/float64.glsl b/src/compiler/glsl/float64.glsl index 232bf18b4d3..72fbefd2eff 100644 --- a/src/compiler/glsl/float64.glsl +++ b/src/compiler/glsl/float64.glsl @@ -880,3 +880,44 @@ __uint_to_fp64(uint a) return __packFloat64(0u, 0x432 - shiftDist, aHigh, aLow); } + +/* Returns the result of converting the double-precision floating-point value + * `a' to the 32-bit two's complement integer format. The conversion is + * performed according to the IEEE Standard for Floating-Point Arithmetic--- + * which means in particular that the conversion is rounded according to the + * current rounding mode. If `a' is a NaN, the largest positive integer is + * returned. Otherwise, if the conversion overflows, the largest integer with + * the same sign as `a' is returned. + */ +int +__fp64_to_int(uint64_t a) +{ + uint aFracLo = __extractFloat64FracLo(a); + uint aFracHi = __extractFloat64FracHi(a); + int aExp = __extractFloat64Exp(a); + uint aSign = __extractFloat64Sign(a); + + uint absZ = 0u; + uint aFracExtra = 0u; + int shiftCount = aExp - 0x413; + + if (0 <= shiftCount) { + if (0x41E < aExp) { + if ((aExp == 0x7FF) && bool(aFracHi | aFracLo)) + aSign = 0u; + return mix(0x7FFFFFFF, 0x80000000, bool(aSign)); + } + __shortShift64Left(aFracHi | 0x00100000u, aFracLo, shiftCount, absZ, aFracExtra); + } else { + if (aExp < 0x3FF) + return 0; + + aFracHi |= 0x00100000u; + aFracExtra = ( aFracHi << (shiftCount & 31)) | aFracLo; + absZ = aFracHi >> (- shiftCount); + } + + int z = mix(int(absZ), -int(absZ), (aSign != 0u)); + int nan = mix(0x7FFFFFFF, 0x80000000, bool(aSign)); + return mix(z, nan, bool(aSign ^ uint(z < 0)) && bool(z)); +} |