2
0
mirror of https://github.com/boostorg/compute.git synced 2026-01-24 17:52:37 +00:00
Files
compute/test/test_valarray.cpp
Jakub Szuppe 28f08dda44 Add valarray operators
This adds missing operators to valarray. Note that in OpenCL it's impossible
to create memory buffer with bool type and because of that valarray<char> is used
as a return type for comparison and logical operators instead of valarray<bool>.
Implemented operators work only for default context (queue) and are asynchronous.
2015-05-15 18:12:07 +02:00

362 lines
14 KiB
C++

//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://kylelutz.github.com/compute for more information.
//---------------------------------------------------------------------------//
#define BOOST_TEST_MODULE TestValarray
#include <boost/test/unit_test.hpp>
#include <boost/compute/system.hpp>
#include <boost/compute/command_queue.hpp>
#include <boost/compute/container/valarray.hpp>
#include "check_macros.hpp"
#include "context_setup.hpp"
BOOST_AUTO_TEST_CASE(size)
{
boost::compute::valarray<float> array;
BOOST_CHECK_EQUAL(array.size(), size_t(0));
array.resize(10);
BOOST_CHECK_EQUAL(array.size(), size_t(10));
}
BOOST_AUTO_TEST_CASE(at)
{
int data[] = { 1, 2, 3, 4, 5 };
boost::compute::valarray<int> array(data, 5);
BOOST_CHECK_EQUAL(array.size(), size_t(5));
boost::compute::system::finish();
BOOST_CHECK_EQUAL(int(array[0]), int(1));
BOOST_CHECK_EQUAL(int(array[1]), int(2));
BOOST_CHECK_EQUAL(int(array[2]), int(3));
BOOST_CHECK_EQUAL(int(array[3]), int(4));
BOOST_CHECK_EQUAL(int(array[4]), int(5));
}
BOOST_AUTO_TEST_CASE(min_and_max)
{
int data[] = { 5, 2, 3, 7, 1, 9, 6, 5 };
boost::compute::valarray<int> array(data, 8);
BOOST_CHECK_EQUAL(array.size(), size_t(8));
BOOST_CHECK_EQUAL((array.min)(), int(1));
BOOST_CHECK_EQUAL((array.max)(), int(9));
}
BOOST_AUTO_TEST_CASE(sum)
{
int data[] = { 1, 2, 3, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::system::finish();
BOOST_CHECK_EQUAL(array.size(), size_t(4));
BOOST_CHECK_EQUAL(array.sum(), int(10));
}
BOOST_AUTO_TEST_CASE(apply)
{
int data[] = { -1, 2, -3, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::abs<int> abs;
boost::compute::valarray<int> result = array.apply(abs);
boost::compute::system::finish();
BOOST_CHECK_EQUAL(int(result[0]), int(1));
BOOST_CHECK_EQUAL(int(result[1]), int(2));
BOOST_CHECK_EQUAL(int(result[2]), int(3));
BOOST_CHECK_EQUAL(int(result[3]), int(4));
}
/// \internal_
/// Tests for compound assignment operators that works for floating
/// point types.
#define BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name) \
BOOST_AUTO_TEST_CASE(op_name##_ca_operator_no_fp) \
{ \
float data[] = { 1, 2, 3, 4 }; \
boost::compute::valarray<float> array1(data, 4); \
boost::compute::valarray<float> array2(data, 4); \
boost::compute::system::finish(); \
\
array1 op##= 1; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(array1[0]), float(1.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[1]), float(2.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[2]), float(3.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[3]), float(4.0f op 1.0f), 1e-4f); \
\
array1 = boost::compute::valarray<float>(data, 4); \
boost::compute::system::finish(); \
\
array1 op##= array2; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(array1[0]), float(1.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[1]), float(2.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[2]), float(3.0f op 3.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array1[3]), float(4.0f op 4.0f), 1e-4f); \
\
array2 op##= array2; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(array2[0]), float(1.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array2[1]), float(2.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array2[2]), float(3.0f op 3.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(array2[3]), float(4.0f op 4.0f), 1e-4f); \
\
}
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT(+, plus)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT(-, minus)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT(*, multiplies)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT(/, divides)
#undef BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT
/// \internal_
/// Tests for compound assignment operators that does NOT work for floating
/// point types.
/// Note: modulo operator works only for integer types.
#define BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
BOOST_AUTO_TEST_CASE(op_name##_ca_operator) \
{ \
int data[] = { 1, 2, 3, 4 }; \
boost::compute::valarray<int> array1(data, 4); \
boost::compute::valarray<int> array2(data, 4); \
boost::compute::system::finish(); \
\
array1 op##= 1; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(array1[0]), int(1 op 1)); \
BOOST_CHECK_EQUAL(int(array1[1]), int(2 op 1)); \
BOOST_CHECK_EQUAL(int(array1[2]), int(3 op 1)); \
BOOST_CHECK_EQUAL(int(array1[3]), int(4 op 1)); \
\
array1 = boost::compute::valarray<int>(data, 4); \
boost::compute::system::finish(); \
\
array1 op##= array2; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(array1[0]), int(1 op 1)); \
BOOST_CHECK_EQUAL(int(array1[1]), int(2 op 2)); \
BOOST_CHECK_EQUAL(int(array1[2]), int(3 op 3)); \
BOOST_CHECK_EQUAL(int(array1[3]), int(4 op 4)); \
\
array2 op##= array2; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(array2[0]), int(1 op 1)); \
BOOST_CHECK_EQUAL(int(array2[1]), int(2 op 2)); \
BOOST_CHECK_EQUAL(int(array2[2]), int(3 op 3)); \
BOOST_CHECK_EQUAL(int(array2[3]), int(4 op 4)); \
\
}
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(%, modulus)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
#undef BOOST_COMPUTE_TEST_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
BOOST_AUTO_TEST_CASE(unary_plus_operator)
{
int data[] = { 1, 2, 3, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::system::finish();
boost::compute::valarray<int> result = +array;
boost::compute::system::finish();
BOOST_CHECK_EQUAL(int(result[0]), +(int(1)));
BOOST_CHECK_EQUAL(int(result[1]), +(int(2)));
BOOST_CHECK_EQUAL(int(result[2]), +(int(3)));
BOOST_CHECK_EQUAL(int(result[3]), +(int(4)));
}
BOOST_AUTO_TEST_CASE(unary_minus_operator)
{
int data[] = { -1, 2, 0, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::system::finish();
boost::compute::valarray<int> result = -array;
boost::compute::system::finish();
BOOST_CHECK_EQUAL(int(result[0]), int(1));
BOOST_CHECK_EQUAL(int(result[1]), int(-2));
BOOST_CHECK_EQUAL(int(result[2]), int(0));
BOOST_CHECK_EQUAL(int(result[3]), int(-4));
}
BOOST_AUTO_TEST_CASE(unary_bitwise_not_operator)
{
int data[] = { 1, 2, 3, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::system::finish();
boost::compute::valarray<int> result = ~array;
boost::compute::system::finish();
BOOST_CHECK_EQUAL(int(result[0]), ~(int(1)));
BOOST_CHECK_EQUAL(int(result[1]), ~(int(2)));
BOOST_CHECK_EQUAL(int(result[2]), ~(int(3)));
BOOST_CHECK_EQUAL(int(result[3]), ~(int(4)));
}
BOOST_AUTO_TEST_CASE(unary_logical_not_operator)
{
int data[] = { 1, -2, 0, 4 };
boost::compute::valarray<int> array(data, 4);
boost::compute::system::finish();
boost::compute::valarray<char> result = !array;
boost::compute::system::finish();
BOOST_CHECK_EQUAL(bool(result[0]), !(int(1)));
BOOST_CHECK_EQUAL(bool(result[1]), !(int(-2)));
BOOST_CHECK_EQUAL(bool(result[2]), !(int(0)));
BOOST_CHECK_EQUAL(bool(result[3]), !(int(4)));
}
/// \internal_
/// Tests for binary operators that works for floating
/// point types.
#define BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR(op, op_name) \
BOOST_AUTO_TEST_CASE(op_name##_binary_operator) \
{ \
float data1[] = { 1, 2, 3, 4 }; \
float data2[] = { 4, 2, 3, 0 }; \
boost::compute::valarray<float> array1(data1, 4); \
boost::compute::valarray<float> array2(data2, 4); \
boost::compute::system::finish(); \
\
boost::compute::valarray<float> result = 2.0f op array1; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(result[0]), float(2.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[1]), float(2.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[2]), float(2.0f op 3.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[3]), float(2.0f op 4.0f), 1e-4f); \
\
result = array1 op 2.0f; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(result[0]), float(1.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[1]), float(2.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[2]), float(3.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[3]), float(4.0f op 2.0f), 1e-4f); \
\
result = array2 op array1; \
boost::compute::system::finish(); \
BOOST_CHECK_CLOSE(float(result[0]), float(4.0f op 1.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[1]), float(2.0f op 2.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[2]), float(3.0f op 3.0f), 1e-4f); \
BOOST_CHECK_CLOSE(float(result[3]), float(0.0f op 4.0f), 1e-4f); \
}
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR(+, plus)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR(-, minus)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR(*, multiplies)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR(/, divides)
#undef BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR
/// \internal_
/// Tests for compound assignment operators that does NOT work for floating
/// point types.
/// Note: modulo operator works only for integer types.
#define BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
BOOST_AUTO_TEST_CASE(op_name##_binary_operator) \
{ \
int data1[] = { 1, 2, 3, 4 }; \
int data2[] = { 4, 5, 2, 1 }; \
boost::compute::valarray<int> array1(data1, 4); \
boost::compute::valarray<int> array2(data2, 4); \
boost::compute::system::finish(); \
\
boost::compute::valarray<int> result = 5 op array1; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(result[0]), int(5 op 1)); \
BOOST_CHECK_EQUAL(int(result[1]), int(5 op 2)); \
BOOST_CHECK_EQUAL(int(result[2]), int(5 op 3)); \
BOOST_CHECK_EQUAL(int(result[3]), int(5 op 4)); \
\
result = array1 op 5; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(result[0]), int(1 op 5)); \
BOOST_CHECK_EQUAL(int(result[1]), int(2 op 5)); \
BOOST_CHECK_EQUAL(int(result[2]), int(3 op 5)); \
BOOST_CHECK_EQUAL(int(result[3]), int(4 op 5)); \
\
result = array1 op array2; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(int(result[0]), int(1 op 4)); \
BOOST_CHECK_EQUAL(int(result[1]), int(2 op 5)); \
BOOST_CHECK_EQUAL(int(result[2]), int(3 op 2)); \
BOOST_CHECK_EQUAL(int(result[3]), int(4 op 1)); \
}
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
#undef BOOST_COMPUTE_TEST_VALARRAY_BINARY_OPERATOR_NO_FP
/// \internal_
/// Macro for generating tests for valarray comparison operators.
#define BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
BOOST_AUTO_TEST_CASE(op_name##_comparision_operator) \
{ \
int data1[] = { 1, 2, 0, 4 }; \
int data2[] = { 4, 0, 2, 1 }; \
boost::compute::valarray<int> array1(data1, 4); \
boost::compute::valarray<int> array2(data2, 4); \
boost::compute::system::finish(); \
\
boost::compute::valarray<char> result = 2 op array1; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(bool(result[0]), bool(2 op 1)); \
BOOST_CHECK_EQUAL(bool(result[1]), bool(2 op 2)); \
BOOST_CHECK_EQUAL(bool(result[2]), bool(2 op 0)); \
BOOST_CHECK_EQUAL(bool(result[3]), bool(2 op 4)); \
\
result = array1 op 2; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(bool(result[0]), bool(1 op 2)); \
BOOST_CHECK_EQUAL(bool(result[1]), bool(2 op 2)); \
BOOST_CHECK_EQUAL(bool(result[2]), bool(0 op 2)); \
BOOST_CHECK_EQUAL(bool(result[3]), bool(4 op 2)); \
\
result = array1 op array2; \
boost::compute::system::finish(); \
BOOST_CHECK_EQUAL(bool(result[0]), bool(1 op 4)); \
BOOST_CHECK_EQUAL(bool(result[1]), bool(2 op 0)); \
BOOST_CHECK_EQUAL(bool(result[2]), bool(0 op 2)); \
BOOST_CHECK_EQUAL(bool(result[3]), bool(4 op 1)); \
}
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(>, greater)
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(<, less)
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
/// \internal_
/// Macro for generating tests for valarray binary logical operators.
#define BOOST_COMPUTE_TEST_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR(op, op_name)
BOOST_COMPUTE_TEST_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
BOOST_COMPUTE_TEST_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
#undef BOOST_COMPUTE_TEST_VALARRAY_LOGICAL_OPERATOR
#undef BOOST_COMPUTE_TEST_VALARRAY_COMPARISON_OPERATOR
BOOST_AUTO_TEST_SUITE_END()