Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit d5b98d8

Browse files
authored
[SYCL][ESIMD] Add mutator for test input data (#789)
Provides the following things: - base options to mutate value. - the function that applies provided mutator to each value for the provided container
1 parent 2db68c1 commit d5b98d8

File tree

4 files changed

+144
-2
lines changed

4 files changed

+144
-2
lines changed

SYCL/ESIMD/api/functional/mutator.hpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//===-- mutator.hpp - This file provides common function and classes to mutate
2+
// reference data. ---------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// This file provides common function and classes to mutate reference data.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#pragma once
16+
17+
#include "type_traits.hpp"
18+
#include "value.hpp"
19+
#include <sycl/sycl.hpp>
20+
21+
// for std::for_each
22+
#include <algorithm>
23+
#include <vector>
24+
25+
namespace esimd_test::api::functional {
26+
27+
// In some test cases it’s possible to pass a reference data as the input data
28+
// directly without any modification. For example, if we check some copy
29+
// constructor or memory move operation it’s OK to have any data values as the
30+
// input ones. But in most cases we need to consider the possibility of UB for
31+
// C++ operations due to modification of input values.
32+
//
33+
// Mutation mechanism covers such requirement.
34+
// The mutator namespace is intended to store such mutators alongside with
35+
// the generic ones provided below.
36+
namespace mutator {
37+
38+
// Replace specific reference values to the bigger ones, so we can safely
39+
// substract `m_value` later.
40+
template <typename T> class For_subtraction {
41+
T m_value;
42+
43+
public:
44+
For_subtraction(T val)
45+
: m_value((assert(val > 0 && "Invalid value."), val)) {}
46+
47+
void operator()(T &val) {
48+
if constexpr (type_traits::is_sycl_signed_v<T>) {
49+
const T lower_border = value<T>::lowest() + m_value;
50+
if (val < lower_border) {
51+
// Validate only the negative infinity case, as the NaN will not enter
52+
// this branch.
53+
if constexpr (type_traits::is_sycl_floating_point_v<T>) {
54+
// sycl::half will be converted to float
55+
if (std::isinf(val)) {
56+
return;
57+
}
58+
}
59+
// we need to update value to avoid UB during subtraction.
60+
val = lower_border;
61+
}
62+
}
63+
}
64+
};
65+
66+
// Replace specific reference values to the smaller ones, so we can safely add
67+
// `m_value` later.
68+
template <typename T> class For_addition {
69+
T m_value;
70+
71+
public:
72+
For_addition(T val) : m_value((assert(val > 0 && "Invalid value."), val)) {}
73+
74+
void operator()(T &val) {
75+
if constexpr (type_traits::is_sycl_signed_v<T>) {
76+
const T upper_border = value<T>::max() - m_value;
77+
if (val > upper_border) {
78+
// Validate only the negative infinity case, as the NaN will not enter
79+
// this branch.
80+
if constexpr (type_traits::is_sycl_floating_point_v<T>) {
81+
// sycl::half will be converted to float
82+
if (std::isinf(val)) {
83+
return;
84+
}
85+
}
86+
// we need to update value to avoid UB during addition.
87+
val = upper_border;
88+
}
89+
}
90+
}
91+
};
92+
93+
// Replace specific reference values to the divided ones, so we can safely
94+
// multiply to `m_value` later.
95+
template <typename T> class For_multiplication {
96+
T m_value;
97+
98+
public:
99+
For_multiplication(T val)
100+
: m_value((assert(val > 0 && "Invalid value."), val)) {}
101+
102+
void operator()(T &val) {
103+
// We don't need to change the inf values, because inf * value gives inf.
104+
if constexpr (type_traits::is_sycl_floating_point_v<T>) {
105+
if (val == value<T>::inf() || val == -value<T>::inf()) {
106+
return;
107+
}
108+
}
109+
110+
const T upper_border = value<T>::max() / m_value;
111+
// we need to update value to avoid UB during multiplication for positive
112+
// and negative numbers.
113+
if (val > upper_border) {
114+
val = upper_border;
115+
} else if (val < -upper_border) {
116+
val = -upper_border;
117+
}
118+
}
119+
};
120+
121+
} // namespace mutator
122+
123+
// Applies provided mutator to each value for provided container.
124+
template <typename T, typename MutatorT>
125+
inline void mutate(std::vector<T> &input_vector, MutatorT &&mutator) {
126+
std::for_each(input_vector.begin(), input_vector.end(), mutator);
127+
}
128+
129+
} // namespace esimd_test::api::functional

SYCL/ESIMD/api/functional/type_traits.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#pragma once
1515

16+
#include <sycl/sycl.hpp>
17+
1618
#include <type_traits>
1719
#include <utility>
1820

@@ -27,6 +29,13 @@ template <typename T>
2729
inline constexpr bool is_sycl_floating_point_v{
2830
is_sycl_floating_point<T>::value};
2931

32+
template <typename T>
33+
using is_sycl_signed =
34+
std::bool_constant<std::is_signed_v<T> || is_sycl_floating_point_v<T>>;
35+
36+
template <typename T>
37+
inline constexpr bool is_sycl_signed_v{is_sycl_signed<T>::value};
38+
3039
template <typename T>
3140
using is_nonconst_rvalue_reference =
3241
std::bool_constant<std::is_rvalue_reference_v<T> &&

SYCL/ESIMD/api/functional/value.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
//===----------------------------------------------------------------------===//
1515

1616
#pragma once
17+
18+
#include "../../esimd_test_utils.hpp"
1719
#include "type_traits.hpp"
18-
#include <CL/sycl.hpp>
20+
#include <sycl/sycl.hpp>
1921

2022
#include <climits>
2123
#include <limits>

SYCL/ESIMD/esimd_test_utils.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include <CL/sycl.hpp>
9+
#pragma once
10+
11+
#include <sycl/sycl.hpp>
1012

1113
#define NOMINMAX
1214

0 commit comments

Comments
 (0)