From dc00b4dd64389a2e82bf9e6bb3482e61264bc47b Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskij Date: Thu, 6 Mar 2014 21:10:08 +0400 Subject: [PATCH] Undefined operation -INT64_MIN was fixed. --- docs/ispc.rst | 8 +++----- stdlib.ispc | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/docs/ispc.rst b/docs/ispc.rst index 18663942..4819ee9c 100644 --- a/docs/ispc.rst +++ b/docs/ispc.rst @@ -3617,8 +3617,8 @@ normalized exponent as a power of two in the ``pw2`` parameter. Saturating Arithmetic --------------------- -A saturation addition, substraction, multiplication and division of all integer -types is provided by the ``ispc`` standard library. +A saturation (no overflow possible) addition, substraction, multiplication and +division of all integer types is provided by the ``ispc`` standard library. :: @@ -3645,9 +3645,7 @@ types is provided by the ``ispc`` standard library. In addition to the ``int8`` variants of saturating arithmetic functions listed above, there are versions that supports ``int16``, ``int32`` and ``int64`` -values as well. Functions that have best high-speed performance are functions -that support ``varying signed/unsined int8/int16`` on IntelĀ® SSE and IntelĀ® AVX, -because they have hardware implementation. +values as well. Pseudo-Random Numbers diff --git a/stdlib.ispc b/stdlib.ispc index d60219d0..a2ca02e7 100644 --- a/stdlib.ispc +++ b/stdlib.ispc @@ -4943,8 +4943,20 @@ static inline uniform int64 saturating_mul(uniform int64 a, uniform int64 b) { uniform unsigned int64 ret = 0; uniform int8 sign = (((a > 0) && (b > 0)) || ((a < 0) && (b < 0))) ? 1 : -1; - uniform unsigned int64 a_abs = (a > 0) ? a : -a; - uniform unsigned int64 b_abs = (b > 0) ? b : -b; + uniform unsigned int64 a_abs = 0; + uniform unsigned int64 b_abs = 0; + + if (a == INT64_MIN) + a_abs = (uniform unsigned int64) INT64_MIN; + // Operation "-" is undefined for "INT64_MIN". + //See 6.3.1.3 section in C99 standart. + else + a_abs = (a > 0) ? a : -a; + + if (b == INT64_MIN) + b_abs = (uniform unsigned int64) INT64_MIN; + else + b_abs = (b > 0) ? b : -b; uniform unsigned int32 a0 = a_abs & 0xFFFFFFFF; uniform unsigned int32 b0 = b_abs & 0xFFFFFFFF; @@ -4969,7 +4981,7 @@ static inline uniform int64 saturating_mul(uniform int64 a, uniform int64 b) { } - if ((sign < 0) && (ret >= -INT64_MIN)) { + if ((sign < 0) && (ret >= (uniform unsigned int64) INT64_MIN)) { return INT64_MIN; } else if ((sign > 0) && (ret >= INT64_MAX)) { return INT64_MAX; @@ -4981,9 +4993,22 @@ static inline uniform int64 saturating_mul(uniform int64 a, uniform int64 b) { static inline varying int64 saturating_mul(varying int64 a, varying int64 b) { varying unsigned int64 ret = 0; - varying int8 sign = (((a > 0) && (b > 0)) || ((a < 0) && (b < 0))) ? 1 : -1; - varying unsigned int64 a_abs = (a > 0) ? a : -a; - varying unsigned int64 b_abs = (b > 0) ? b : -b; + varying int8 sign = (((a > 0) && (b > 0)) || ((a < 0) && (b < 0))) ? 1 : -1; + varying unsigned int64 a_abs = 0; + varying unsigned int64 b_abs = 0; + + if (a == INT64_MIN) + a_abs = (varying unsigned int64) INT64_MIN; + // Operation "-" is undefined for "INT64_MIN". + //See 6.3.1.3 section in C99 standart. + else + a_abs = (a > 0) ? a : -a; + + if (b == INT64_MIN) + b_abs = (varying unsigned int64) INT64_MIN; + else + b_abs = (b > 0) ? b : -b; + varying unsigned int32 a0 = a_abs & 0xFFFFFFFF; varying unsigned int32 b0 = b_abs & 0xFFFFFFFF; @@ -5008,7 +5033,7 @@ static inline varying int64 saturating_mul(varying int64 a, varying int64 b) { } - if ((sign < 0) && (ret >= -INT64_MIN)) { + if ((sign < 0) && (ret >= (varying unsigned int64) INT64_MIN)) { return INT64_MIN; } else if ((sign > 0) && (ret >= INT64_MAX)) { return INT64_MAX;