diff --git a/stdlib.ispc b/stdlib.ispc index cb41c49c..160c520d 100644 --- a/stdlib.ispc +++ b/stdlib.ispc @@ -4411,6 +4411,42 @@ static inline varying int16 saturating_add(varying int16 a, varying int16 b) { return __padds_vi16(a, b); } +static inline uniform int32 saturating_add(uniform int32 a, uniform int32 b) { + uniform unsigned int32 a_unsig = a, b_unsig = b; + uniform unsigned int32 result = a_unsig + b_unsig; + a_unsig = (a_unsig >> 31) + INT32_MAX; + if ((uniform int32) ((a_unsig ^ b_unsig) | ~(b_unsig ^ result)) >= 0) + result = a_unsig; + return result; +} + +static inline varying int32 saturating_add(varying int32 a, varying int32 b) { + varying unsigned int32 a_unsig = a, b_unsig = b; + varying unsigned int32 result = a_unsig + b_unsig; + a_unsig = (a_unsig >> 31) + INT32_MAX; + if ((varying int32) ((a_unsig ^ b_unsig) | ~(b_unsig ^ result)) >= 0) + result = a_unsig; + return result; +} + +static inline uniform int64 saturating_add(uniform int64 a, uniform int64 b) { + uniform unsigned int64 a_unsig = a, b_unsig = b; + uniform unsigned int64 result = a_unsig + b_unsig; + a_unsig = (a_unsig >> 63) + INT64_MAX; + if ((uniform int64) ((a_unsig ^ b_unsig) | ~(b_unsig ^ result)) >= 0) + result = a_unsig; + return result; +} + +static inline varying int64 saturating_add(varying int64 a, varying int64 b) { + varying unsigned int64 a_unsig = a, b_unsig = b; + varying unsigned int64 result = a_unsig + b_unsig; + a_unsig = (a_unsig >> 63) + INT64_MAX; + if ((varying int64) ((a_unsig ^ b_unsig) | ~(b_unsig ^ result)) >= 0) + result = a_unsig; + return result; +} + static inline uniform unsigned int8 saturating_add(uniform unsigned int8 a, uniform unsigned int8 b) { uniform unsigned int8 result = a + b; @@ -4435,6 +4471,34 @@ static inline varying unsigned int16 saturating_add(varying unsigned int16 a, return __paddus_vi16(a, b); } +static inline uniform unsigned int32 saturating_add(uniform unsigned int32 a, + uniform unsigned int32 b) { + uniform unsigned int32 result = a + b; + result |= (-(uniform int32)(result < a)); + return result; +} + +static inline varying unsigned int32 saturating_add(varying unsigned int32 a, + varying unsigned int32 b) { + varying unsigned int32 result = a + b; + result |= (-(varying int32)(result < a)); + return result; +} + +static inline uniform unsigned int64 saturating_add(uniform unsigned int64 a, + uniform unsigned int64 b) { + uniform unsigned int64 result = a + b; + result |= (-(uniform int64)(result < a)); + return result; +} + +static inline varying unsigned int64 saturating_add(varying unsigned int64 a, + varying unsigned int64 b) { + varying unsigned int64 result = a + b; + result |= (-(varying int64)(result < a)); + return result; +} + static inline uniform int8 saturating_sub(uniform int8 a, uniform int8 b) { uniform unsigned int8 a_unsig = a, b_unsig = b; uniform unsigned int8 result = a_unsig - b_unsig; @@ -4461,6 +4525,42 @@ static inline varying int16 saturating_sub(varying int16 a, varying int16 b) { return __psubs_vi16(a, b); } +static inline uniform int32 saturating_sub(uniform int32 a, uniform int32 b) { + uniform unsigned int32 a_unsig = a, b_unsig = b; + uniform unsigned int32 result = a_unsig - b_unsig; + a_unsig = (a_unsig >> 31) + INT32_MAX; + if ((uniform int32) ((a_unsig ^ b_unsig) & (a_unsig ^ result)) < 0) + result = a_unsig; + return result; +} + +static inline varying int32 saturating_sub(varying int32 a, varying int32 b) { + varying unsigned int32 a_unsig = a, b_unsig = b; + varying unsigned int32 result = a_unsig - b_unsig; + a_unsig = (a_unsig >> 31) + INT32_MAX; + if ((varying int32) ((a_unsig ^ b_unsig) & (a_unsig ^ result)) < 0) + result = a_unsig; + return result; +} + +static inline uniform int64 saturating_sub(uniform int64 a, uniform int64 b) { + uniform unsigned int64 a_unsig = a, b_unsig = b; + uniform unsigned int64 result = a_unsig - b_unsig; + a_unsig = (a_unsig >> 63) + INT64_MAX; + if ((uniform int64) ((a_unsig ^ b_unsig) & (a_unsig ^ result)) < 0) + result = a_unsig; + return result; +} + +static inline varying int64 saturating_sub(varying int64 a, varying int64 b) { + varying unsigned int64 a_unsig = a, b_unsig = b; + varying unsigned int64 result = a_unsig - b_unsig; + a_unsig = (a_unsig >> 63) + INT64_MAX; + if ((varying int64) ((a_unsig ^ b_unsig) & (a_unsig ^ result)) < 0) + result = a_unsig; + return result; +} + static inline uniform unsigned int8 saturating_sub(uniform unsigned int8 a, uniform unsigned int8 b) { uniform unsigned int8 result = a - b; @@ -4484,6 +4584,34 @@ static inline varying unsigned int16 saturating_sub(varying unsigned int16 a, varying unsigned int16 b) { return __psubus_vi16(a, b); } + +static inline uniform unsigned int32 saturating_sub(uniform unsigned int32 a, + uniform unsigned int32 b) { + uniform unsigned int32 result = a - b; + result &= (-(uniform int32)(result <= a)); + return result; +} + +static inline varying unsigned int32 saturating_sub(varying unsigned int32 a, + varying unsigned int32 b) { + varying unsigned int32 result = a - b; + result &= (-(varying int32)(result <= a)); + return result; +} + +static inline uniform unsigned int64 saturating_sub(uniform unsigned int64 a, + uniform unsigned int64 b) { + uniform unsigned int64 result = a - b; + result &= (-(uniform int64)(result <= a)); + return result; +} + +static inline varying unsigned int64 saturating_sub(varying unsigned int64 a, + varying unsigned int64 b) { + varying unsigned int64 result = a - b; + result &= (-(varying int64)(result <= a)); + return result; +} /////////////////////////////////////////////////////////////////////////// // rdrand diff --git a/tests/padds_i32.ispc b/tests/padds_i32.ispc new file mode 100644 index 00000000..a92e640f --- /dev/null +++ b/tests/padds_i32.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform int32 a_max = 2147483647, a_min = -2147483648; // max and min signed int32 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_add(a_min, -b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform int32) 2147483647; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform int32) -2147483648; + } + else { + RET[programIndex] = (uniform int32) -2147483643; + } +} diff --git a/tests/padds_i64.ispc b/tests/padds_i64.ispc new file mode 100644 index 00000000..be21dc88 --- /dev/null +++ b/tests/padds_i64.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform int64 a_max = 9223372036854775807, a_min = -9223372036854775808; // max and min signed int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_add(a_min, -b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform int64) 9223372036854775807; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform int64) -9223372036854775808; + } + else { + RET[programIndex] = (uniform int64) -9223372036854775803; + } +} diff --git a/tests/padds_vi32.ispc b/tests/padds_vi32.ispc new file mode 100644 index 00000000..f566f84b --- /dev/null +++ b/tests/padds_vi32.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying int32 a_max = 2147483647, a_min = -2147483648; // max and min signed int32 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_add(a_min, -b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying int32) 2147483647; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying int32) -2147483648; + } + else { + RET[programIndex] = (varying int32) -2147483643; + } +} diff --git a/tests/padds_vi64.ispc b/tests/padds_vi64.ispc new file mode 100644 index 00000000..c8492fb4 --- /dev/null +++ b/tests/padds_vi64.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying int64 a_max = 9223372036854775807, a_min = -9223372036854775808; // max and min signed int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_add(a_min, -b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying int64) 9223372036854775807; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying int64) -9223372036854775808; + } + else { + RET[programIndex] = (varying int64) -9223372036854775803; + } +} diff --git a/tests/paddus_i32.ispc b/tests/paddus_i32.ispc new file mode 100644 index 00000000..2745b5eb --- /dev/null +++ b/tests/paddus_i32.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform unsigned int32 a_max = 4294967295, a_min = 0; // max and min unsigned int32 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (uniform unsigned int32) 4294967295; + } + else { + RET[programIndex] = (uniform unsigned int32) 5; + } +} diff --git a/tests/paddus_i64.ispc b/tests/paddus_i64.ispc new file mode 100644 index 00000000..ff63307d --- /dev/null +++ b/tests/paddus_i64.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform unsigned int64 a_max = 18446744073709551615, a_min = 0; // max and min unsigned int64 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (uniform unsigned int64) 18446744073709551615; + } + else { + RET[programIndex] = (uniform unsigned int64) 5; + } +} diff --git a/tests/paddus_vi32.ispc b/tests/paddus_vi32.ispc new file mode 100644 index 00000000..eaa4097f --- /dev/null +++ b/tests/paddus_vi32.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying unsigned int32 a_max = 4294967295, a_min = 0; // max and min unsigned int32 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (varying unsigned int32) 4294967295; + } + else { + RET[programIndex] = (varying unsigned int32) 5; + } +} diff --git a/tests/paddus_vi64.ispc b/tests/paddus_vi64.ispc new file mode 100644 index 00000000..3694125e --- /dev/null +++ b/tests/paddus_vi64.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying unsigned int64 a_max = 18446744073709551615, a_min = 0; // max and min unsigned int64 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_add(a_max, b); + } + else { + RET[programIndex] = saturating_add(a_min, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (varying unsigned int64) 18446744073709551615; + } + else { + RET[programIndex] = (varying unsigned int64) 5; + } +} diff --git a/tests/psubs_i32.ispc b/tests/psubs_i32.ispc new file mode 100644 index 00000000..9fefd861 --- /dev/null +++ b/tests/psubs_i32.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform int32 a_max = 2147483647, a_min = -2147483648; // max and min int32 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_sub(a_max, -b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform int32) -2147483648; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform int32) 2147483647; + } + else { + RET[programIndex] = (uniform int32) 2147483642; + } +} diff --git a/tests/psubs_i64.ispc b/tests/psubs_i64.ispc new file mode 100644 index 00000000..b1e061bc --- /dev/null +++ b/tests/psubs_i64.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform int64 a_max = 9223372036854775807, a_min = -9223372036854775808; // max and min int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_sub(a_max, -b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (uniform int64) -9223372036854775808; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (uniform int64) 9223372036854775807; + } + else { + RET[programIndex] = (uniform int64) 9223372036854775802; + } +} diff --git a/tests/psubs_vi32.ispc b/tests/psubs_vi32.ispc new file mode 100644 index 00000000..1dd2720c --- /dev/null +++ b/tests/psubs_vi32.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying int32 a_max = 2147483647, a_min = -2147483648; // max and min int32 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_sub(a_max, -b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying int32) -2147483648; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying int32) 2147483647; + } + else { + RET[programIndex] = (varying int32) 2147483642; + } +} diff --git a/tests/psubs_vi64.ispc b/tests/psubs_vi64.ispc new file mode 100644 index 00000000..75a9711e --- /dev/null +++ b/tests/psubs_vi64.ispc @@ -0,0 +1,27 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying int64 a_max = 9223372036854775807, a_min = -9223372036854775808; // max and min int64 + if (programIndex % 3 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else if (programIndex % 3 == 1) { + RET[programIndex] = saturating_sub(a_max, -b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 3 == 0) { + RET[programIndex] = (varying int64) -9223372036854775808; + } + else if (programIndex % 3 == 1) { + RET[programIndex] = (varying int64) 9223372036854775807; + } + else { + RET[programIndex] = (varying int64) 9223372036854775802; + } +} diff --git a/tests/psubus_i32.ispc b/tests/psubus_i32.ispc new file mode 100644 index 00000000..dc188fc3 --- /dev/null +++ b/tests/psubus_i32.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform unsigned int32 a_max = 4294967295, a_min = 0; // max and min unsigned int32 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (uniform unsigned int32) 0; + } + else { + RET[programIndex] = (uniform unsigned int32) 4294967290; + } +} diff --git a/tests/psubus_i64.ispc b/tests/psubus_i64.ispc new file mode 100644 index 00000000..bca59a40 --- /dev/null +++ b/tests/psubus_i64.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + uniform unsigned int64 a_max = 18446744073709551615, a_min = 0; // max and min unsigned int64 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (uniform unsigned int64) 0; + } + else { + RET[programIndex] = (uniform unsigned int64) 18446744073709551610; + } +} diff --git a/tests/psubus_vi32.ispc b/tests/psubus_vi32.ispc new file mode 100644 index 00000000..dffcaeb4 --- /dev/null +++ b/tests/psubus_vi32.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying unsigned int32 a_max = 4294967295, a_min = 0; // max and min unsigned int32 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (varying unsigned int32) 0; + } + else { + RET[programIndex] = (varying unsigned int32) 4294967290; + } +} diff --git a/tests/psubus_vi64.ispc b/tests/psubus_vi64.ispc new file mode 100644 index 00000000..e56d8972 --- /dev/null +++ b/tests/psubus_vi64.ispc @@ -0,0 +1,21 @@ + +export uniform int width() { return programCount; } + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying unsigned int64 a_max = 18446744073709551615, a_min = 0; // max and min unsigned int64 + if (programIndex % 2 == 0) { + RET[programIndex] = saturating_sub(a_min, b); + } + else { + RET[programIndex] = saturating_sub(a_max, b); + } +} + +export void result(uniform float RET[]) { + if (programIndex % 2 == 0) { + RET[programIndex] = (varying unsigned int64) 0; + } + else { + RET[programIndex] = (varying unsigned int64) 18446744073709551610; + } +}