123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- //---------------------------------------------------------------------------//
- // 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://boostorg.github.com/compute for more information.
- //---------------------------------------------------------------------------//
- #define BOOST_TEST_MODULE TestTransform
- #include <boost/test/unit_test.hpp>
- #include <boost/compute/lambda.hpp>
- #include <boost/compute/system.hpp>
- #include <boost/compute/function.hpp>
- #include <boost/compute/functional.hpp>
- #include <boost/compute/algorithm/transform.hpp>
- #include <boost/compute/container/vector.hpp>
- #include <boost/compute/iterator/counting_iterator.hpp>
- #include <boost/compute/functional/field.hpp>
- #include "check_macros.hpp"
- #include "context_setup.hpp"
- namespace bc = boost::compute;
- namespace compute = boost::compute;
- BOOST_AUTO_TEST_CASE(transform_int_abs)
- {
- int data[] = { 1, -2, -3, -4, 5 };
- bc::vector<int> vector(data, data + 5, queue);
- CHECK_RANGE_EQUAL(int, 5, vector, (1, -2, -3, -4, 5));
- bc::transform(vector.begin(),
- vector.end(),
- vector.begin(),
- bc::abs<int>(),
- queue);
- CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 3, 4, 5));
- }
- BOOST_AUTO_TEST_CASE(transform_float_sqrt)
- {
- float data[] = { 1.0f, 4.0f, 9.0f, 16.0f };
- bc::vector<float> vector(data, data + 4, queue);
- CHECK_RANGE_EQUAL(float, 4, vector, (1.0f, 4.0f, 9.0f, 16.0f));
- bc::transform(vector.begin(),
- vector.end(),
- vector.begin(),
- bc::sqrt<float>(),
- queue);
- queue.finish();
- BOOST_CHECK_CLOSE(float(vector[0]), 1.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(vector[1]), 2.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(vector[2]), 3.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(vector[3]), 4.0f, 1e-4f);
- }
- BOOST_AUTO_TEST_CASE(transform_float_clamp)
- {
- float data[] = { 10.f, 20.f, 30.f, 40.f, 50.f };
- bc::vector<float> vector(data, data + 5, queue);
- CHECK_RANGE_EQUAL(float, 5, vector, (10.0f, 20.0f, 30.0f, 40.0f, 50.0f));
- bc::transform(vector.begin(),
- vector.end(),
- vector.begin(),
- clamp(bc::_1, 15.f, 45.f),
- queue);
- CHECK_RANGE_EQUAL(float, 5, vector, (15.0f, 20.0f, 30.0f, 40.0f, 45.0f));
- }
- BOOST_AUTO_TEST_CASE(transform_add_int)
- {
- int data1[] = { 1, 2, 3, 4 };
- bc::vector<int> input1(data1, data1 + 4, queue);
- int data2[] = { 10, 20, 30, 40 };
- bc::vector<int> input2(data2, data2 + 4, queue);
- bc::vector<int> output(4, context);
- bc::transform(input1.begin(),
- input1.end(),
- input2.begin(),
- output.begin(),
- bc::plus<int>(),
- queue);
- CHECK_RANGE_EQUAL(int, 4, output, (11, 22, 33, 44));
- bc::transform(input1.begin(),
- input1.end(),
- input2.begin(),
- output.begin(),
- bc::multiplies<int>(),
- queue);
- CHECK_RANGE_EQUAL(int, 4, output, (10, 40, 90, 160));
- }
- BOOST_AUTO_TEST_CASE(transform_pow4)
- {
- float data[] = { 1.0f, 2.0f, 3.0f, 4.0f };
- bc::vector<float> vector(data, data + 4, queue);
- CHECK_RANGE_EQUAL(float, 4, vector, (1.0f, 2.0f, 3.0f, 4.0f));
- bc::vector<float> result(4, context);
- bc::transform(vector.begin(),
- vector.end(),
- result.begin(),
- pown(bc::_1, 4),
- queue);
- queue.finish();
- BOOST_CHECK_CLOSE(float(result[0]), 1.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[1]), 16.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[2]), 81.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[3]), 256.0f, 1e-4f);
- }
- BOOST_AUTO_TEST_CASE(transform_custom_function)
- {
- float data[] = { 9.0f, 7.0f, 5.0f, 3.0f };
- bc::vector<float> vector(data, data + 4, queue);
- BOOST_COMPUTE_FUNCTION(float, pow3add4, (float x),
- {
- return pow(x, 3.0f) + 4.0f;
- });
- bc::vector<float> result(4, context);
- bc::transform(vector.begin(),
- vector.end(),
- result.begin(),
- pow3add4,
- queue);
- queue.finish();
- BOOST_CHECK_CLOSE(float(result[0]), 733.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[1]), 347.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[2]), 129.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(result[3]), 31.0f, 1e-4f);
- }
- BOOST_AUTO_TEST_CASE(extract_vector_component)
- {
- using bc::int2_;
- int data[] = { 1, 2,
- 3, 4,
- 5, 6,
- 7, 8 };
- bc::vector<int2_> vector(
- reinterpret_cast<int2_ *>(data),
- reinterpret_cast<int2_ *>(data) + 4,
- queue
- );
- CHECK_RANGE_EQUAL(
- int2_, 4, vector,
- (int2_(1, 2), int2_(3, 4), int2_(5, 6), int2_(7, 8))
- );
- bc::vector<int> x_components(4, context);
- bc::transform(vector.begin(),
- vector.end(),
- x_components.begin(),
- bc::get<0>(),
- queue);
- CHECK_RANGE_EQUAL(int, 4, x_components, (1, 3, 5, 7));
- bc::vector<int> y_components(4, context);
- bc::transform(vector.begin(),
- vector.end(),
- y_components.begin(),
- bc::get<1>(),
- queue);
- CHECK_RANGE_EQUAL(int, 4, y_components, (2, 4, 6, 8));
- }
- BOOST_AUTO_TEST_CASE(transform_pinned_vector)
- {
- int data[] = { 2, -3, 4, -5, 6, -7 };
- std::vector<int> vector(data, data + 6);
- bc::buffer buffer(context,
- vector.size() * sizeof(int),
- bc::buffer::read_write | bc::buffer::use_host_ptr,
- &vector[0]);
- bc::transform(bc::make_buffer_iterator<int>(buffer, 0),
- bc::make_buffer_iterator<int>(buffer, 6),
- bc::make_buffer_iterator<int>(buffer, 0),
- bc::abs<int>(),
- queue);
- void *ptr = queue.enqueue_map_buffer(buffer,
- bc::command_queue::map_read,
- 0,
- buffer.size());
- BOOST_VERIFY(ptr == &vector[0]);
- BOOST_CHECK_EQUAL(vector[0], 2);
- BOOST_CHECK_EQUAL(vector[1], 3);
- BOOST_CHECK_EQUAL(vector[2], 4);
- BOOST_CHECK_EQUAL(vector[3], 5);
- BOOST_CHECK_EQUAL(vector[4], 6);
- BOOST_CHECK_EQUAL(vector[5], 7);
- queue.enqueue_unmap_buffer(buffer, ptr);
- }
- BOOST_AUTO_TEST_CASE(transform_popcount)
- {
- using boost::compute::uint_;
- uint_ data[] = { 0, 1, 2, 3, 4, 45, 127, 5000, 789, 15963 };
- bc::vector<uint_> input(data, data + 10, queue);
- bc::vector<uint_> output(input.size(), context);
- bc::transform(
- input.begin(),
- input.end(),
- output.begin(),
- bc::popcount<uint_>(),
- queue
- );
- CHECK_RANGE_EQUAL(uint_, 10, output, (0, 1, 1, 2, 1, 4, 7, 5, 5, 10));
- }
- // generates the first 25 fibonacci numbers in parallel using the
- // rounding-based fibonacci formula
- BOOST_AUTO_TEST_CASE(generate_fibonacci_sequence)
- {
- using boost::compute::uint_;
- boost::compute::vector<uint_> sequence(25, context);
- BOOST_COMPUTE_FUNCTION(uint_, nth_fibonacci, (const uint_ n),
- {
- const float golden_ratio = (1.f + sqrt(5.f)) / 2.f;
- return floor(pown(golden_ratio, n) / sqrt(5.f) + 0.5f);
- });
- boost::compute::transform(
- boost::compute::make_counting_iterator(uint_(0)),
- boost::compute::make_counting_iterator(uint_(sequence.size())),
- sequence.begin(),
- nth_fibonacci,
- queue
- );
- CHECK_RANGE_EQUAL(
- uint_, 25, sequence,
- (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610,
- 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368)
- );
- }
- BOOST_AUTO_TEST_CASE(field)
- {
- using compute::uint2_;
- using compute::uint4_;
- using compute::field;
- unsigned int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
- compute::vector<uint4_> input(
- reinterpret_cast<uint4_ *>(data),
- reinterpret_cast<uint4_ *>(data) + 2,
- queue
- );
- compute::vector<uint2_> output(input.size(), context);
- compute::transform(
- input.begin(),
- input.end(),
- output.begin(),
- compute::field<uint2_>("xz"),
- queue
- );
- queue.finish();
- BOOST_CHECK_EQUAL(uint2_(output[0]), uint2_(1, 3));
- BOOST_CHECK_EQUAL(uint2_(output[1]), uint2_(5, 7));
- }
- BOOST_AUTO_TEST_CASE(transform_abs_doctest)
- {
- //! [transform_abs]
- int data[] = { -1, -2, -3, -4 };
- boost::compute::vector<int> vec(data, data + 4, queue);
- using boost::compute::abs;
- // calculate the absolute value for each element in-place
- boost::compute::transform(
- vec.begin(), vec.end(), vec.begin(), abs<int>(), queue
- );
- // vec == { 1, 2, 3, 4 }
- //! [transform_abs]
- CHECK_RANGE_EQUAL(int, 4, vec, (1, 2, 3, 4));
- }
- BOOST_AUTO_TEST_CASE(abs_if_odd)
- {
- // return absolute value only for odd values
- BOOST_COMPUTE_FUNCTION(int, abs_if_odd, (int x),
- {
- if(x & 1){
- return abs(x);
- }
- else {
- return x;
- }
- });
- int data[] = { -2, -3, -4, -5, -6, -7, -8, -9 };
- compute::vector<int> vector(data, data + 8, queue);
- compute::transform(
- vector.begin(), vector.end(), vector.begin(), abs_if_odd, queue
- );
- CHECK_RANGE_EQUAL(int, 8, vector, (-2, +3, -4, +5, -6, +7, -8, +9));
- }
- BOOST_AUTO_TEST_SUITE_END()
|