Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2d50750
remove dummy bin
jinge90 Nov 24, 2025
9c76946
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Nov 26, 2025
fe628a9
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Nov 27, 2025
7a7e62b
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Nov 28, 2025
4de8fa5
merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 1, 2025
e52bb98
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 4, 2025
4b63322
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 10, 2025
544d912
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 12, 2025
2ad6143
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 17, 2025
cf391d9
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Dec 24, 2025
e0f2a15
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Jan 6, 2026
aa7a97c
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Jan 12, 2026
9244680
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Jan 30, 2026
b4b5793
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Feb 3, 2026
50f8f75
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Feb 4, 2026
ebc7166
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Feb 4, 2026
159748c
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Feb 4, 2026
17362e0
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Mar 3, 2026
9e38387
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Mar 5, 2026
dd1e30b
Merge remote-tracking branch 'origin/sycl' into sycl
jinge90 Mar 5, 2026
01fa557
Merge remote-tracking branch 'upstream/sycl' into sycl
jinge90 Mar 25, 2026
08ff3e3
[SYCL] Add E2E test to cover std::complex<T> mul/div
jinge90 Mar 25, 2026
bc9a08e
make the mulsc3/divsc3 test to run on Linux
jinge90 Mar 26, 2026
2102954
fix typo
jinge90 Mar 26, 2026
a7d4c12
Merge remote-tracking branch 'upstream/sycl' into add_test_for_mulsc3…
jinge90 Mar 31, 2026
5f7adec
fix header
jinge90 Mar 31, 2026
1a15fd8
include cmath header
jinge90 Mar 31, 2026
fc65987
Update sycl/test-e2e/DeviceLib/std_complex_math_test.cpp
jinge90 Apr 1, 2026
a30bd8d
address copilot comments
jinge90 Apr 1, 2026
b5938c9
Update sycl/test-e2e/DeviceLib/std_complex_math_test.cpp
jinge90 Apr 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 376 additions & 0 deletions sycl/test-e2e/DeviceLib/complex_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,376 @@
#pragma once
#include <array>
#include <cmath>
#include <complex>
#include <sycl/detail/core.hpp>
enum { zero, non_zero, inf, NaN, non_zero_nan };
template <typename T> int complex_classify(std::complex<T> x) {
if (x == std::complex<T>(0, 0))
return zero;
if (std::isinf(x.real()) || std::isinf(x.imag()))
return inf;
Comment on lines +1 to +11
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

complex_utils.hpp uses std::array, std::isnan, and std::isinf but only includes <complex>. Please add the missing standard headers (e.g., <array> and <cmath>) so this helper is self-contained and doesn’t rely on include order in the including test files.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

if (std::isnan(x.real()) && std::isnan(x.imag()))
return NaN;
if (std::isnan(x.real())) {
if (x.imag() == 0)
return NaN;
return non_zero_nan;
}
if (std::isnan(x.imag())) {
if (x.real() == 0)
return NaN;
return non_zero_nan;
}
return non_zero;
}

template <typename T>
int complex_compare_mul(std::complex<T> x, std::complex<T> y,
std::complex<T> z) {
switch (complex_classify<T>(x)) {
case zero:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != zero)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != zero)
return 1;
break;
case inf:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case non_zero:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != zero)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != non_zero)
return 1;
{
T a = x.real(), b = x.imag(), c = y.real(), d = y.imag();
std::complex<T> t(a * c - b * d, a * d + b * c);
// relaxed tolerance to arbitrary (1.e-6) amount.
if (std::abs((z - t) / z) > 1.e-6)
return 1;
}
break;
case inf:
if (complex_classify<T>(z) != inf)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case inf:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != inf)
return 1;
break;
case inf:
if (complex_classify<T>(z) != inf)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != inf)
return 1;
break;
}
break;
case NaN:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case inf:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case non_zero_nan:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case inf:
if (complex_classify<T>(z) != inf)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
}

return 0;
}

template <typename T>
int complex_compare_div(std::complex<T> x, std::complex<T> y,
std::complex<T> z) {
switch (complex_classify<T>(x)) {
case zero:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != zero)
return 1;
break;
case inf:
if (complex_classify<T>(z) != zero)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case non_zero:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != inf)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != non_zero)
return 1;
{
T a = x.real(), b = x.imag(), c = y.real(), d = y.imag();
std::complex<T> t((a * c + b * d) / (c * c + d * d),
(b * c - a * d) / (c * c + d * d));
if (std::abs((z - t) / z) > 1.e-6)
return 1;
}
break;
case inf:
if (complex_classify<T>(z) != zero)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case inf:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != inf)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != inf)
return 1;
break;
case inf:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case NaN:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case inf:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
case non_zero_nan:
switch (complex_classify<T>(y)) {
case zero:
if (complex_classify<T>(z) != inf)
return 1;
break;
case non_zero:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case inf:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case NaN:
if (complex_classify<T>(z) != NaN)
return 1;
break;
case non_zero_nan:
if (complex_classify<T>(z) != NaN)
return 1;
break;
}
break;
}

return 0;
}
template <typename T, size_t InputSize>
int device_complex_test_mul(sycl::queue &deviceQueue,
std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfMulInput{InputSize};
sycl::range<1> numOfMulOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_mul_result;
{
sycl::buffer<std::complex<T>, 1> buffer_complex_mul(complex_input,
numOfMulInput);
Comment on lines +300 to +307
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

device_complex_test_mul only reads from complex_input. Consider taking const std::complex<T>* (and creating the input buffer from a const pointer where possible) to make the API intent clear and prevent accidental mutation.

Suggested change
std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfMulInput{InputSize};
sycl::range<1> numOfMulOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_mul_result;
{
sycl::buffer<std::complex<T>, 1> buffer_complex_mul(complex_input,
numOfMulInput);
const std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfMulInput{InputSize};
sycl::range<1> numOfMulOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_mul_result;
{
sycl::buffer<const std::complex<T>, 1> buffer_complex_mul(complex_input,
numOfMulInput);

Copilot uses AI. Check for mistakes.
sycl::buffer<std::complex<T>, 1> buffer_complex_mul_res(
complex_mul_result.data(), numOfMulOutput);
deviceQueue.submit([&](sycl::handler &cgh) {
auto complex_mul_access =
buffer_complex_mul.template get_access<sycl::access::mode::read>(cgh);
auto complex_mul_res_access =
buffer_complex_mul_res.template get_access<sycl::access::mode::write>(
cgh);
cgh.single_task<class DeviceComplexMulTest>([=]() {
size_t i, j;
for (i = 0; i < InputSize; ++i) {
Comment on lines +310 to +318
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

device_complex_test_mul is a function template, but the kernel is always named DeviceComplexMulTest. If this helper ever gets instantiated more than once in the same translation unit (e.g., for both float and double, or different InputSize), the identical kernel name type can cause a SYCL kernel name collision/ODR violation. Consider making the kernel name depend on the template parameters (e.g., a templated kernel-name type) or using an unnamed kernel form if supported by the project/toolchain.

Copilot uses AI. Check for mistakes.
for (j = 0; j < InputSize; ++j)
complex_mul_res_access[i * InputSize + j] =
complex_mul_access[i] * complex_mul_access[j];
}
});
});
}

size_t i, j;
for (i = 0; i < InputSize; ++i)
for (j = 0; j < InputSize; ++j) {
if (complex_compare_mul(complex_input[i], complex_input[j],
complex_mul_result[i * InputSize + j])) {
return 1;
}
}
return 0;
Comment on lines +327 to +335
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both device_complex_test_mul/device_complex_test_div return 1 on the first mismatch and don’t report which (i,j) input pair failed or what the computed/expected values were. That makes failures hard to diagnose in CI. Consider accumulating a failure count (like the other tests in this directory) and/or printing the failing indices and values before returning.

Copilot uses AI. Check for mistakes.
}

template <typename T, size_t InputSize>
int device_complex_test_div(sycl::queue &deviceQueue,
std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfDivInput{InputSize};
sycl::range<1> numOfDivOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_div_result;
{
sycl::buffer<std::complex<T>, 1> buffer_complex_div(complex_input,
numOfDivInput);
Comment on lines +340 to +347
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

device_complex_test_div only reads from complex_input. Consider taking const std::complex<T>* (and using a read-only buffer/accessor) to better express const-correctness.

Suggested change
std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfDivInput{InputSize};
sycl::range<1> numOfDivOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_div_result;
{
sycl::buffer<std::complex<T>, 1> buffer_complex_div(complex_input,
numOfDivInput);
const std::complex<T> *complex_input) {
constexpr size_t OutputSize = InputSize * InputSize;
sycl::range<1> numOfDivInput{InputSize};
sycl::range<1> numOfDivOutput{OutputSize};
std::array<std::complex<T>, OutputSize> complex_div_result;
{
sycl::buffer<const std::complex<T>, 1> buffer_complex_div(complex_input,
numOfDivInput);

Copilot uses AI. Check for mistakes.
sycl::buffer<std::complex<T>, 1> buffer_complex_div_res(
complex_div_result.data(), numOfDivOutput);
deviceQueue.submit([&](sycl::handler &cgh) {
auto complex_div_access =
buffer_complex_div.template get_access<sycl::access::mode::read>(cgh);
auto complex_div_res_access =
buffer_complex_div_res.template get_access<sycl::access::mode::write>(
cgh);
cgh.single_task<class DeviceComplexDivTest>([=]() {
size_t i, j;
for (i = 0; i < InputSize; ++i) {
Comment on lines +350 to +358
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

device_complex_test_div is a function template, but the kernel is always named DeviceComplexDivTest. If this helper is instantiated more than once in the same translation unit (different T/InputSize), the repeated kernel name type can cause a SYCL kernel name collision/ODR violation. Consider parameterizing the kernel-name type on the template arguments (or using an unnamed kernel form).

Copilot uses AI. Check for mistakes.
for (j = 0; j < InputSize; ++j)
complex_div_res_access[i * InputSize + j] =
complex_div_access[i] / complex_div_access[j];
}
});
});
}

size_t i, j;
for (i = 0; i < InputSize; ++i)
for (j = 0; j < InputSize; ++j) {
if (complex_compare_div(complex_input[i], complex_input[j],
complex_div_result[i * InputSize + j])) {
return 1;
}
}
return 0;
}
Loading
Loading