From af836cda27f38010333454b023f838de37c610fd Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskij Date: Sun, 23 Feb 2014 19:48:03 +0400 Subject: [PATCH] Saturating multiplication for int64 was added. --- stdlib.ispc | 36 ++++++++++++++++++++++++++++++++++++ tests/pmuls_i64.ispc | 28 ++++++++++++++++++++++++++++ tests/pmuls_vi64.ispc | 28 ++++++++++++++++++++++++++++ tests/pmulus_i64.ispc | 28 ++++++++++++++++++++++++++++ tests/pmulus_vi64.ispc | 28 ++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 tests/pmuls_i64.ispc create mode 100644 tests/pmuls_vi64.ispc create mode 100644 tests/pmulus_i64.ispc create mode 100644 tests/pmulus_vi64.ispc diff --git a/stdlib.ispc b/stdlib.ispc index 1582a04a..28dd8970 100644 --- a/stdlib.ispc +++ b/stdlib.ispc @@ -4885,6 +4885,28 @@ static inline varying int32 saturating_mul(varying int32 a, varying int32 b) { return result; } +static inline uniform int64 saturating_mul(uniform int64 a, uniform int64 b) { + uniform int64 a_abs = (a > 0) ? a : -a; + uniform int64 b_abs = (b > 0) ? b : -b; + if (a_abs > (INT64_MAX / b_abs)) + if (((a > 0) && (b > 0)) || ((a < 0) && (b < 0))) + return INT64_MAX; + else + return INT64_MIN; + return a * b; +} + +static inline varying int64 saturating_mul(varying int64 a, varying int64 b) { + varying int64 a_abs = (a > 0) ? a : -a; + varying int64 b_abs = (b > 0) ? b : -b; + if (a_abs > (INT64_MAX / b_abs)) + if (((a > 0) && (b > 0)) || ((a < 0) && (b < 0))) + return INT64_MAX; + else + return INT64_MIN; + return a * b; +} + static inline uniform unsigned int8 saturating_mul(uniform unsigned int8 a, uniform unsigned int8 b) { uniform unsigned int16 result = (uniform unsigned int16) a * @@ -4938,6 +4960,20 @@ static inline varying unsigned int32 saturating_mul(varying unsigned int32 a, varying unsigned int32 lo = result; return lo | - (varying int32) !! hi; } + +static inline uniform unsigned int64 saturating_mul(uniform unsigned int64 a, + uniform unsigned int64 b) { + if (a > (UINT64_MAX / b)) + return UINT64_MAX; + return a * b; +} + +static inline varying unsigned int64 saturating_mul(varying unsigned int64 a, + varying unsigned int64 b) { + if (a > (UINT64_MAX / b)) + return UINT64_MAX; + return a * b; +} /////////////////////////////////////////////////////////////////////////// // rdrand diff --git a/tests/pmuls_i64.ispc b/tests/pmuls_i64.ispc new file mode 100644 index 00000000..a04ca698 --- /dev/null +++ b/tests/pmuls_i64.ispc @@ -0,0 +1,28 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform int64 a_max = 0x7FFFFFFFFFFFFFFF, a_min = -0x8000000000000000; // max and min signed int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_mul(a_max, (uniform int64) b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_mul(a_min, (uniform int64) b); + } + else { + RET[programIndex] = saturating_mul((uniform int64) b, + (uniform int64) b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform int64) 0x7FFFFFFFFFFFFFFF; // max signed int64 + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform int64) -0x8000000000000000; // min signed int64 + } + else { + RET[programIndex] = (uniform int64) 25; + } +} diff --git a/tests/pmuls_vi64.ispc b/tests/pmuls_vi64.ispc new file mode 100644 index 00000000..32df2fac --- /dev/null +++ b/tests/pmuls_vi64.ispc @@ -0,0 +1,28 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying int64 a_max = 0x7FFFFFFFFFFFFFFF, a_min = -0x8000000000000000; // max and min signed int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_mul(a_max, (varying int64) b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_mul(a_min, (varying int64) b); + } + else { + RET[programIndex] = saturating_mul((varying int64) b, + (varying int64) b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying int64) 0x7FFFFFFFFFFFFFFF; // max signed int64 + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying int64) -0x8000000000000000; // min signed int64 + } + else { + RET[programIndex] = (varying int64) 25; + } +} diff --git a/tests/pmulus_i64.ispc b/tests/pmulus_i64.ispc new file mode 100644 index 00000000..179902a3 --- /dev/null +++ b/tests/pmulus_i64.ispc @@ -0,0 +1,28 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform unsigned int64 a_max = 0xFFFFFFFFFFFFFFFF, a_min = 0; // max and min unsigned int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_mul(a_max, (uniform unsigned int64) b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_mul(a_min, (uniform unsigned int64) -b); + } + else { + RET[programIndex] = saturating_mul((uniform unsigned int64) b, + (uniform unsigned int64) b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform unsigned int64) 0xFFFFFFFFFFFFFFFF; // max unsigned int64 + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform unsigned int64) 0; // min unsigned int64 + } + else { + RET[programIndex] = (uniform unsigned int64) 25; + } +} diff --git a/tests/pmulus_vi64.ispc b/tests/pmulus_vi64.ispc new file mode 100644 index 00000000..43ae9aac --- /dev/null +++ b/tests/pmulus_vi64.ispc @@ -0,0 +1,28 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying unsigned int64 a_max = 0xFFFFFFFFFFFFFFFF, a_min = 0; // max and min unsigned int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_mul(a_max, (varying unsigned int64) b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_mul(a_min, (varying unsigned int64) -b); + } + else { + RET[programIndex] = saturating_mul((varying unsigned int64) b, + (varying unsigned int64) b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying unsigned int64) 0xFFFFFFFFFFFFFFFF; // max unsigned int64 + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying unsigned int64) 0; // min unsigned int64 + } + else { + RET[programIndex] = (varying unsigned int64) 25; + } +}