Skip to content

Commit 77d648d

Browse files
eunakim0103euna.kim
andauthored
[SYCL] Change the behavior of sycl::maximum and sycl::minimum to be consistent with std::max and std::min (#10094)
The behavior of sycl::maximum and sycl::minimum used to be different from std::max and std::min in the case of one of two operand was NaN since sycl::maximum was implemented with std::greater<> while std::max used operator <. KhronosGroup/SYCL-Docs#285 --------- Signed-off-by: Kim, Euna <[email protected]> Co-authored-by: euna.kim <[email protected]>
1 parent 19f9807 commit 77d648d

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

sycl/include/sycl/functional.hpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,36 +35,39 @@ template <typename T = void> struct logical_or {
3535

3636
template <> struct logical_or<void> : std::logical_or<void> {};
3737

38+
// sycl::minimum definition should be consistent with std::min
3839
template <typename T = void> struct minimum {
3940
T operator()(const T &lhs, const T &rhs) const {
40-
return std::less<T>()(lhs, rhs) ? lhs : rhs;
41+
return (rhs < lhs) ? rhs : lhs;
4142
}
4243
};
4344

4445
template <> struct minimum<void> {
4546
struct is_transparent {};
4647
template <typename T, typename U>
47-
auto operator()(T &&lhs, U &&rhs) const -> std::common_type_t<T &&, U &&> {
48-
return std::less<>()(std::forward<const T>(lhs), std::forward<const U>(rhs))
49-
? std::forward<T>(lhs)
50-
: std::forward<U>(rhs);
48+
auto operator()(T &&lhs, U &&rhs) const ->
49+
typename std::common_type<T &&, U &&>::type {
50+
return (std::forward<const U>(rhs) < std::forward<const T>(lhs))
51+
? std::forward<U>(rhs)
52+
: std::forward<T>(lhs);
5153
}
5254
};
5355

56+
// sycl::maximum definition should be consistent with std::max
5457
template <typename T = void> struct maximum {
5558
T operator()(const T &lhs, const T &rhs) const {
56-
return std::greater<T>()(lhs, rhs) ? lhs : rhs;
59+
return (lhs < rhs) ? rhs : lhs;
5760
}
5861
};
5962

6063
template <> struct maximum<void> {
6164
struct is_transparent {};
6265
template <typename T, typename U>
63-
auto operator()(T &&lhs, U &&rhs) const -> std::common_type_t<T &&, U &&> {
64-
return std::greater<>()(std::forward<const T>(lhs),
65-
std::forward<const U>(rhs))
66-
? std::forward<T>(lhs)
67-
: std::forward<U>(rhs);
66+
auto operator()(T &&lhs, U &&rhs) const ->
67+
typename std::common_type<T &&, U &&>::type {
68+
return (std::forward<const T>(lhs) < std::forward<const U>(rhs))
69+
? std::forward<U>(rhs)
70+
: std::forward<T>(lhs);
6871
}
6972
};
7073

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: %t.out
3+
#include <sycl/sycl.hpp>
4+
5+
#include <algorithm>
6+
#include <cassert>
7+
#include <limits>
8+
9+
int main() {
10+
double f1 = 1.0f;
11+
double f2 = std::numeric_limits<double>::quiet_NaN();
12+
13+
assert(((std::max(f1, f2) == sycl::maximum{}(f1, f2)) &&
14+
"sycl::maximum result is wrong"));
15+
assert(((std::isnan((std::max(f2, f1)))) &&
16+
(std::isnan(sycl::maximum{}(f2, f1)))) &&
17+
"sycl::maximum result is wrong");
18+
assert(((std::min(f1, f2) == sycl::minimum{}(f1, f2)) &&
19+
"sycl::minimum result is wrong"));
20+
assert(((std::isnan((std::min(f2, f1)))) &&
21+
(std::isnan(sycl::minimum{}(f2, f1)))) &&
22+
"sycl::minimum result is wrong");
23+
24+
return 0;
25+
}

0 commit comments

Comments
 (0)