Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/Catch2"]
path = vendor/Catch2
url = https://github.com/catchorg/Catch2
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.15)
project(sandbox LANGUAGES CXX)

# Setup Catch2
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/vendor/Catch2/CMakeLists.txt")
message(FATAL_ERROR "The git submodule vendor/Catch2 is missing.\nTry running `git submodule update --init`.")
endif()
add_subdirectory(vendor/Catch2)

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
# find_package(DPCPP)

# Load catch2 cmake module
include(CTest)
include(Catch)

add_subdirectory(tests)

15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,17 @@ int main() {

## Tests

Crude tests for all C++ complex math functions are provided in `/tests/`. Just defined a correct `CXX` and then `make` , `make run`
Testing is implemented with Catch2 and CMake. Catch2 is added as a git submodule inside the `vendor` directory.

Instructions to build and run tests for DPCPP are below:
```
mkdir build

cd build

cmake -G Ninja -DCMAKE_CXX_COMPILER=$PATH_TO_LLVM/bin/clang++ -DCMAKE_CXX_FLAGS=-fsycl ..

ninja

ctest
Comment thread
AidanBeltonS marked this conversation as resolved.
```
45 changes: 45 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
file(GLOB test_cases CONFIGURE_DEPENDS "*.cpp")

# set(test_cases

@TApplencourt TApplencourt Sep 6, 2022

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess we can remove the comments now :)

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.

Haha thanks for catching this. I have removed the comments

# "abs_complex.cpp"
# "acos_complex.cpp"
# "acosh_complex.cpp"
# "arg_complex.cpp"
# "asin_complex.cpp"
# "asinh_complex.cpp"
# "atan_complex.cpp"
# "atanh_complex.cpp"
# "cos_complex.cpp"
# "cosh_complex.cpp"
# "exp_complex.cpp"
# "log_complex.cpp"
# "log10_complex.cpp"
# "norm_complex.cpp"
# "polar_complex.cpp"
# "pow_complex.cpp"
# "sin_complex.cpp"
# "sinh_complex.cpp"
# "sqrt_complex.cpp"
# "tan_complex.cpp"
# "tanh_complex.cpp"
# "test_complex_types.cpp"
# "test_gencomplex.cpp"
# "test_operator_complex.cpp"
# "test_stream_operator.cpp"
# )

foreach(test_file IN LISTS test_cases)
# if(EXISTS "${test_file}")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# if(EXISTS "${test_file}")

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.

I have uncommented these checks to make sure each file is available and emit a warning if it is not.

get_filename_component(exe_name "${test_file}" NAME_WE)

add_executable(${exe_name} ${test_file})
target_include_directories(${exe_name} PUBLIC ../include/)
target_link_libraries(${exe_name} PRIVATE
Catch2::Catch2WithMain
)

catch_discover_tests(${exe_name})
# else()
# message(FATAL_ERROR "No file named ${test_file}")
# endif()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# else()
# message(FATAL_ERROR "No file named ${test_file}")
# endif()

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.

I have uncommented this check. Same as above.

endforeach()
26 changes: 0 additions & 26 deletions tests/Makefile

This file was deleted.

67 changes: 25 additions & 42 deletions tests/abs_complex.cpp
Original file line number Diff line number Diff line change
@@ -1,57 +1,40 @@
#include "test_helper.hpp"

template <typename T> struct test_abs {
bool operator()(sycl::queue &Q, T init_re, T init_im) {
bool pass = true;
TEMPLATE_TEST_CASE("Test complex abs", "[abs]", double, float, sycl::half) {
using T = TestType;

auto std_in = init_std_complex(init_re, init_im);
sycl::ext::cplx::complex<T> cplx_input{init_re, init_im};
sycl::queue Q;

// Test cases
cmplx<T> input = GENERATE(
cmplx<T>{4.42, 2.02}, cmplx<T>{inf_val<T>, 2.02},
cmplx<T>{4.42, inf_val<T>}, cmplx<T>{inf_val<T>, inf_val<T>},
cmplx<T>{nan_val<T>, 2.02}, cmplx<T>{4.42, nan_val<T>},
cmplx<T>{nan_val<T>, nan_val<T>}, cmplx<T>{nan_val<T>, inf_val<T>},
cmplx<T>{inf_val<T>, nan_val<T>});

auto std_in = init_std_complex(input);
sycl::ext::cplx::complex<T> cplx_input{input.re, input.im};

T std_out{};
auto *cplx_out = sycl::malloc_shared<T>(1, Q);
T std_out{};
auto *cplx_out = sycl::malloc_shared<T>(1, Q);

// Get std::complex output
std_out = std::abs(std_in);
// Get std::complex output
std_out = std::abs(std_in);

// Check cplx::complex output from device
// Check cplx::complex output from device
if (is_type_supported<T>(Q)) {
Q.single_task([=]() {
cplx_out[0] = sycl::ext::cplx::abs<T>(cplx_input);
}).wait();

pass &= check_results(cplx_out[0], std_out, /*is_device*/ true);

// Check cplx::complex output from host
cplx_out[0] = sycl::ext::cplx::abs<T>(cplx_input);

pass &= check_results(cplx_out[0], std_out, /*is_device*/ false);

sycl::free(cplx_out, Q);

return pass;
check_results(cplx_out[0], std_out);
}
};

int main() {
sycl::queue Q;

bool test_passes = true;
test_passes &= test_valid_types<test_abs>(Q, 4.42, 2.02);

test_passes &= test_valid_types<test_abs>(Q, INFINITY, 2.02);
test_passes &= test_valid_types<test_abs>(Q, 4.42, INFINITY);
test_passes &= test_valid_types<test_abs>(Q, INFINITY, INFINITY);

test_passes &= test_valid_types<test_abs>(Q, NAN, 2.02);
test_passes &= test_valid_types<test_abs>(Q, 4.42, NAN);
test_passes &= test_valid_types<test_abs>(Q, NAN, NAN);

test_passes &= test_valid_types<test_abs>(Q, NAN, INFINITY);
test_passes &= test_valid_types<test_abs>(Q, INFINITY, NAN);
test_passes &= test_valid_types<test_abs>(Q, NAN, INFINITY);
test_passes &= test_valid_types<test_abs>(Q, INFINITY, NAN);
// Check cplx::complex output from host
cplx_out[0] = sycl::ext::cplx::abs<T>(cplx_input);

if (!test_passes)
std::cerr << "acos complex test fails\n";
check_results(cplx_out[0], std_out);

return !test_passes;
sycl::free(cplx_out, Q);
}
86 changes: 36 additions & 50 deletions tests/acos_complex.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
#include "test_helper.hpp"

template <typename T> struct test_acos {
bool operator()(sycl::queue &Q, T init_re, T init_im,
bool is_error_checking = false) {
bool pass = true;
TEMPLATE_TEST_CASE("Test complex acos", "[acos]", double, float, sycl::half) {
using T = TestType;
using std::make_tuple;

auto std_in = init_std_complex(init_re, init_im);
sycl::ext::cplx::complex<T> cplx_input{init_re, init_im};
sycl::queue Q;

cmplx<T> input;
bool is_error_checking;

std::tie(input, is_error_checking) = GENERATE(table<cmplx<T>, bool>(
{make_tuple(cmplx<T>{4.42, 2.02}, false),
make_tuple(cmplx<T>{inf_val<T>, 2.02}, true),
make_tuple(cmplx<T>{4.42, inf_val<T>}, true),
make_tuple(cmplx<T>{inf_val<T>, inf_val<T>}, true),
make_tuple(cmplx<T>{nan_val<T>, 2.02}, true),
make_tuple(cmplx<T>{4.42, nan_val<T>}, true),
make_tuple(cmplx<T>{nan_val<T>, nan_val<T>}, true),
make_tuple(cmplx<T>{nan_val<T>, inf_val<T>}, true),
make_tuple(cmplx<T>{inf_val<T>, nan_val<T>}, true)}));

auto std_in = init_std_complex(input);
sycl::ext::cplx::complex<T> cplx_input{input.re, input.im};

std::complex<T> std_out{init_re, init_im};
auto *cplx_out = sycl::malloc_shared<sycl::ext::cplx::complex<T>>(1, Q);
std::complex<T> std_out{input.re, input.im};
auto *cplx_out = sycl::malloc_shared<sycl::ext::cplx::complex<T>>(1, Q);

// Get std::complex output
if (is_error_checking)
std_out = std::acos(std_in);
// Get std::complex output
if (is_error_checking)
std_out = std::acos(std_in);

// Check cplx::complex output from device
// Check cplx::complex output from device
if (is_type_supported<T>(Q)) {
if (is_error_checking) {
Q.single_task(
[=]() { cplx_out[0] = sycl::ext::cplx::acos<T>(cplx_input); });
Expand All @@ -26,47 +42,17 @@ template <typename T> struct test_acos {
});
}
Q.wait();

pass &= check_results(cplx_out[0], std_out, /*is_device*/ true,
/*tol_multiplier*/ 2);

// Check cplx::complex output from host
if (is_error_checking)
cplx_out[0] = sycl::ext::cplx::acos<T>(cplx_input);
else
cplx_out[0] =
sycl::ext::cplx::cos<T>(sycl::ext::cplx::acos<T>(cplx_input));

pass &= check_results(cplx_out[0], std_out, /*is_device*/ false,
/*tol_multiplier*/ 2);

sycl::free(cplx_out, Q);

return pass;
}
};

int main() {
sycl::queue Q;

bool test_passes = true;
test_passes &= test_valid_types<test_acos>(Q, 4.42, 2.02);

test_passes &= test_valid_types<test_acos>(Q, INFINITY, 2.02, true);
test_passes &= test_valid_types<test_acos>(Q, 4.42, INFINITY, true);
test_passes &= test_valid_types<test_acos>(Q, INFINITY, INFINITY, true);

test_passes &= test_valid_types<test_acos>(Q, NAN, 2.02, true);
test_passes &= test_valid_types<test_acos>(Q, 4.42, NAN, true);
test_passes &= test_valid_types<test_acos>(Q, NAN, NAN, true);
check_results(cplx_out[0], std_out, /*tol_multiplier*/ 2);

test_passes &= test_valid_types<test_acos>(Q, NAN, INFINITY, true);
test_passes &= test_valid_types<test_acos>(Q, INFINITY, NAN, true);
test_passes &= test_valid_types<test_acos>(Q, NAN, INFINITY, true);
test_passes &= test_valid_types<test_acos>(Q, INFINITY, NAN, true);
// Check cplx::complex output from host
if (is_error_checking)
cplx_out[0] = sycl::ext::cplx::acos<T>(cplx_input);
else
cplx_out[0] = sycl::ext::cplx::cos<T>(sycl::ext::cplx::acos<T>(cplx_input));

if (!test_passes)
std::cerr << "acos complex test fails\n";
check_results(cplx_out[0], std_out, /*tol_multiplier*/ 2);

return !test_passes;
sycl::free(cplx_out, Q);
}
Loading