From 773190f2816b77f815b7503ccd984daa81480bec Mon Sep 17 00:00:00 2001 From: Elie Tournier Date: Wed, 9 Aug 2017 14:22:47 +0100 Subject: [PATCH] glsl: Add "built-in" functions to do fp64_to_int(fp64) v2: use mix Signed-off-by: Elie Tournier --- src/compiler/glsl/float64.glsl | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) 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)); +} -- 2.30.2