summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/compute/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/compute/test')
-rw-r--r--src/boost/libs/compute/test/CMakeLists.txt236
-rw-r--r--src/boost/libs/compute/test/Jamfile.v249
-rw-r--r--src/boost/libs/compute/test/check/has_opencl.cpp11
-rw-r--r--src/boost/libs/compute/test/check_macros.hpp84
-rw-r--r--src/boost/libs/compute/test/context_setup.hpp33
-rw-r--r--src/boost/libs/compute/test/data/invalid_program.cl10
-rw-r--r--src/boost/libs/compute/test/data/program.cl15
-rw-r--r--src/boost/libs/compute/test/data/program.spirv32bin0 -> 472 bytes
-rw-r--r--src/boost/libs/compute/test/data/program.spirv64bin0 -> 528 bytes
-rw-r--r--src/boost/libs/compute/test/extra/CMakeLists.txt81
-rw-r--r--src/boost/libs/compute/test/extra/test_interop_eigen.cpp106
-rw-r--r--src/boost/libs/compute/test/extra/test_interop_opencv.cpp105
-rw-r--r--src/boost/libs/compute/test/extra/test_interop_opengl.cpp28
-rw-r--r--src/boost/libs/compute/test/extra/test_interop_qt.cpp95
-rw-r--r--src/boost/libs/compute/test/extra/test_interop_vtk.cpp118
-rw-r--r--src/boost/libs/compute/test/extra/test_multiple_objects1.cpp21
-rw-r--r--src/boost/libs/compute/test/extra/test_multiple_objects2.cpp15
-rw-r--r--src/boost/libs/compute/test/opencl_version_check.hpp20
-rw-r--r--src/boost/libs/compute/test/quirks.hpp128
-rw-r--r--src/boost/libs/compute/test/test_accumulate.cpp302
-rw-r--r--src/boost/libs/compute/test/test_adjacent_difference.cpp102
-rw-r--r--src/boost/libs/compute/test/test_adjacent_find.cpp68
-rw-r--r--src/boost/libs/compute/test/test_amd_cpp_kernel_language.cpp68
-rw-r--r--src/boost/libs/compute/test/test_any_all_none_of.cpp89
-rw-r--r--src/boost/libs/compute/test/test_array.cpp87
-rw-r--r--src/boost/libs/compute/test/test_async_wait.cpp72
-rw-r--r--src/boost/libs/compute/test/test_async_wait_guard.cpp51
-rw-r--r--src/boost/libs/compute/test/test_bernoulli_distribution.cpp39
-rw-r--r--src/boost/libs/compute/test/test_binary_search.cpp102
-rw-r--r--src/boost/libs/compute/test/test_buffer.cpp213
-rw-r--r--src/boost/libs/compute/test/test_buffer_allocator.cpp29
-rw-r--r--src/boost/libs/compute/test/test_buffer_iterator.cpp69
-rw-r--r--src/boost/libs/compute/test/test_clamp_range.cpp43
-rw-r--r--src/boost/libs/compute/test/test_closure.cpp223
-rw-r--r--src/boost/libs/compute/test/test_command_queue.cpp352
-rw-r--r--src/boost/libs/compute/test/test_complex.cpp173
-rw-r--r--src/boost/libs/compute/test/test_constant_iterator.cpp96
-rw-r--r--src/boost/libs/compute/test/test_context.cpp67
-rw-r--r--src/boost/libs/compute/test/test_context_error.cpp25
-rw-r--r--src/boost/libs/compute/test/test_copy.cpp411
-rw-r--r--src/boost/libs/compute/test/test_copy_if.cpp119
-rw-r--r--src/boost/libs/compute/test/test_copy_type_mismatch.cpp1380
-rw-r--r--src/boost/libs/compute/test/test_count.cpp221
-rw-r--r--src/boost/libs/compute/test/test_counting_iterator.cpp100
-rw-r--r--src/boost/libs/compute/test/test_device.cpp293
-rw-r--r--src/boost/libs/compute/test/test_discard_iterator.cpp94
-rw-r--r--src/boost/libs/compute/test/test_discrete_distribution.cpp237
-rw-r--r--src/boost/libs/compute/test/test_dynamic_bitset.cpp96
-rw-r--r--src/boost/libs/compute/test/test_equal.cpp61
-rw-r--r--src/boost/libs/compute/test/test_equal_range.cpp73
-rw-r--r--src/boost/libs/compute/test/test_event.cpp143
-rw-r--r--src/boost/libs/compute/test/test_extents.cpp100
-rw-r--r--src/boost/libs/compute/test/test_extrema.cpp396
-rw-r--r--src/boost/libs/compute/test/test_fill.cpp333
-rw-r--r--src/boost/libs/compute/test/test_find.cpp107
-rw-r--r--src/boost/libs/compute/test/test_find_end.cpp63
-rw-r--r--src/boost/libs/compute/test/test_flat_map.cpp147
-rw-r--r--src/boost/libs/compute/test/test_flat_set.cpp136
-rw-r--r--src/boost/libs/compute/test/test_for_each.cpp46
-rw-r--r--src/boost/libs/compute/test/test_function.cpp209
-rw-r--r--src/boost/libs/compute/test/test_function_input_iterator.cpp50
-rw-r--r--src/boost/libs/compute/test/test_functional_as.cpp59
-rw-r--r--src/boost/libs/compute/test/test_functional_bind.cpp237
-rw-r--r--src/boost/libs/compute/test/test_functional_convert.cpp44
-rw-r--r--src/boost/libs/compute/test/test_functional_get.cpp83
-rw-r--r--src/boost/libs/compute/test/test_functional_hash.cpp42
-rw-r--r--src/boost/libs/compute/test/test_functional_identity.cpp39
-rw-r--r--src/boost/libs/compute/test/test_functional_popcount.cpp42
-rw-r--r--src/boost/libs/compute/test/test_functional_unpack.cpp99
-rw-r--r--src/boost/libs/compute/test/test_gather.cpp71
-rw-r--r--src/boost/libs/compute/test/test_generate.cpp71
-rw-r--r--src/boost/libs/compute/test/test_image1d.cpp70
-rw-r--r--src/boost/libs/compute/test/test_image2d.cpp226
-rw-r--r--src/boost/libs/compute/test/test_image3d.cpp37
-rw-r--r--src/boost/libs/compute/test/test_image_sampler.cpp65
-rw-r--r--src/boost/libs/compute/test/test_includes.cpp60
-rw-r--r--src/boost/libs/compute/test/test_inner_product.cpp53
-rw-r--r--src/boost/libs/compute/test/test_inplace_merge.cpp47
-rw-r--r--src/boost/libs/compute/test/test_inplace_reduce.cpp138
-rw-r--r--src/boost/libs/compute/test/test_insertion_sort.cpp171
-rw-r--r--src/boost/libs/compute/test/test_invoke.cpp59
-rw-r--r--src/boost/libs/compute/test/test_iota.cpp90
-rw-r--r--src/boost/libs/compute/test/test_is_permutation.cpp71
-rw-r--r--src/boost/libs/compute/test/test_is_sorted.cpp71
-rw-r--r--src/boost/libs/compute/test/test_kernel.cpp335
-rw-r--r--src/boost/libs/compute/test/test_lambda.cpp617
-rw-r--r--src/boost/libs/compute/test/test_lexicographical_compare.cpp75
-rw-r--r--src/boost/libs/compute/test/test_linear_congruential_engine.cpp120
-rw-r--r--src/boost/libs/compute/test/test_literal_conversion.cpp72
-rw-r--r--src/boost/libs/compute/test/test_local_buffer.cpp80
-rw-r--r--src/boost/libs/compute/test/test_malloc.cpp40
-rw-r--r--src/boost/libs/compute/test/test_mapped_view.cpp70
-rw-r--r--src/boost/libs/compute/test/test_merge.cpp167
-rw-r--r--src/boost/libs/compute/test/test_merge_sort_gpu.cpp374
-rw-r--r--src/boost/libs/compute/test/test_mersenne_twister_engine.cpp120
-rw-r--r--src/boost/libs/compute/test/test_mismatch.cpp64
-rw-r--r--src/boost/libs/compute/test/test_next_permutation.cpp71
-rw-r--r--src/boost/libs/compute/test/test_no_device_found.cpp31
-rw-r--r--src/boost/libs/compute/test/test_normal_distribution.cpp84
-rw-r--r--src/boost/libs/compute/test/test_nth_element.cpp113
-rw-r--r--src/boost/libs/compute/test/test_opencl_error.cpp35
-rw-r--r--src/boost/libs/compute/test/test_pair.cpp194
-rw-r--r--src/boost/libs/compute/test/test_partial_sum.cpp41
-rw-r--r--src/boost/libs/compute/test/test_partition.cpp82
-rw-r--r--src/boost/libs/compute/test/test_partition_point.cpp38
-rw-r--r--src/boost/libs/compute/test/test_permutation_iterator.cpp110
-rw-r--r--src/boost/libs/compute/test/test_pinned_allocator.cpp27
-rw-r--r--src/boost/libs/compute/test/test_pipe.cpp36
-rw-r--r--src/boost/libs/compute/test/test_platform.cpp45
-rw-r--r--src/boost/libs/compute/test/test_prev_permutation.cpp71
-rw-r--r--src/boost/libs/compute/test/test_program.cpp401
-rw-r--r--src/boost/libs/compute/test/test_program_cache.cpp99
-rw-r--r--src/boost/libs/compute/test/test_radix_sort.cpp543
-rw-r--r--src/boost/libs/compute/test/test_radix_sort_by_key.cpp311
-rw-r--r--src/boost/libs/compute/test/test_random_fill.cpp76
-rw-r--r--src/boost/libs/compute/test/test_random_shuffle.cpp54
-rw-r--r--src/boost/libs/compute/test/test_reduce.cpp298
-rw-r--r--src/boost/libs/compute/test/test_reduce_by_key.cpp210
-rw-r--r--src/boost/libs/compute/test/test_remove.cpp55
-rw-r--r--src/boost/libs/compute/test/test_replace.cpp53
-rw-r--r--src/boost/libs/compute/test/test_result_of.cpp40
-rw-r--r--src/boost/libs/compute/test/test_reverse.cpp93
-rw-r--r--src/boost/libs/compute/test/test_rotate.cpp69
-rw-r--r--src/boost/libs/compute/test/test_rotate_copy.cpp73
-rw-r--r--src/boost/libs/compute/test/test_scan.cpp490
-rw-r--r--src/boost/libs/compute/test/test_scatter.cpp57
-rw-r--r--src/boost/libs/compute/test/test_scatter_if.cpp141
-rw-r--r--src/boost/libs/compute/test/test_search.cpp72
-rw-r--r--src/boost/libs/compute/test/test_search_n.cpp56
-rw-r--r--src/boost/libs/compute/test/test_set_difference.cpp62
-rw-r--r--src/boost/libs/compute/test/test_set_intersection.cpp62
-rw-r--r--src/boost/libs/compute/test/test_set_symmetric_difference.cpp63
-rw-r--r--src/boost/libs/compute/test/test_set_union.cpp64
-rw-r--r--src/boost/libs/compute/test/test_sort.cpp367
-rw-r--r--src/boost/libs/compute/test/test_sort_by_key.cpp207
-rw-r--r--src/boost/libs/compute/test/test_sort_by_transform.cpp110
-rw-r--r--src/boost/libs/compute/test/test_stable_partition.cpp38
-rw-r--r--src/boost/libs/compute/test/test_stable_sort.cpp92
-rw-r--r--src/boost/libs/compute/test/test_stable_sort_by_key.cpp206
-rw-r--r--src/boost/libs/compute/test/test_stack.cpp50
-rw-r--r--src/boost/libs/compute/test/test_strided_iterator.cpp194
-rw-r--r--src/boost/libs/compute/test/test_string.cpp89
-rw-r--r--src/boost/libs/compute/test/test_struct.cpp165
-rw-r--r--src/boost/libs/compute/test/test_svm_ptr.cpp156
-rw-r--r--src/boost/libs/compute/test/test_system.cpp38
-rw-r--r--src/boost/libs/compute/test/test_tabulate.cpp37
-rw-r--r--src/boost/libs/compute/test/test_threefry_engine.cpp87
-rw-r--r--src/boost/libs/compute/test/test_transform.cpp324
-rw-r--r--src/boost/libs/compute/test/test_transform_if.cpp40
-rw-r--r--src/boost/libs/compute/test/test_transform_iterator.cpp108
-rw-r--r--src/boost/libs/compute/test/test_transform_reduce.cpp101
-rw-r--r--src/boost/libs/compute/test/test_tuple.cpp141
-rw-r--r--src/boost/libs/compute/test/test_type_traits.cpp131
-rw-r--r--src/boost/libs/compute/test/test_types.cpp97
-rw-r--r--src/boost/libs/compute/test/test_uniform_int_distribution.cpp77
-rw-r--r--src/boost/libs/compute/test/test_uniform_real_distribution.cpp105
-rw-r--r--src/boost/libs/compute/test/test_unique.cpp96
-rw-r--r--src/boost/libs/compute/test/test_unique_copy.cpp37
-rw-r--r--src/boost/libs/compute/test/test_unsupported_extension.cpp18
-rw-r--r--src/boost/libs/compute/test/test_user_defined_types.cpp122
-rw-r--r--src/boost/libs/compute/test/test_user_event.cpp35
-rw-r--r--src/boost/libs/compute/test/test_valarray.cpp361
-rw-r--r--src/boost/libs/compute/test/test_vector.cpp502
-rw-r--r--src/boost/libs/compute/test/test_wait_list.cpp82
-rw-r--r--src/boost/libs/compute/test/test_zip_iterator.cpp232
165 files changed, 21184 insertions, 0 deletions
diff --git a/src/boost/libs/compute/test/CMakeLists.txt b/src/boost/libs/compute/test/CMakeLists.txt
new file mode 100644
index 00000000..1aa99ff9
--- /dev/null
+++ b/src/boost/libs/compute/test/CMakeLists.txt
@@ -0,0 +1,236 @@
+# ---------------------------------------------------------------------------
+# 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
+#
+# ---------------------------------------------------------------------------
+
+include_directories(../include)
+
+set(BOOST_COMPONENTS unit_test_framework)
+
+if(${BOOST_COMPUTE_USE_CPP11})
+ # allow tests to use C++11 features
+ add_definitions(-DBOOST_COMPUTE_USE_CPP11)
+endif()
+
+if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
+ set(BOOST_COMPONENTS ${BOOST_COMPONENTS} system filesystem)
+ add_definitions(-DBOOST_COMPUTE_USE_OFFLINE_CACHE)
+endif()
+
+if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
+ set(BOOST_COMPONENTS ${BOOST_COMPONENTS} system thread)
+endif()
+
+if(MSVC AND BOOST_COMPONENTS)
+ set(BOOST_COMPONENTS ${BOOST_COMPONENTS} chrono)
+endif()
+
+if(BOOST_COMPONENTS)
+ list(REMOVE_DUPLICATES BOOST_COMPONENTS)
+endif()
+find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
+
+if(NOT MSVC)
+ add_definitions(-DBOOST_TEST_DYN_LINK)
+else()
+ if(MSVC AND ${BOOST_COMPUTE_BOOST_ALL_DYN_LINK})
+ add_definitions(-DBOOST_TEST_DYN_LINK)
+ endif()
+endif()
+
+# enable automatic kernel compilation error messages for tests
+add_definitions(-DBOOST_COMPUTE_DEBUG_KERNEL_COMPILATION)
+
+# enable code coverage generation (only with GCC for now)
+if(${BOOST_COMPUTE_ENABLE_COVERAGE} AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
+ add_definitions(-fprofile-arcs -ftest-coverage)
+endif()
+
+# add path to test data dir
+add_definitions(-DBOOST_COMPUTE_TEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/data")
+
+function(add_compute_test TEST_NAME TEST_SOURCE)
+ get_filename_component(TEST_TARGET ${TEST_SOURCE} NAME_WE)
+ add_executable(${TEST_TARGET} ${TEST_SOURCE})
+ target_link_libraries(${TEST_TARGET}
+ ${OpenCL_LIBRARIES}
+ ${Boost_LIBRARIES}
+ )
+
+ # link with coverage library
+ if(${BOOST_COMPUTE_ENABLE_COVERAGE} AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
+ target_link_libraries(${TEST_TARGET} -fprofile-arcs -ftest-coverage)
+ endif()
+
+ add_test(${TEST_NAME} ${TEST_TARGET})
+endfunction()
+
+add_compute_test("core.buffer" test_buffer.cpp)
+add_compute_test("core.closure" test_closure.cpp)
+add_compute_test("core.command_queue" test_command_queue.cpp)
+add_compute_test("core.context" test_context.cpp)
+add_compute_test("core.device" test_device.cpp)
+add_compute_test("core.event" test_event.cpp)
+add_compute_test("core.function" test_function.cpp)
+add_compute_test("core.kernel" test_kernel.cpp)
+add_compute_test("core.pipe" test_pipe.cpp)
+add_compute_test("core.platform" test_platform.cpp)
+add_compute_test("core.program" test_program.cpp)
+add_compute_test("core.system" test_system.cpp)
+add_compute_test("core.type_traits" test_type_traits.cpp)
+add_compute_test("core.user_event" test_user_event.cpp)
+
+add_compute_test("utility.extents" test_extents.cpp)
+add_compute_test("utility.invoke" test_invoke.cpp)
+add_compute_test("utility.program_cache" test_program_cache.cpp)
+add_compute_test("utility.wait_list" test_wait_list.cpp)
+
+add_compute_test("algorithm.accumulate" test_accumulate.cpp)
+add_compute_test("algorithm.adjacent_difference" test_adjacent_difference.cpp)
+add_compute_test("algorithm.adjacent_find" test_adjacent_find.cpp)
+add_compute_test("algorithm.any_all_none_of" test_any_all_none_of.cpp)
+add_compute_test("algorithm.binary_search" test_binary_search.cpp)
+add_compute_test("algorithm.copy" test_copy.cpp)
+add_compute_test("algorithm.copy_type_mismatch" test_copy_type_mismatch.cpp)
+add_compute_test("algorithm.copy_if" test_copy_if.cpp)
+add_compute_test("algorithm.count" test_count.cpp)
+add_compute_test("algorithm.equal" test_equal.cpp)
+add_compute_test("algorithm.equal_range" test_equal_range.cpp)
+add_compute_test("algorithm.extrema" test_extrema.cpp)
+add_compute_test("algorithm.fill" test_fill.cpp)
+add_compute_test("algorithm.find" test_find.cpp)
+add_compute_test("algorithm.find_end" test_find_end.cpp)
+add_compute_test("algorithm.for_each" test_for_each.cpp)
+add_compute_test("algorithm.gather" test_gather.cpp)
+add_compute_test("algorithm.generate" test_generate.cpp)
+add_compute_test("algorithm.includes" test_includes.cpp)
+add_compute_test("algorithm.inner_product" test_inner_product.cpp)
+add_compute_test("algorithm.inplace_merge" test_inplace_merge.cpp)
+add_compute_test("algorithm.inplace_reduce" test_inplace_reduce.cpp)
+add_compute_test("algorithm.insertion_sort" test_insertion_sort.cpp)
+add_compute_test("algorithm.iota" test_iota.cpp)
+add_compute_test("algorithm.is_permutation" test_is_permutation.cpp)
+add_compute_test("algorithm.is_sorted" test_is_sorted.cpp)
+add_compute_test("algorithm.merge_sort_gpu" test_merge_sort_gpu.cpp)
+add_compute_test("algorithm.merge" test_merge.cpp)
+add_compute_test("algorithm.mismatch" test_mismatch.cpp)
+add_compute_test("algorithm.next_permutation" test_next_permutation.cpp)
+add_compute_test("algorithm.nth_element" test_nth_element.cpp)
+add_compute_test("algorithm.partial_sum" test_partial_sum.cpp)
+add_compute_test("algorithm.partition" test_partition.cpp)
+add_compute_test("algorithm.partition_point" test_partition_point.cpp)
+add_compute_test("algorithm.prev_permutation" test_prev_permutation.cpp)
+add_compute_test("algorithm.radix_sort" test_radix_sort.cpp)
+add_compute_test("algorithm.radix_sort_by_key" test_radix_sort_by_key.cpp)
+add_compute_test("algorithm.random_fill" test_random_fill.cpp)
+add_compute_test("algorithm.random_shuffle" test_random_shuffle.cpp)
+add_compute_test("algorithm.reduce" test_reduce.cpp)
+add_compute_test("algorithm.reduce_by_key" test_reduce_by_key.cpp)
+add_compute_test("algorithm.remove" test_remove.cpp)
+add_compute_test("algorithm.replace" test_replace.cpp)
+add_compute_test("algorithm.reverse" test_reverse.cpp)
+add_compute_test("algorithm.rotate" test_rotate.cpp)
+add_compute_test("algorithm.rotate_copy" test_rotate_copy.cpp)
+add_compute_test("algorithm.scan" test_scan.cpp)
+add_compute_test("algorithm.scatter" test_scatter.cpp)
+add_compute_test("algorithm.scatter_if" test_scatter_if.cpp)
+add_compute_test("algorithm.search" test_search.cpp)
+add_compute_test("algorithm.search_n" test_search_n.cpp)
+add_compute_test("algorithm.set_difference" test_set_difference.cpp)
+add_compute_test("algorithm.set_intersection" test_set_intersection.cpp)
+add_compute_test("algorithm.set_symmetric_difference" test_set_symmetric_difference.cpp)
+add_compute_test("algorithm.set_union" test_set_union.cpp)
+add_compute_test("algorithm.sort" test_sort.cpp)
+add_compute_test("algorithm.sort_by_key" test_sort_by_key.cpp)
+add_compute_test("algorithm.stable_partition" test_stable_partition.cpp)
+add_compute_test("algorithm.stable_sort" test_stable_sort.cpp)
+add_compute_test("algorithm.stable_sort_by_key" test_stable_sort_by_key.cpp)
+add_compute_test("algorithm.transform" test_transform.cpp)
+add_compute_test("algorithm.transform_if" test_transform_if.cpp)
+add_compute_test("algorithm.transform_reduce" test_transform_reduce.cpp)
+add_compute_test("algorithm.unique" test_unique.cpp)
+add_compute_test("algorithm.unique_copy" test_unique_copy.cpp)
+add_compute_test("algorithm.lexicographical_compare" test_lexicographical_compare.cpp)
+
+add_compute_test("allocator.buffer_allocator" test_buffer_allocator.cpp)
+add_compute_test("allocator.pinned_allocator" test_pinned_allocator.cpp)
+
+add_compute_test("async.wait" test_async_wait.cpp)
+add_compute_test("async.wait_guard" test_async_wait_guard.cpp)
+
+add_compute_test("container.array" test_array.cpp)
+add_compute_test("container.dynamic_bitset" test_dynamic_bitset.cpp)
+add_compute_test("container.flat_map" test_flat_map.cpp)
+add_compute_test("container.flat_set" test_flat_set.cpp)
+add_compute_test("container.mapped_view" test_mapped_view.cpp)
+add_compute_test("container.stack" test_stack.cpp)
+add_compute_test("container.string" test_string.cpp)
+add_compute_test("container.valarray" test_valarray.cpp)
+add_compute_test("container.vector" test_vector.cpp)
+
+add_compute_test("exception.context_error" test_context_error.cpp)
+add_compute_test("exception.no_device_found" test_no_device_found.cpp)
+add_compute_test("exception.opencl_error" test_opencl_error.cpp)
+add_compute_test("exception.unsupported_extension" test_unsupported_extension.cpp)
+
+add_compute_test("functional.as" test_functional_as.cpp)
+add_compute_test("functional.bind" test_functional_bind.cpp)
+add_compute_test("functional.convert" test_functional_convert.cpp)
+add_compute_test("functional.get" test_functional_get.cpp)
+add_compute_test("functional.hash" test_functional_hash.cpp)
+add_compute_test("functional.identity" test_functional_identity.cpp)
+add_compute_test("functional.popcount" test_functional_popcount.cpp)
+add_compute_test("functional.unpack" test_functional_unpack.cpp)
+
+add_compute_test("image.image1d" test_image1d.cpp)
+add_compute_test("image.image2d" test_image2d.cpp)
+add_compute_test("image.image3d" test_image3d.cpp)
+add_compute_test("image.image_sampler" test_image_sampler.cpp)
+
+add_compute_test("iterator.buffer_iterator" test_buffer_iterator.cpp)
+add_compute_test("iterator.constant_iterator" test_constant_iterator.cpp)
+add_compute_test("iterator.counting_iterator" test_counting_iterator.cpp)
+add_compute_test("iterator.discard_iterator" test_discard_iterator.cpp)
+add_compute_test("iterator.function_input_iterator" test_function_input_iterator.cpp)
+add_compute_test("iterator.permutation_iterator" test_permutation_iterator.cpp)
+add_compute_test("iterator.strided_iterator" test_strided_iterator.cpp)
+add_compute_test("iterator.transform_iterator" test_transform_iterator.cpp)
+add_compute_test("iterator.zip_iterator" test_zip_iterator.cpp)
+
+add_compute_test("memory.local_buffer" test_local_buffer.cpp)
+add_compute_test("memory.svm_ptr" test_svm_ptr.cpp)
+
+add_compute_test("random.bernoulli_distribution" test_bernoulli_distribution.cpp)
+add_compute_test("random.discrete_distribution" test_discrete_distribution.cpp)
+add_compute_test("random.linear_congruential_engine" test_linear_congruential_engine.cpp)
+add_compute_test("random.mersenne_twister_engine" test_mersenne_twister_engine.cpp)
+add_compute_test("random.threefry_engine" test_threefry_engine.cpp)
+add_compute_test("random.normal_distribution" test_normal_distribution.cpp)
+add_compute_test("random.uniform_int_distribution" test_uniform_int_distribution.cpp)
+add_compute_test("random.uniform_real_distribution" test_uniform_real_distribution.cpp)
+
+add_compute_test("types.fundamental" test_types.cpp)
+add_compute_test("types.complex" test_complex.cpp)
+add_compute_test("types.pair" test_pair.cpp)
+add_compute_test("types.tuple" test_tuple.cpp)
+add_compute_test("types.struct" test_struct.cpp)
+
+add_compute_test("type_traits.result_of" test_result_of.cpp)
+
+add_compute_test("experimental.clamp_range" test_clamp_range.cpp)
+add_compute_test("experimental.malloc" test_malloc.cpp)
+add_compute_test("experimental.sort_by_transform" test_sort_by_transform.cpp)
+add_compute_test("experimental.tabulate" test_tabulate.cpp)
+
+# miscellaneous tests
+add_compute_test("misc.amd_cpp_kernel_language" test_amd_cpp_kernel_language.cpp)
+add_compute_test("misc.lambda" test_lambda.cpp)
+add_compute_test("misc.user_defined_types" test_user_defined_types.cpp)
+add_compute_test("misc.literal_conversion" test_literal_conversion.cpp)
+
+# extra tests (interop tests, linkage tests, etc.)
+add_subdirectory(extra)
diff --git a/src/boost/libs/compute/test/Jamfile.v2 b/src/boost/libs/compute/test/Jamfile.v2
new file mode 100644
index 00000000..f1a6bfe5
--- /dev/null
+++ b/src/boost/libs/compute/test/Jamfile.v2
@@ -0,0 +1,49 @@
+# (C) Copyright 2015: Kyle Lutz
+# 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)
+
+import testing ;
+
+lib boost_unit_test_framework ;
+
+obj has_opencl : check/has_opencl.cpp ;
+explicit has_opencl ;
+
+project
+ : source-location .
+ : requirements
+ <define>BOOST_ALL_NO_LIB=1
+ <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
+ <toolset>msvc:<define>NOMINMAX
+ <toolset>msvc:<cxxflags>/wd4003 # Not enough actual parameters for a BOOST_PP macro
+ <toolset>msvc:<cxxflags>/wd4244 # Warning C4244: 'initializing': conversion from 'double' to 'int', possible loss of data
+ <toolset>msvc:<cxxflags>/wd4305 # Warning C4305: 'initializing': truncation from 'double' to 'float'
+ <toolset>msvc:<cxxflags>/wd4800 # Warning C4800: 'uint32_t' : forcing value to bool 'true' or 'false' (performance warning)
+ <toolset>msvc:<cxxflags>/wd4838 # Warning C4838: conversion from 'double' to 'float' requires a narrowing conversion
+ <library>/boost/test//boost_unit_test_framework
+
+ [ check-target-builds has_opencl "OpenCL" : : <build>no ]
+ ;
+
+rule test_all
+{
+ local all_rules = ;
+
+ for local fileb in [ glob *.cpp ]
+ {
+ all_rules += [ run $(fileb)
+ :
+ :
+ :
+ <link>shared:<define>BOOST_TEST_DYN_LINK=1
+ <host-os>linux:<linkflags>"-lOpenCL"
+ <host-os>darwin:<linkflags>"-framework OpenCL"
+ <host-os>freebsd:<linkflags>"-lOpenCL"
+ ] ;
+ }
+
+ return $(all_rules) ;
+}
+
+test-suite compute : [ test_all r ] : ;
diff --git a/src/boost/libs/compute/test/check/has_opencl.cpp b/src/boost/libs/compute/test/check/has_opencl.cpp
new file mode 100644
index 00000000..10769d2b
--- /dev/null
+++ b/src/boost/libs/compute/test/check/has_opencl.cpp
@@ -0,0 +1,11 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017 Kohei Takahashi
+//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <boost/compute/cl.hpp>
diff --git a/src/boost/libs/compute/test/check_macros.hpp b/src/boost/libs/compute/test/check_macros.hpp
new file mode 100644
index 00000000..f3e609ed
--- /dev/null
+++ b/src/boost/libs/compute/test/check_macros.hpp
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TEST_CHECK_MACROS_HPP
+#define BOOST_COMPUTE_TEST_CHECK_MACROS_HPP
+
+#define LIST_ARRAY_VALUES(z, n, data) \
+ BOOST_PP_COMMA_IF(n) BOOST_PP_ARRAY_ELEM(n, data)
+
+// checks 'size' values of 'type' in the device range 'actual`
+// against the values given in the array 'expected'
+#define CHECK_RANGE_EQUAL(type, size, actual, expected) \
+ { \
+ type _actual[size]; \
+ boost::compute::copy( \
+ actual.begin(), actual.begin()+size, _actual, queue \
+ ); \
+ const type _expected[size] = { \
+ BOOST_PP_REPEAT(size, LIST_ARRAY_VALUES, (size, expected)) \
+ }; \
+ BOOST_CHECK_EQUAL_COLLECTIONS( \
+ _actual, _actual + size, _expected, _expected + size \
+ ); \
+ }
+
+template <typename Left, typename Right, typename ToleranceBaseType>
+inline void
+equal_close_impl(Left left_begin,
+ Left left_end,
+ Right right_begin,
+ Right right_end,
+ ToleranceBaseType tolerance)
+{
+ for(; left_begin != (left_end); ++left_begin, ++right_begin) {
+ BOOST_CHECK_CLOSE(*left_begin, *right_begin, tolerance); \
+ }
+}
+
+#define BOOST_COMPUTE_TEST_CHECK_CLOSE_COLLECTIONS(L_begin, L_end, R_begin, R_end, tolerance) \
+ { \
+ equal_close_impl(L_begin, L_end, R_begin, R_end, tolerance); \
+ }
+
+#define CHECK_RANGE_CLOSE(type, size, actual, expected, tolerance) \
+ { \
+ type _actual[size]; \
+ boost::compute::copy( \
+ actual.begin(), actual.begin()+size, _actual, queue \
+ ); \
+ const type _expected[size] = { \
+ BOOST_PP_REPEAT(size, LIST_ARRAY_VALUES, (size, expected)) \
+ }; \
+ BOOST_COMPUTE_TEST_CHECK_CLOSE_COLLECTIONS( \
+ _actual, _actual + size, _expected, _expected + size, tolerance \
+ ); \
+ }
+
+#define CHECK_HOST_RANGE_EQUAL(type, size, actual, expected) \
+ { \
+ const type _expected[size] = { \
+ BOOST_PP_REPEAT(size, LIST_ARRAY_VALUES, (size, expected)) \
+ }; \
+ BOOST_CHECK_EQUAL_COLLECTIONS( \
+ actual, actual + size, _expected, _expected + size \
+ ); \
+ }
+
+#define CHECK_STRING_EQUAL(actual, expected) \
+ { \
+ std::string _actual(actual.size(), '\0'); \
+ boost::compute::copy( \
+ actual.begin(), actual.end(), _actual.begin(), queue \
+ ); \
+ BOOST_CHECK_EQUAL(_actual, expected); \
+ }
+
+#endif // BOOST_COMPUTE_TEST_CHECK_MACROS_HPP
diff --git a/src/boost/libs/compute/test/context_setup.hpp b/src/boost/libs/compute/test/context_setup.hpp
new file mode 100644
index 00000000..bff606ec
--- /dev/null
+++ b/src/boost/libs/compute/test/context_setup.hpp
@@ -0,0 +1,33 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Denis Demidov
+//
+// 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.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TEST_CONTEXT_SETUP_HPP
+#define BOOST_COMPUTE_TEST_CONTEXT_SETUP_HPP
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+
+#include "opencl_version_check.hpp"
+
+struct Context {
+ boost::compute::device device;
+ boost::compute::context context;
+ boost::compute::command_queue queue;
+
+ Context() :
+ device ( boost::compute::system::default_device() ),
+ context( boost::compute::system::default_context() ),
+ queue ( boost::compute::system::default_queue() )
+ {}
+};
+
+BOOST_FIXTURE_TEST_SUITE(compute_test, Context)
+
+#endif
diff --git a/src/boost/libs/compute/test/data/invalid_program.cl b/src/boost/libs/compute/test/data/invalid_program.cl
new file mode 100644
index 00000000..3a9de877
--- /dev/null
+++ b/src/boost/libs/compute/test/data/invalid_program.cl
@@ -0,0 +1,10 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017 Kristian Popov <kristian.popov@outlook.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.
+//---------------------------------------------------------------------------//
+__kernel void foo(__global int *input) { !@#$%^&*() }
diff --git a/src/boost/libs/compute/test/data/program.cl b/src/boost/libs/compute/test/data/program.cl
new file mode 100644
index 00000000..c8962b88
--- /dev/null
+++ b/src/boost/libs/compute/test/data/program.cl
@@ -0,0 +1,15 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2017 Jakub Szuppe <j.szuppe@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.
+//---------------------------------------------------------------------------//
+
+__kernel void foobar(__global int* x)
+{
+ const int gid = get_global_id(0);
+ x[gid] = gid;
+}
diff --git a/src/boost/libs/compute/test/data/program.spirv32 b/src/boost/libs/compute/test/data/program.spirv32
new file mode 100644
index 00000000..79eb6153
--- /dev/null
+++ b/src/boost/libs/compute/test/data/program.spirv32
Binary files differ
diff --git a/src/boost/libs/compute/test/data/program.spirv64 b/src/boost/libs/compute/test/data/program.spirv64
new file mode 100644
index 00000000..57113d41
--- /dev/null
+++ b/src/boost/libs/compute/test/data/program.spirv64
Binary files differ
diff --git a/src/boost/libs/compute/test/extra/CMakeLists.txt b/src/boost/libs/compute/test/extra/CMakeLists.txt
new file mode 100644
index 00000000..4795a6cc
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/CMakeLists.txt
@@ -0,0 +1,81 @@
+# ---------------------------------------------------------------------------
+# Copyright (c) 2015 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
+#
+# ---------------------------------------------------------------------------
+
+# include local test headers
+include_directories(..)
+
+# Check for linkage problems
+add_executable(test_multiple_objects
+ test_multiple_objects1.cpp
+ test_multiple_objects2.cpp
+ )
+target_link_libraries(test_multiple_objects
+ ${OPENCL_LIBRARIES}
+ ${Boost_LIBRARIES}
+ )
+# link with coverage library
+if(${BOOST_COMPUTE_ENABLE_COVERAGE} AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
+ target_link_libraries(test_multiple_objects -fprofile-arcs -ftest-coverage)
+endif()
+add_test("misc.multiple_objects" test_multiple_objects)
+
+# eigen interop tests
+if(${BOOST_COMPUTE_HAVE_EIGEN})
+ find_package(Eigen REQUIRED)
+ include_directories(SYSTEM ${EIGEN_INCLUDE_DIRS})
+ add_compute_test("interop.eigen" test_interop_eigen.cpp)
+endif()
+
+# opencv interop tests
+if(${BOOST_COMPUTE_HAVE_OPENCV})
+ find_package(OpenCV REQUIRED)
+ include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
+ add_compute_test("interop.opencv" test_interop_opencv.cpp)
+ target_link_libraries(test_interop_opencv ${OpenCV_LIBS})
+endif()
+
+# qt interop tests
+if(${BOOST_COMPUTE_HAVE_QT})
+ # look for Qt4 in the first place
+ find_package(Qt4 QUIET)
+
+ if(${QT4_FOUND})
+ find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtOpenGL)
+ include(${QT_USE_FILE})
+ else()
+ find_package(Qt5Widgets QUIET)
+
+ # look for Qt5
+ if(${Qt5Widgets_FOUND})
+ find_package(Qt5Core REQUIRED)
+ find_package(Qt5Widgets REQUIRED)
+ find_package(Qt5OpenGL REQUIRED)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5OpenGL_EXECUTABLE_COMPILE_FLAGS}")
+ set(QT_LIBRARIES ${Qt5OpenGL_LIBRARIES})
+ else()
+ # no valid Qt framework found
+ message(FATAL_ERROR "Error: Did not find Qt4 or Qt5")
+ endif()
+ endif()
+
+ add_compute_test("interop.qt" test_interop_qt.cpp)
+ target_link_libraries(test_interop_qt ${QT_LIBRARIES})
+
+ # the opengl interop test depends on qt to create the opengl context
+ add_compute_test("interop.opengl" test_interop_opengl.cpp)
+ target_link_libraries(test_interop_opengl ${QT_LIBRARIES})
+endif()
+
+# vtk interop tests
+if(${BOOST_COMPUTE_HAVE_VTK})
+ find_package(VTK REQUIRED)
+ include(${VTK_USE_FILE})
+ add_compute_test("interop.vtk" test_interop_vtk.cpp)
+ target_link_libraries(test_interop_vtk ${VTK_LIBRARIES})
+endif()
diff --git a/src/boost/libs/compute/test/extra/test_interop_eigen.cpp b/src/boost/libs/compute/test/extra/test_interop_eigen.cpp
new file mode 100644
index 00000000..a184de9b
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_interop_eigen.cpp
@@ -0,0 +1,106 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestInteropEigen
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/closure.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/interop/eigen.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bcl = boost::compute;
+
+BOOST_AUTO_TEST_CASE(eigen)
+{
+ Eigen::MatrixXf mat(3, 3);
+ mat << 1, 2, 3,
+ 6, 5, 4,
+ 7, 8, 9;
+
+ // copy matrix to gpu buffer
+ bcl::vector<float> vec(9, context);
+ bcl::eigen_copy_matrix_to_buffer(mat, vec.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 9, vec, (1, 6, 7, 2, 5, 8, 3, 4, 9));
+
+ // transpose matrix and then copy to gpu buffer
+ mat = mat.transpose().eval();
+ bcl::eigen_copy_matrix_to_buffer(mat, vec.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 9, vec, (1, 2, 3, 6, 5, 4, 7, 8, 9));
+
+ // set matrix to zero and copy data back from gpu buffer
+ mat.setZero();
+ bcl::eigen_copy_buffer_to_matrix(vec.begin(), mat, queue);
+ BOOST_CHECK(mat.isZero() == false);
+ BOOST_CHECK_EQUAL(mat.sum(), 45);
+}
+
+BOOST_AUTO_TEST_CASE(eigen_types)
+{
+ BOOST_CHECK(std::strcmp(bcl::type_name<Eigen::Vector2i>(), "int2") == 0);
+ BOOST_CHECK(std::strcmp(bcl::type_name<Eigen::Vector2f>(), "float2") == 0);
+ BOOST_CHECK(std::strcmp(bcl::type_name<Eigen::Vector4f>(), "float4") == 0);
+ BOOST_CHECK(std::strcmp(bcl::type_name<Eigen::Vector4d>(), "double4") == 0);
+}
+
+BOOST_AUTO_TEST_CASE(multiply_matrix4)
+{
+ std::vector<Eigen::Vector4f> host_vectors;
+ std::vector<Eigen::Matrix4f> host_matrices;
+
+ Eigen::Matrix4f matrix;
+ matrix << 1, 2, 0, 3,
+ 2, 1, 2, 0,
+ 0, 3, 1, 2,
+ 2, 0, 2, 1;
+
+ host_vectors.push_back(Eigen::Vector4f(1, 2, 3, 4));
+ host_vectors.push_back(Eigen::Vector4f(4, 3, 2, 1));
+ host_vectors.push_back(Eigen::Vector4f(1, 2, 3, 4));
+ host_vectors.push_back(Eigen::Vector4f(4, 3, 2, 1));
+
+ // store the eigen 4x4 matrix as a float16
+ bcl::float16_ M =
+ bcl::eigen_matrix4f_to_float16(matrix);
+
+ // returns the result of M*x
+ BOOST_COMPUTE_CLOSURE(Eigen::Vector4f, transform4x4, (const Eigen::Vector4f x), (M),
+ {
+ float4 r;
+ r.x = dot(M.s048c, x);
+ r.y = dot(M.s159d, x);
+ r.z = dot(M.s26ae, x);
+ r.w = dot(M.s37bf, x);
+ return r;
+ });
+
+ bcl::vector<Eigen::Vector4f> vectors(4, context);
+ bcl::vector<Eigen::Vector4f> results(4, context);
+
+ bcl::copy(host_vectors.begin(), host_vectors.end(), vectors.begin(), queue);
+
+ bcl::transform(
+ vectors.begin(), vectors.end(), results.begin(), transform4x4, queue
+ );
+
+ std::vector<Eigen::Vector4f> host_results(4);
+ bcl::copy(results.begin(), results.end(), host_results.begin(), queue);
+
+ BOOST_CHECK((matrix * host_vectors[0]) == host_results[0]);
+ BOOST_CHECK((matrix * host_vectors[1]) == host_results[1]);
+ BOOST_CHECK((matrix * host_vectors[2]) == host_results[2]);
+ BOOST_CHECK((matrix * host_vectors[3]) == host_results[3]);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/extra/test_interop_opencv.cpp b/src/boost/libs/compute/test/extra/test_interop_opencv.cpp
new file mode 100644
index 00000000..4d959360
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_interop_opencv.cpp
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestInteropOpenCV
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/interop/opencv.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bcl = boost::compute;
+
+BOOST_AUTO_TEST_CASE(opencv_mat_to_buffer)
+{
+ // create opencv mat
+ cv::Mat mat(1, 4, CV_32F);
+ mat.at<float>(0, 0) = 0.0f;
+ mat.at<float>(0, 1) = 2.5f;
+ mat.at<float>(0, 2) = 4.1f;
+ mat.at<float>(0, 3) = 5.6f;
+
+ // copy mat to gpu vector
+ bcl::vector<float> vector(4, context);
+ bcl::opencv_copy_mat_to_buffer(mat, vector.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 4, vector, (0.0f, 2.5f, 4.1f, 5.6f));
+
+ // reverse gpu vector and copy back to mat
+ bcl::reverse(vector.begin(), vector.end(), queue);
+ bcl::opencv_copy_buffer_to_mat(vector.begin(), mat, queue);
+ BOOST_CHECK_EQUAL(mat.at<float>(0), 5.6f);
+ BOOST_CHECK_EQUAL(mat.at<float>(1), 4.1f);
+ BOOST_CHECK_EQUAL(mat.at<float>(2), 2.5f);
+ BOOST_CHECK_EQUAL(mat.at<float>(3), 0.0f);
+}
+
+BOOST_AUTO_TEST_CASE(opencv_image_format)
+{
+ // 8-bit uchar BGRA
+ BOOST_CHECK(
+ bcl::opencv_get_mat_image_format(cv::Mat(32, 32, CV_8UC4)) ==
+ bcl::image_format(CL_BGRA, CL_UNORM_INT8)
+ );
+
+ // 32-bit float
+ BOOST_CHECK(
+ bcl::opencv_get_mat_image_format(cv::Mat(32, 32, CV_32F)) ==
+ bcl::image_format(CL_INTENSITY, CL_FLOAT)
+ );
+
+ // 32-bit float RGBA
+ BOOST_CHECK(
+ bcl::opencv_get_mat_image_format(cv::Mat(32, 32, CV_32FC4)) ==
+ bcl::image_format(CL_RGBA, CL_FLOAT)
+ );
+
+ // 16-bit uchar BGRA
+ BOOST_CHECK(
+ bcl::opencv_get_mat_image_format(cv::Mat(32, 32, CV_16UC4)) ==
+ bcl::image_format(CL_BGRA, CL_UNORM_INT16)
+ );
+
+ // 8-bit uchar
+ BOOST_CHECK(
+ bcl::opencv_get_mat_image_format(cv::Mat(32, 32, CV_8UC1)) ==
+ bcl::image_format(CL_INTENSITY, CL_UNORM_INT8)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(opencv_float_mat_image2d)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ cv::Vec4f pixel;
+ // create opencv mat
+ cv::Mat mat(2, 2, CV_32FC4, cv::Scalar(100, 150, 200, 255));
+ // transfer image to gpu
+ bcl::image2d image =
+ bcl::opencv_create_image2d_with_mat(
+ mat,
+ bcl::image2d::read_only,
+ queue
+ );
+ // copy the data back to cpu
+ bcl::opencv_copy_image_to_mat(image, mat, queue);
+
+ pixel = mat.at<cv::Vec4f>(1,1);
+ BOOST_CHECK_EQUAL(pixel[0], 100.0f);
+ BOOST_CHECK_EQUAL(pixel[1], 150.0f);
+ BOOST_CHECK_EQUAL(pixel[2], 200.0f);
+ BOOST_CHECK_EQUAL(pixel[3], 255.0f);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/extra/test_interop_opengl.cpp b/src/boost/libs/compute/test/extra/test_interop_opengl.cpp
new file mode 100644
index 00000000..876abfab
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_interop_opengl.cpp
@@ -0,0 +1,28 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestInteropOpenGL
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/interop/opengl.hpp>
+
+BOOST_AUTO_TEST_CASE(opengl_buffer)
+{
+}
+
+BOOST_AUTO_TEST_CASE(type_name)
+{
+ BOOST_CHECK_EQUAL(
+ boost::compute::type_name<boost::compute::opengl_texture>(), "image2d_t"
+ );
+ BOOST_CHECK_EQUAL(
+ boost::compute::type_name<boost::compute::opengl_renderbuffer>(), "image2d_t"
+ );
+}
diff --git a/src/boost/libs/compute/test/extra/test_interop_qt.cpp b/src/boost/libs/compute/test/extra/test_interop_qt.cpp
new file mode 100644
index 00000000..a07f44fb
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_interop_qt.cpp
@@ -0,0 +1,95 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestInteropQt
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+#include <boost/compute/interop/qt.hpp>
+
+#include <QList>
+#include <QVector>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bcl = boost::compute;
+
+BOOST_AUTO_TEST_CASE(qimage_format)
+{
+ BOOST_CHECK(
+ bcl::qt_qimage_format_to_image_format(QImage::Format_RGB32) ==
+ bcl::image_format(CL_BGRA, CL_UNORM_INT8)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_qvector_to_device)
+{
+ QList<int> qvector;
+ qvector.append(0);
+ qvector.append(2);
+ qvector.append(4);
+ qvector.append(6);
+
+ bcl::vector<int> vector(4, context);
+ bcl::copy(qvector.begin(), qvector.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (0, 2, 4, 6));
+}
+
+BOOST_AUTO_TEST_CASE(copy_qlist_to_device)
+{
+ QList<int> list;
+ list.append(1);
+ list.append(3);
+ list.append(5);
+ list.append(7);
+
+ bcl::vector<int> vector(4, context);
+ bcl::copy(list.begin(), list.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (1, 3, 5, 7));
+}
+
+BOOST_AUTO_TEST_CASE(qvector_of_qpoint)
+{
+ QVector<QPoint> qt_points;
+ qt_points.append(QPoint(0, 1));
+ qt_points.append(QPoint(2, 3));
+ qt_points.append(QPoint(4, 5));
+ qt_points.append(QPoint(6, 7));
+
+ bcl::vector<QPoint> bcl_points(qt_points.size(), context);
+ bcl::copy(qt_points.begin(), qt_points.end(), bcl_points.begin(), queue);
+}
+
+BOOST_AUTO_TEST_CASE(qvector_of_qpointf)
+{
+ QVector<QPointF> qt_points;
+ qt_points.append(QPointF(0.3f, 1.7f));
+ qt_points.append(QPointF(2.3f, 3.7f));
+ qt_points.append(QPointF(4.3f, 5.7f));
+ qt_points.append(QPointF(6.3f, 7.7f));
+
+ bcl::vector<QPointF> bcl_points(qt_points.size(), context);
+ bcl::copy(qt_points.begin(), qt_points.end(), bcl_points.begin(), queue);
+}
+
+BOOST_AUTO_TEST_CASE(qvector_iterator)
+{
+ using boost::compute::detail::is_contiguous_iterator;
+
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<QVector<int>::iterator>::value == true);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<QVector<int>::const_iterator>::value == true);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<QList<int>::iterator>::value == false);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<QList<int>::const_iterator>::value == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/extra/test_interop_vtk.cpp b/src/boost/libs/compute/test/extra/test_interop_vtk.cpp
new file mode 100644
index 00000000..ca98790f
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_interop_vtk.cpp
@@ -0,0 +1,118 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestInteropVTK
+#include <boost/test/unit_test.hpp>
+
+#include <vtkFloatArray.h>
+#include <vtkMatrix4x4.h>
+#include <vtkNew.h>
+#include <vtkPoints.h>
+#include <vtkSmartPointer.h>
+#include <vtkUnsignedCharArray.h>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+#include <boost/compute/interop/vtk.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(bounds)
+{
+ using compute::float4_;
+
+ // create vtk points
+ vtkNew<vtkPoints> points;
+ points->InsertNextPoint(0.0, 0.0, 0.0);
+ points->InsertNextPoint(1.0, 2.0, 1.0);
+ points->InsertNextPoint(-1.0, -3.0, -1.0);
+ points->InsertNextPoint(0.5, 2.5, 1.5);
+
+ // copy points to vector on gpu
+ compute::vector<float4_> vector(points->GetNumberOfPoints(), context);
+ compute::vtk_copy_points_to_buffer(points.GetPointer(), vector.begin(), queue);
+
+ // compute bounds
+ double bounds[6];
+ compute::vtk_compute_bounds(vector.begin(), vector.end(), bounds, queue);
+
+ // check bounds
+ BOOST_CHECK_CLOSE(bounds[0], -1.0, 1e-8);
+ BOOST_CHECK_CLOSE(bounds[1], 1.0, 1e-8);
+ BOOST_CHECK_CLOSE(bounds[2], -3.0, 1e-8);
+ BOOST_CHECK_CLOSE(bounds[3], 2.5, 1e-8);
+ BOOST_CHECK_CLOSE(bounds[4], -1.0, 1e-8);
+ BOOST_CHECK_CLOSE(bounds[5], 1.5, 1e-8);
+}
+
+BOOST_AUTO_TEST_CASE(copy_uchar_array)
+{
+ // create vtk uchar vector containing 3 RGBA colors
+ vtkNew<vtkUnsignedCharArray> array;
+ array->SetNumberOfComponents(4);
+
+ unsigned char red[4] = { 255, 0, 0, 255 };
+ array->InsertNextTupleValue(red);
+ unsigned char green[4] = { 0, 255, 0, 255 };
+ array->InsertNextTupleValue(green);
+ unsigned char blue[4] = { 0, 0, 255, 255 };
+ array->InsertNextTupleValue(blue);
+
+ // create vector<uchar4> on device and copy values from vtk array
+ compute::vector<compute::uchar4_> vector(3, context);
+ compute::vtk_copy_data_array_to_buffer(
+ array.GetPointer(),
+ compute::make_buffer_iterator<compute::uchar_>(vector.get_buffer(), 0),
+ queue
+ );
+
+ // check values
+ std::vector<compute::uchar4_> host_vector(3);
+ compute::copy(
+ vector.begin(), vector.end(), host_vector.begin(), queue
+ );
+ BOOST_CHECK(host_vector[0] == compute::uchar4_(255, 0, 0, 255));
+ BOOST_CHECK(host_vector[1] == compute::uchar4_(0, 255, 0, 255));
+ BOOST_CHECK(host_vector[2] == compute::uchar4_(0, 0, 255, 255));
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_array)
+{
+ // create vtk float array
+ vtkNew<vtkFloatArray> array;
+ array->InsertNextValue(2.5f);
+ array->InsertNextValue(1.0f);
+ array->InsertNextValue(6.5f);
+ array->InsertNextValue(4.0f);
+
+ // create vector on device and copy values from vtk array
+ compute::vector<float> vector(4, context);
+ compute::vtk_copy_data_array_to_buffer(array.GetPointer(), vector.begin(), queue);
+
+ // sort values on the gpu
+ compute::sort(vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(float, 4, vector, (1.0f, 2.5f, 4.0f, 6.5f));
+
+ // copy sorted values back to the vtk array
+ compute::vtk_copy_buffer_to_data_array(
+ vector.begin(), vector.end(), array.GetPointer(), queue
+ );
+ BOOST_CHECK_EQUAL(array->GetValue(0), 1.0f);
+ BOOST_CHECK_EQUAL(array->GetValue(1), 2.5f);
+ BOOST_CHECK_EQUAL(array->GetValue(2), 4.0f);
+ BOOST_CHECK_EQUAL(array->GetValue(3), 6.5f);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/extra/test_multiple_objects1.cpp b/src/boost/libs/compute/test/extra/test_multiple_objects1.cpp
new file mode 100644
index 00000000..af80d7c1
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_multiple_objects1.cpp
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------//
+// 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 TestMultipleObjects
+#include <boost/test/unit_test.hpp>
+#include <boost/compute.hpp>
+
+bool dummy_function();
+
+BOOST_AUTO_TEST_CASE(multiple_objects)
+{
+ // It is enough if the test compiles.
+ BOOST_CHECK( dummy_function() );
+}
diff --git a/src/boost/libs/compute/test/extra/test_multiple_objects2.cpp b/src/boost/libs/compute/test/extra/test_multiple_objects2.cpp
new file mode 100644
index 00000000..8beb8b98
--- /dev/null
+++ b/src/boost/libs/compute/test/extra/test_multiple_objects2.cpp
@@ -0,0 +1,15 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <boost/compute.hpp>
+
+bool dummy_function() {
+ return true;
+}
diff --git a/src/boost/libs/compute/test/opencl_version_check.hpp b/src/boost/libs/compute/test/opencl_version_check.hpp
new file mode 100644
index 00000000..2c7ad68a
--- /dev/null
+++ b/src/boost/libs/compute/test/opencl_version_check.hpp
@@ -0,0 +1,20 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Denis Demidov
+//
+// 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.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TEST_OPENCL_VERSION_CHECK_HPP
+#define BOOST_COMPUTE_TEST_OPENCL_VERSION_CHECK_HPP
+
+#define REQUIRES_OPENCL_VERSION(major, minor) \
+ if (!device.check_version(major, minor)) return
+
+#define REQUIRES_OPENCL_PLATFORM_VERSION(major, minor) \
+ if (!device.platform().check_version(major, minor)) return
+
+#endif
diff --git a/src/boost/libs/compute/test/quirks.hpp b/src/boost/libs/compute/test/quirks.hpp
new file mode 100644
index 00000000..adffeb1f
--- /dev/null
+++ b/src/boost/libs/compute/test/quirks.hpp
@@ -0,0 +1,128 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_TEST_QUIRKS_HPP
+#define BOOST_COMPUTE_TEST_QUIRKS_HPP
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/platform.hpp>
+#include <boost/compute/detail/vendor.hpp>
+
+// this file contains functions which check for 'quirks' or buggy
+// behavior in OpenCL implementations. this allows us to skip certain
+// tests when running on buggy platforms.
+
+// returns true if the device is a POCL device
+inline bool is_pocl_device(const boost::compute::device &device)
+{
+ return device.platform().name() == "Portable Computing Language";
+}
+
+// returns true if the device is from Apple OpenCL platform
+inline bool is_apple_device(const boost::compute::device &device)
+{
+ return device.platform().name() == "Apple";
+}
+
+// AMD platforms have a bug when using struct assignment. this affects
+// algorithms like fill() when used with pairs/tuples.
+//
+// see: https://community.amd.com/thread/166622
+inline bool bug_in_struct_assignment(const boost::compute::device &device)
+{
+ return boost::compute::detail::is_amd_device(device);
+}
+
+// clEnqueueSVMMemcpy() operation does not work on AMD devices. This affects
+// copy() algorithm. This bug was fixed in AMD drivers for Windows.
+//
+// see: https://community.amd.com/thread/190585
+inline bool bug_in_svmmemcpy(const boost::compute::device &device)
+{
+ #ifdef _WIN32
+ return false;
+ #else
+ return boost::compute::detail::is_amd_device(device);
+ #endif
+}
+
+// For CPU devices on Apple platform local memory can not be used when work
+// group size is not [1;1;1]. If work group size is greater "Invalid Work Group
+// Size" error is thrown. (Apple OpenCL implementation can sometimes reduce
+// max work group size for other reasons.)
+// When local memory is not used max work group size for CPU devices on Apple
+// platform should be [1024;1;1].
+inline bool is_apple_cpu_device(const boost::compute::device &device)
+{
+ return is_apple_device(device) && (device.type() & ::boost::compute::device::cpu);
+}
+
+// On Apple devices clCreateBuffer does not return NULL and does no set error
+// to CL_INVALID_BUFFER_SIZE when size of the buffer memory object is greater
+// than CL_DEVICE_MAX_MEM_ALLOC_SIZE.
+inline bool bug_in_clcreatebuffer(const boost::compute::device &device)
+{
+ return is_apple_device(device);
+}
+
+// returns true if the device supports image samplers.
+inline bool supports_image_samplers(const boost::compute::device &device)
+{
+ // POCL does not yet support image samplers and gives the following
+ // error when attempting to create one:
+ //
+ // pocl error: encountered unimplemented part of the OpenCL specs
+ // in clCreateSampler.c:28
+ if(is_pocl_device(device)){
+ return false;
+ }
+
+ return true;
+}
+
+// returns true if the device has remquo() built-in OpenCL function implementation
+inline bool has_remquo_func(const boost::compute::device &device)
+{
+ // POCL does not have it
+ if(is_pocl_device(device)){
+ return false;
+ }
+ return true;
+}
+
+// returns true if the device supports clSetMemObjectDestructorCallback
+inline bool supports_destructor_callback(const boost::compute::device &device)
+{
+ // unimplemented in POCL
+ return !is_pocl_device(device);
+}
+
+// returns true if the device supports clCompileProgram
+inline bool supports_compile_program(const boost::compute::device &device)
+{
+ // unimplemented in POCL
+ return !is_pocl_device(device);
+}
+
+// returns true if the device supports clLinkProgram
+inline bool supports_link_program(const boost::compute::device &device)
+{
+ // unimplemented in POCL
+ return !is_pocl_device(device);
+}
+
+// See https://github.com/pocl/pocl/issues/577, POCL fails when a program
+// with incorrect code is built for the 2nd time
+inline bool pocl_bug_issue_577(const boost::compute::device &device)
+{
+ return is_pocl_device(device);
+}
+
+#endif // BOOST_COMPUTE_TEST_QUIRKS_HPP
diff --git a/src/boost/libs/compute/test/test_accumulate.cpp b/src/boost/libs/compute/test/test_accumulate.cpp
new file mode 100644
index 00000000..b77c07df
--- /dev/null
+++ b/src/boost/libs/compute/test/test_accumulate.cpp
@@ -0,0 +1,302 @@
+//---------------------------------------------------------------------------//
+// 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 TestAccumulate
+#include <boost/test/unit_test.hpp>
+
+#include <numeric>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/container/mapped_view.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(sum_int)
+{
+ int data[] = { 2, 4, 6, 8 };
+ boost::compute::vector<int> vector(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
+ 20
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), -10, queue),
+ 10
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 5, queue),
+ 25
+ );
+}
+
+BOOST_AUTO_TEST_CASE(product_int)
+{
+ int data[] = { 2, 4, 6, 8 };
+ boost::compute::vector<int> vector(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ vector.begin(), vector.end(), 1, boost::compute::multiplies<int>(),
+ queue),
+ 384
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ vector.begin(), vector.end(), -1, boost::compute::multiplies<int>(),
+ queue),
+ -384
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ vector.begin(), vector.end(), 2, boost::compute::multiplies<int>(),
+ queue),
+ 768
+ );
+}
+
+BOOST_AUTO_TEST_CASE(quotient_int)
+{
+ int data[] = { 2, 8, 16 };
+ boost::compute::vector<int> vector(data, data + 3, queue);
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ vector.begin(),
+ vector.end(),
+ 1024,
+ boost::compute::divides<int>(),
+ queue
+ ),
+ 4
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sum_counting_iterator)
+{
+ // sum 0 -> 9
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ boost::compute::make_counting_iterator(0),
+ boost::compute::make_counting_iterator(10),
+ 0,
+ boost::compute::plus<int>(),
+ queue
+ ),
+ 45
+ );
+
+ // sum 0 -> 9 + 7
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ boost::compute::make_counting_iterator(0),
+ boost::compute::make_counting_iterator(10),
+ 7,
+ boost::compute::plus<int>(),
+ queue
+ ),
+ 52
+ );
+
+ // sum 15 -> 24
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ boost::compute::make_counting_iterator(15),
+ boost::compute::make_counting_iterator(25),
+ 0,
+ boost::compute::plus<int>(),
+ queue
+ ),
+ 195
+ );
+
+ // sum -5 -> 10
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ boost::compute::make_counting_iterator(-5),
+ boost::compute::make_counting_iterator(10),
+ 0,
+ boost::compute::plus<int>(),
+ queue
+ ),
+ 30
+ );
+
+ // sum -5 -> 10 - 2
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(
+ boost::compute::make_counting_iterator(-5),
+ boost::compute::make_counting_iterator(10),
+ -2,
+ boost::compute::plus<int>(),
+ queue
+ ),
+ 28
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sum_iota)
+{
+ // size 0
+ boost::compute::vector<int> vector(0, context);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
+ 0
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 4, queue),
+ 4
+ );
+
+ // size 50
+ vector.resize(50);
+ boost::compute::iota(vector.begin(), vector.end(), 0, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
+ 1225
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 11, queue),
+ 1236
+ );
+
+ // size 1000
+ vector.resize(1000);
+ boost::compute::iota(vector.begin(), vector.end(), 0, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
+ 499500
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), -45, queue),
+ 499455
+ );
+
+ // size 1025
+ vector.resize(1025);
+ boost::compute::iota(vector.begin(), vector.end(), 0, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 0, queue),
+ 524800
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::accumulate(vector.begin(), vector.end(), 2, queue),
+ 524802
+ );
+}
+
+BOOST_AUTO_TEST_CASE(min_and_max)
+{
+ using boost::compute::int2_;
+
+ int data[] = { 5, 3, 1, 6, 4, 2 };
+ boost::compute::vector<int> vector(data, data + 6, queue);
+
+ BOOST_COMPUTE_FUNCTION(int2_, min_and_max, (int2_ accumulator, const int value),
+ {
+ return (int2)((min)(accumulator.x, value), (max)(accumulator.y, value));
+ });
+
+ int2_ result = boost::compute::accumulate(
+ vector.begin(), vector.end(), int2_(100, -100), min_and_max, queue
+ );
+ BOOST_CHECK_EQUAL(result[0], 1);
+ BOOST_CHECK_EQUAL(result[1], 6);
+}
+
+BOOST_AUTO_TEST_CASE(min_max)
+{
+ float data[] = { 1.2f, 5.5f, 0.1f, 9.6f, 4.2f, 6.7f, 9.0f, 3.4f };
+ boost::compute::vector<float> vec(data, data + 8, queue);
+
+ using ::boost::compute::min;
+ using ::boost::compute::max;
+
+ float min_value = boost::compute::accumulate(
+ vec.begin(), vec.end(), (std::numeric_limits<float>::max)(), min<float>(), queue
+ );
+ BOOST_CHECK_EQUAL(min_value, 0.1f);
+
+ float max_value = boost::compute::accumulate(
+ vec.begin(), vec.end(), (std::numeric_limits<float>::min)(), max<float>(), queue
+ );
+ BOOST_CHECK_EQUAL(max_value, 9.6f);
+
+ // find min with init less than any value in the array
+ min_value = boost::compute::accumulate(
+ vec.begin(), vec.end(), -1.f, min<float>(), queue
+ );
+ BOOST_CHECK_EQUAL(min_value, -1.f);
+
+ // find max with init greater than any value in the array
+ max_value = boost::compute::accumulate(
+ vec.begin(), vec.end(), 10.f, max<float>(), queue
+ );
+ BOOST_CHECK_EQUAL(max_value, 10.f);
+}
+
+template<class T>
+void ensure_std_accumulate_equality(const std::vector<T> &data,
+ boost::compute::command_queue &queue)
+{
+ boost::compute::mapped_view<T> view(&data[0], data.size(), queue.get_context());
+
+ BOOST_CHECK_EQUAL(
+ std::accumulate(data.begin(), data.end(), 0),
+ boost::compute::accumulate(view.begin(), view.end(), 0, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(std_accumulate_equality)
+{
+ // test accumulate() with int
+ int data1[] = { 1, 2, 3, 4 };
+ std::vector<int> vec1(data1, data1 + 4);
+ ensure_std_accumulate_equality(vec1, queue);
+
+ vec1.resize(10000);
+ std::fill(vec1.begin(), vec1.end(), 2);
+ ensure_std_accumulate_equality(vec1, queue);
+
+ // test accumulate() with float
+ float data2[] = { 1.2f, 2.3f, 4.5f, 6.7f, 8.9f };
+ std::vector<float> vec2(data2, data2 + 5);
+ ensure_std_accumulate_equality(vec2, queue);
+
+ vec2.resize(10000);
+ std::fill(vec2.begin(), vec2.end(), 1.01f);
+ ensure_std_accumulate_equality(vec2, queue);
+
+ // test accumulate() with double
+ if(device.supports_extension("cl_khr_fp64")){
+ double data3[] = { 1.2, 2.3, 4.5, 6.7, 8.9 };
+ std::vector<double> vec3(data3, data3 + 5);
+ ensure_std_accumulate_equality(vec3, queue);
+
+ vec3.resize(10000);
+ std::fill(vec3.begin(), vec3.end(), 2.02);
+ ensure_std_accumulate_equality(vec3, queue);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_adjacent_difference.cpp b/src/boost/libs/compute/test/test_adjacent_difference.cpp
new file mode 100644
index 00000000..0fca4dab
--- /dev/null
+++ b/src/boost/libs/compute/test/test_adjacent_difference.cpp
@@ -0,0 +1,102 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestAdjacentDifference
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/all_of.hpp>
+#include <boost/compute/algorithm/adjacent_difference.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(adjacent_difference_int)
+{
+ using compute::int_;
+
+ compute::vector<int_> a(5, context);
+ compute::iota(a.begin(), a.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int_, 5, a, (0, 1, 2, 3, 4));
+
+ compute::vector<int_> b(5, context);
+ compute::vector<int_>::iterator iter =
+ compute::adjacent_difference(a.begin(), a.end(), b.begin(), queue);
+ BOOST_CHECK(iter == b.end());
+ CHECK_RANGE_EQUAL(int_, 5, b, (0, 1, 1, 1, 1));
+
+ int_ data[] = { 1, 9, 36, 48, 81 };
+ compute::copy(data, data + 5, a.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 5, a, (1, 9, 36, 48, 81));
+
+ iter = compute::adjacent_difference(a.begin(), a.end(), b.begin(), queue);
+ BOOST_CHECK(iter == b.end());
+ CHECK_RANGE_EQUAL(int_, 5, b, (1, 8, 27, 12, 33));
+}
+
+BOOST_AUTO_TEST_CASE(adjacent_difference_first_eq_last)
+{
+ using compute::int_;
+
+ compute::vector<int_> a(size_t(5), int_(1), queue);
+ compute::vector<int_> b(size_t(5), int_(0), queue);
+ compute::vector<int_>::iterator iter =
+ compute::adjacent_difference(a.begin(), a.begin(), b.begin(), queue);
+ BOOST_CHECK(iter == b.begin());
+ CHECK_RANGE_EQUAL(int_, 5, b, (0, 0, 0, 0, 0));
+}
+
+BOOST_AUTO_TEST_CASE(adjacent_difference_first_eq_result)
+{
+ using compute::int_;
+
+ compute::vector<int_> a(5, context);
+ compute::iota(a.begin(), a.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int_, 5, a, (0, 1, 2, 3, 4));
+
+ compute::vector<int_>::iterator iter =
+ compute::adjacent_difference(a.begin(), a.end(), a.begin(), queue);
+ BOOST_CHECK(iter == a.end());
+ CHECK_RANGE_EQUAL(int_, 5, a, (0, 1, 1, 1, 1));
+}
+
+BOOST_AUTO_TEST_CASE(all_same)
+{
+ using compute::int_;
+
+ compute::vector<int_> input(1000, context);
+ compute::fill(input.begin(), input.end(), 42, queue);
+
+ compute::vector<int_> output(input.size(), context);
+
+ compute::adjacent_difference(
+ input.begin(), input.end(), output.begin(), queue
+ );
+
+ int_ first;
+ compute::copy_n(output.begin(), 1, &first, queue);
+ BOOST_CHECK_EQUAL(first, 42);
+
+ using compute::lambda::_1;
+
+ BOOST_CHECK(
+ compute::all_of(output.begin() + 1, output.end(), _1 == 0, queue)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_adjacent_find.cpp b/src/boost/libs/compute/test/test_adjacent_find.cpp
new file mode 100644
index 00000000..bfb864e4
--- /dev/null
+++ b/src/boost/libs/compute/test/test_adjacent_find.cpp
@@ -0,0 +1,68 @@
+//---------------------------------------------------------------------------//
+// 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 TestAdjacentFind
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/adjacent_find.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(adjacent_find_int)
+{
+ int data[] = { 1, 3, 5, 5, 6, 7, 7, 8 };
+ compute::vector<int> vec(data, data + 8, queue);
+
+ compute::vector<int>::iterator iter =
+ compute::adjacent_find(vec.begin(), vec.end(), queue);
+ BOOST_CHECK(iter == vec.begin() + 2);
+}
+
+BOOST_AUTO_TEST_CASE(adjacent_find_int2)
+{
+ using compute::int2_;
+
+ compute::vector<int2_> vec(context);
+ vec.push_back(int2_(1, 2), queue);
+ vec.push_back(int2_(3, 4), queue);
+ vec.push_back(int2_(5, 6), queue);
+ vec.push_back(int2_(7, 8), queue);
+ vec.push_back(int2_(7, 8), queue);
+
+ compute::vector<int2_>::iterator iter =
+ compute::adjacent_find(vec.begin(), vec.end(), queue);
+ BOOST_CHECK(iter == vec.begin() + 3);
+}
+
+BOOST_AUTO_TEST_CASE(adjacent_find_iota)
+{
+ compute::vector<int> vec(2048, context);
+ compute::iota(vec.begin(), vec.end(), 1, queue);
+ BOOST_VERIFY(
+ compute::adjacent_find(vec.begin(), vec.end(), queue) == vec.end()
+ );
+}
+
+BOOST_AUTO_TEST_CASE(adjacent_find_fill)
+{
+ compute::vector<int> vec(2048, context);
+ compute::fill(vec.begin(), vec.end(), 7, queue);
+ BOOST_VERIFY(
+ compute::adjacent_find(vec.begin(), vec.end(), queue) == vec.begin()
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_amd_cpp_kernel_language.cpp b/src/boost/libs/compute/test/test_amd_cpp_kernel_language.cpp
new file mode 100644
index 00000000..4a3c31f8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_amd_cpp_kernel_language.cpp
@@ -0,0 +1,68 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestAmdCppKernel
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/vendor.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(amd_template_function)
+{
+ if(!compute::detail::is_amd_device(device)){
+ std::cerr << "skipping amd_template_function test: c++ static kernel "
+ "language is only supported on AMD devices." << std::endl;
+ return;
+ }
+
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ template<typename T>
+ inline T square(const T x)
+ {
+ return x * x;
+ }
+
+ template<typename T>
+ __kernel void square_kernel(__global T *data)
+ {
+ const uint i = get_global_id(0);
+ data[i] = square(data[i]);
+ }
+
+ template __attribute__((mangled_name(square_kernel_int)))
+ __kernel void square_kernel(__global int *data);
+ );
+
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vec(data, data + 4, queue);
+
+ compute::program square_program =
+ compute::program::build_with_source(source, context, "-x clc++");
+
+ compute::kernel square_kernel(square_program, "square_kernel_int");
+ square_kernel.set_arg(0, vec);
+
+ queue.enqueue_1d_range_kernel(square_kernel, 0, vec.size(), 4);
+
+ CHECK_RANGE_EQUAL(int, 4, vec, (1, 4, 9, 16));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_any_all_none_of.cpp b/src/boost/libs/compute/test/test_any_all_none_of.cpp
new file mode 100644
index 00000000..29391af3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_any_all_none_of.cpp
@@ -0,0 +1,89 @@
+//---------------------------------------------------------------------------//
+// 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 TestAnyAllNoneOf
+#include <boost/test/unit_test.hpp>
+
+#include <limits>
+#include <cmath>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/all_of.hpp>
+#include <boost/compute/algorithm/any_of.hpp>
+#include <boost/compute/algorithm/none_of.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(any_all_none_of)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6 };
+ bc::vector<int> v(data, data + 6, queue);
+
+ using ::boost::compute::_1;
+
+ BOOST_CHECK(bc::any_of(v.begin(), v.end(), _1 == 6) == true);
+ BOOST_CHECK(bc::any_of(v.begin(), v.end(), _1 == 9) == false);
+ BOOST_CHECK(bc::none_of(v.begin(), v.end(), _1 == 6) == false);
+ BOOST_CHECK(bc::none_of(v.begin(), v.end(), _1 == 9) == true);
+ BOOST_CHECK(bc::all_of(v.begin(), v.end(), _1 == 6) == false);
+ BOOST_CHECK(bc::all_of(v.begin(), v.end(), _1 < 9) == true);
+ BOOST_CHECK(bc::all_of(v.begin(), v.end(), _1 < 6) == false);
+ BOOST_CHECK(bc::all_of(v.begin(), v.end(), _1 >= 1) == true);
+}
+
+BOOST_AUTO_TEST_CASE(any_nan_inf)
+{
+ using ::boost::compute::_1;
+ using ::boost::compute::lambda::isinf;
+ using ::boost::compute::lambda::isnan;
+ using ::boost::compute::lambda::isfinite;
+
+ float nan = std::sqrt(-1.f);
+ float inf = std::numeric_limits<float>::infinity();
+
+ float data[] = { 1.2f, 2.3f, nan, nan, 3.4f, inf, 4.5f, inf };
+ compute::vector<float> vector(data, data + 8, queue);
+
+ BOOST_CHECK(compute::any_of(vector.begin(), vector.end(),
+ isinf(_1) || isnan(_1), queue) == true);
+ BOOST_CHECK(compute::any_of(vector.begin(), vector.end(),
+ isfinite(_1), queue) == true);
+ BOOST_CHECK(compute::all_of(vector.begin(), vector.end(),
+ isfinite(_1), queue) == false);
+ BOOST_CHECK(compute::all_of(vector.begin(), vector.begin() + 2,
+ isfinite(_1), queue) == true);
+ BOOST_CHECK(compute::all_of(vector.begin() + 2, vector.begin() + 4,
+ isnan(_1), queue) == true);
+ BOOST_CHECK(compute::none_of(vector.begin(), vector.end(),
+ isinf(_1), queue) == false);
+ BOOST_CHECK(compute::none_of(vector.begin(), vector.begin() + 4,
+ isinf(_1), queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(any_of_doctest)
+{
+ using boost::compute::lambda::_1;
+
+ int data[] = { 1, 2, 3, 4 };
+ boost::compute::vector<int> v(data, data + 4, queue);
+
+ bool result =
+//! [any_of]
+boost::compute::any_of(v.begin(), v.end(), _1 < 0, queue);
+//! [any_of]
+
+ BOOST_CHECK(result == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_array.cpp b/src/boost/libs/compute/test/test_array.cpp
new file mode 100644
index 00000000..7b203f76
--- /dev/null
+++ b/src/boost/libs/compute/test/test_array.cpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// 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 TestArray
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/array.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(concept_check)
+{
+ BOOST_CONCEPT_ASSERT((boost::Container<boost::compute::array<int, 3> >));
+// BOOST_CONCEPT_ASSERT((boost::SequenceConcept<boost::compute::array<int, 3> >));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<boost::compute::array<int, 3>::iterator>));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<boost::compute::array<int, 3>::const_iterator>));
+}
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ boost::compute::array<int, 0> empty_array(context);
+ BOOST_CHECK_EQUAL(empty_array.size(), size_t(0));
+
+ boost::compute::array<int, 10> array10(context);
+ BOOST_CHECK_EQUAL(array10.size(), size_t(10));
+}
+
+BOOST_AUTO_TEST_CASE(at)
+{
+ boost::compute::array<int, 3> array(context);
+ array[0] = 3;
+ array[1] = -2;
+ array[2] = 5;
+ BOOST_CHECK_EQUAL(array.at(0), 3);
+ BOOST_CHECK_EQUAL(array.at(1), -2);
+ BOOST_CHECK_EQUAL(array.at(2), 5);
+ BOOST_CHECK_THROW(array.at(3), std::out_of_range);
+}
+
+BOOST_AUTO_TEST_CASE(copy_from_vector)
+{
+ int data[] = { 3, 6, 9, 12 };
+ boost::compute::vector<int> vector(data, data + 4, queue);
+
+ boost::compute::array<int, 4> array(context);
+ boost::compute::copy(vector.begin(), vector.end(), array.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, array, (3, 6, 9, 12));
+}
+
+BOOST_AUTO_TEST_CASE(fill)
+{
+ boost::compute::array<int, 4> array(context);
+ array.fill(0);
+ CHECK_RANGE_EQUAL(int, 4, array, (0, 0, 0, 0));
+
+ array.fill(17);
+ CHECK_RANGE_EQUAL(int, 4, array, (17, 17, 17, 17));
+}
+
+BOOST_AUTO_TEST_CASE(swap)
+{
+ int data[] = { 1, 2, 6, 9 };
+ boost::compute::array<int, 4> a(context);
+ boost::compute::copy(data, data + 4, a.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 2, 6, 9));
+
+ boost::compute::array<int, 4> b(context);
+ b.fill(3);
+ CHECK_RANGE_EQUAL(int, 4, b, (3, 3, 3, 3));
+
+ a.swap(b);
+ CHECK_RANGE_EQUAL(int, 4, a, (3, 3, 3, 3));
+ CHECK_RANGE_EQUAL(int, 4, b, (1, 2, 6, 9));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_async_wait.cpp b/src/boost/libs/compute/test/test_async_wait.cpp
new file mode 100644
index 00000000..0b9eebab
--- /dev/null
+++ b/src/boost/libs/compute/test/test_async_wait.cpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestAsyncWait
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/async/wait.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(empty)
+{
+}
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+BOOST_AUTO_TEST_CASE(wait_for_copy)
+{
+ // wait list
+ compute::wait_list events;
+
+ // create host data array
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ // create vector on the device
+ compute::vector<int> vector(8, context);
+
+ // fill vector with 9's
+ compute::future<void> fill_future =
+ compute::fill_async(vector.begin(), vector.end(), 9, queue);
+
+ // wait for fill() to complete
+ compute::wait_for_all(fill_future);
+
+ // check data on the device
+ CHECK_RANGE_EQUAL(int, 8, vector, (9, 9, 9, 9, 9, 9, 9, 9));
+
+ // copy each pair of values independently and asynchronously
+ compute::event copy1 = queue.enqueue_write_buffer_async(
+ vector.get_buffer(), 0 * sizeof(int), 2 * sizeof(int), data + 0
+ );
+ compute::event copy2 = queue.enqueue_write_buffer_async(
+ vector.get_buffer(), 2 * sizeof(int), 2 * sizeof(int), data + 2
+ );
+ compute::event copy3 = queue.enqueue_write_buffer_async(
+ vector.get_buffer(), 4 * sizeof(int), 2 * sizeof(int), data + 4
+ );
+ compute::event copy4 = queue.enqueue_write_buffer_async(
+ vector.get_buffer(), 6 * sizeof(int), 2 * sizeof(int), data + 6
+ );
+
+ // wait for all copies to complete
+ compute::wait_for_all(copy1, copy2, copy3, copy4);
+
+ // check data on the device
+ CHECK_RANGE_EQUAL(int, 8, vector, (1, 2, 3, 4, 5, 6, 7, 8));
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_async_wait_guard.cpp b/src/boost/libs/compute/test/test_async_wait_guard.cpp
new file mode 100644
index 00000000..626d25bb
--- /dev/null
+++ b/src/boost/libs/compute/test/test_async_wait_guard.cpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestAsyncWaitGuard
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/async/wait_guard.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+static size_t wait_num = 0;
+
+struct waitable_object
+{
+ void wait()
+ {
+ wait_num++;
+ }
+};
+
+BOOST_AUTO_TEST_CASE(wait_guard_test)
+{
+ waitable_object waitable;
+
+ BOOST_CHECK(wait_num == 0);
+ {
+ compute::wait_guard<waitable_object> waitable_object_guard(waitable);
+ }
+ BOOST_CHECK(wait_num == 1);
+ {
+ compute::wait_guard<waitable_object> waitable_object_guard1(waitable);
+ compute::wait_guard<waitable_object> waitable_object_guard2(waitable);
+ }
+ BOOST_CHECK(wait_num == 3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_bernoulli_distribution.cpp b/src/boost/libs/compute/test/test_bernoulli_distribution.cpp
new file mode 100644
index 00000000..3172a83a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_bernoulli_distribution.cpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestBernoulliDistribution
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/bernoulli_distribution.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(bernoulli_distribution_doctest)
+{
+ boost::compute::vector<bool> vec(10, context);
+
+//! [generate]
+// initialize the default random engine
+boost::compute::default_random_engine engine(queue);
+
+// setup the bernoulli distribution to produce booleans
+// with parameter p = 0.25
+boost::compute::bernoulli_distribution<float> distribution(0.25f);
+
+// generate the random values and store them to 'vec'
+distribution.generate(vec.begin(), vec.end(), engine, queue);
+//! [generate]
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_binary_search.cpp b/src/boost/libs/compute/test/test_binary_search.cpp
new file mode 100644
index 00000000..43e4fcff
--- /dev/null
+++ b/src/boost/libs/compute/test/test_binary_search.cpp
@@ -0,0 +1,102 @@
+//---------------------------------------------------------------------------//
+// 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 TestBinarySearch
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/binary_search.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/lower_bound.hpp>
+#include <boost/compute/algorithm/upper_bound.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(binary_search_int)
+{
+ // test data = { 1, ..., 2, ..., 4, 4, 5, 7, ..., 9, ..., 10 }
+ boost::compute::vector<int> vector(size_t(4096), int(1), queue);
+ boost::compute::vector<int>::iterator first = vector.begin() + 128;
+ boost::compute::vector<int>::iterator last = first + (1024 - 128);
+ boost::compute::fill(first, last, int(2), queue);
+ last.write(4, queue); last++;
+ last.write(4, queue); last++;
+ last.write(5, queue); last++;
+ first = last;
+ last = first + 127;
+ boost::compute::fill(first, last, 7, queue);
+ first = last;
+ last = vector.end() - 1;
+ boost::compute::fill(first, last, 9, queue);
+ last.write(10, queue);
+ queue.finish();
+
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(0), queue) == false);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(1), queue) == true);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(2), queue) == true);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(3), queue) == false);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(4), queue) == true);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(5), queue) == true);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(6), queue) == false);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(7), queue) == true);
+ BOOST_CHECK(boost::compute::binary_search(vector.begin(), vector.end(), int(8), queue) == false);
+}
+
+BOOST_AUTO_TEST_CASE(range_bounds_int)
+{
+ // test data = { 1, ..., 2, ..., 4, 4, 5, 7, ..., 9, ..., 10 }
+ boost::compute::vector<int> vector(size_t(4096), int(1), queue);
+ boost::compute::vector<int>::iterator first = vector.begin() + 128;
+ boost::compute::vector<int>::iterator last = first + (1024 - 128);
+ boost::compute::fill(first, last, int(2), queue);
+ last.write(4, queue); last++; // 1024
+ last.write(4, queue); last++; // 1025
+ last.write(5, queue); last++; // 1026
+ first = last;
+ last = first + 127;
+ boost::compute::fill(first, last, 7, queue);
+ first = last;
+ last = vector.end() - 1;
+ boost::compute::fill(first, last, 9, queue);
+ last.write(10, queue);
+ queue.finish();
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(0), queue) == vector.begin());
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(0), queue) == vector.begin());
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(1), queue) == vector.begin());
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(1), queue) == vector.begin() + 128);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(2), queue) == vector.begin() + 128);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(2), queue) == vector.begin() + 1024);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(4), queue) == vector.begin() + 1024);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(4), queue) == vector.begin() + 1026);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(5), queue) == vector.begin() + 1026);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(5), queue) == vector.begin() + 1027);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(6), queue) == vector.begin() + 1027);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(6), queue) == vector.begin() + 1027);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(7), queue) == vector.begin() + 1027);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(7), queue) == vector.begin() + (1027 + 127));
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(9), queue) == vector.begin() + (1027 + 127));
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(9), queue) == vector.end() - 1);
+
+ BOOST_CHECK(boost::compute::lower_bound(vector.begin(), vector.end(), int(10), queue) == vector.end() - 1);
+ BOOST_CHECK(boost::compute::upper_bound(vector.begin(), vector.end(), int(10), queue) == vector.end());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_buffer.cpp b/src/boost/libs/compute/test/test_buffer.cpp
new file mode 100644
index 00000000..e86c41be
--- /dev/null
+++ b/src/boost/libs/compute/test/test_buffer.cpp
@@ -0,0 +1,213 @@
+//---------------------------------------------------------------------------//
+// 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 TestBuffer
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/bind.hpp>
+
+#ifdef BOOST_COMPUTE_USE_CPP11
+#include <mutex>
+#include <future>
+#endif // BOOST_COMPUTE_USE_CPP11
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ bc::buffer buffer(context, 100);
+ BOOST_CHECK_EQUAL(buffer.size(), size_t(100));
+ BOOST_VERIFY(buffer.max_size() > buffer.size());
+}
+
+BOOST_AUTO_TEST_CASE(cl_context)
+{
+ bc::buffer buffer(context, 100);
+ BOOST_VERIFY(buffer.get_context() == context);
+}
+
+BOOST_AUTO_TEST_CASE(equality_operator)
+{
+ bc::buffer a(context, 10);
+ bc::buffer b(context, 10);
+ BOOST_VERIFY(a == a);
+ BOOST_VERIFY(b == b);
+ BOOST_VERIFY(!(a == b));
+ BOOST_VERIFY(a != b);
+
+ a = b;
+ BOOST_VERIFY(a == b);
+ BOOST_VERIFY(!(a != b));
+}
+
+BOOST_AUTO_TEST_CASE(construct_from_cl_mem)
+{
+ // create cl_mem
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_WRITE, 16, 0, 0);
+ BOOST_VERIFY(mem);
+
+ // create boost::compute::buffer
+ boost::compute::buffer buffer(mem);
+
+ // check buffer
+ BOOST_CHECK(buffer.get() == mem);
+ BOOST_CHECK(buffer.get_context() == context);
+ BOOST_CHECK_EQUAL(buffer.size(), size_t(16));
+
+ // cleanup cl_mem
+ clReleaseMemObject(mem);
+}
+
+BOOST_AUTO_TEST_CASE(reference_count)
+{
+ using boost::compute::uint_;
+
+ boost::compute::buffer buf(context, 16);
+ BOOST_CHECK_GE(buf.reference_count(), uint_(1));
+}
+
+BOOST_AUTO_TEST_CASE(get_size)
+{
+ boost::compute::buffer buf(context, 16);
+ BOOST_CHECK_EQUAL(buf.size(), size_t(16));
+ BOOST_CHECK_EQUAL(buf.get_info<CL_MEM_SIZE>(), size_t(16));
+ BOOST_CHECK_EQUAL(buf.get_info<size_t>(CL_MEM_SIZE), size_t(16));
+}
+
+#ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+BOOST_AUTO_TEST_CASE(move_constructor)
+{
+ boost::compute::buffer buffer1(context, 16);
+ BOOST_CHECK(buffer1.get() != 0);
+ BOOST_CHECK_EQUAL(buffer1.size(), size_t(16));
+
+ boost::compute::buffer buffer2(std::move(buffer1));
+ BOOST_CHECK(buffer1.get() == 0);
+ BOOST_CHECK(buffer2.get() != 0);
+ BOOST_CHECK_EQUAL(buffer2.size(), size_t(16));
+}
+#endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+BOOST_AUTO_TEST_CASE(clone_buffer)
+{
+ boost::compute::buffer buffer1(context, 16);
+ boost::compute::buffer buffer2 = buffer1.clone(queue);
+ BOOST_CHECK(buffer1.get() != buffer2.get());
+ BOOST_CHECK_EQUAL(buffer1.size(), buffer2.size());
+ BOOST_CHECK(buffer1.get_memory_flags() == buffer2.get_memory_flags());
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
+#ifdef BOOST_COMPUTE_USE_CPP11
+std::mutex callback_mutex;
+std::condition_variable callback_condition_variable;
+
+static void BOOST_COMPUTE_CL_CALLBACK
+destructor_callback_function(cl_mem, void *user_data)
+{
+ std::lock_guard<std::mutex> lock(callback_mutex);
+
+ bool *flag = static_cast<bool *>(user_data);
+ *flag = true;
+
+ callback_condition_variable.notify_one();
+}
+
+BOOST_AUTO_TEST_CASE(destructor_callback)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(!supports_destructor_callback(device))
+ {
+ return;
+ }
+
+ bool invoked = false;
+ {
+ boost::compute::buffer buf(context, 128);
+ buf.set_destructor_callback(destructor_callback_function, &invoked);
+ }
+
+ std::unique_lock<std::mutex> lock(callback_mutex);
+ callback_condition_variable.wait_for(
+ lock, std::chrono::seconds(1), [&](){ return invoked; }
+ );
+ BOOST_CHECK(invoked == true);
+}
+
+static void BOOST_COMPUTE_CL_CALLBACK
+destructor_templated_callback_function(bool *flag)
+{
+ std::lock_guard<std::mutex> lock(callback_mutex);
+ *flag = true;
+ callback_condition_variable.notify_one();
+}
+
+BOOST_AUTO_TEST_CASE(destructor_templated_callback)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(!supports_destructor_callback(device))
+ {
+ return;
+ }
+
+ bool invoked = false;
+ {
+ boost::compute::buffer buf(context, 128);
+ buf.set_destructor_callback(boost::bind(destructor_templated_callback_function, &invoked));
+ }
+
+ std::unique_lock<std::mutex> lock(callback_mutex);
+ callback_condition_variable.wait_for(
+ lock, std::chrono::seconds(1), [&](){ return invoked; }
+ );
+
+ BOOST_CHECK(invoked == true);
+}
+
+#endif // BOOST_COMPUTE_USE_CPP11
+
+BOOST_AUTO_TEST_CASE(create_subbuffer)
+{
+ REQUIRES_OPENCL_VERSION(1, 1);
+
+ size_t base_addr_align = device.get_info<CL_DEVICE_MEM_BASE_ADDR_ALIGN>() / 8;
+ size_t multiplier = 16;
+ size_t buffer_size = base_addr_align * multiplier;
+ size_t subbuffer_size = 64;
+ boost::compute::buffer buffer(context, buffer_size);
+
+ for(size_t i = 0; i < multiplier; ++i)
+ {
+ boost::compute::buffer subbuffer = buffer.create_subbuffer(
+ boost::compute::buffer::read_write, base_addr_align * i, subbuffer_size);
+ BOOST_CHECK(buffer.get() != subbuffer.get());
+ BOOST_CHECK_EQUAL(subbuffer.size(), subbuffer_size);
+ }
+}
+
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
+
+BOOST_AUTO_TEST_CASE(create_buffer_doctest)
+{
+//! [constructor]
+boost::compute::buffer buf(context, 32 * sizeof(float));
+//! [constructor]
+
+ BOOST_CHECK_EQUAL(buf.size(), 32 * sizeof(float));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_buffer_allocator.cpp b/src/boost/libs/compute/test/test_buffer_allocator.cpp
new file mode 100644
index 00000000..abc8c6aa
--- /dev/null
+++ b/src/boost/libs/compute/test/test_buffer_allocator.cpp
@@ -0,0 +1,29 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestBufferAllocator
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/allocator/buffer_allocator.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(allocate)
+{
+ compute::buffer_allocator<int> allocator(context);
+
+ typedef compute::buffer_allocator<int>::pointer pointer;
+ pointer x = allocator.allocate(10);
+ allocator.deallocate(x, 10);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_buffer_iterator.cpp b/src/boost/libs/compute/test/test_buffer_iterator.cpp
new file mode 100644
index 00000000..eb448188
--- /dev/null
+++ b/src/boost/libs/compute/test/test_buffer_iterator.cpp
@@ -0,0 +1,69 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestBufferIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ compute::buffer_iterator<int>::value_type, int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ compute::buffer_iterator<float>::value_type, float
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(reverse_external_buffer_doctest)
+{
+ int data[] = { 1, 2, 3 };
+ compute::buffer buffer(context, 3 * sizeof(int));
+ queue.enqueue_write_buffer(buffer, 0, 3 * sizeof(int), data);
+
+ cl_mem external_mem_obj = buffer.get();
+
+//! [reverse_external_buffer]
+// create a buffer object wrapping the cl_mem object
+boost::compute::buffer buf(external_mem_obj);
+
+// reverse the values in the buffer
+boost::compute::reverse(
+ boost::compute::make_buffer_iterator<int>(buf, 0),
+ boost::compute::make_buffer_iterator<int>(buf, 3),
+ queue
+);
+//! [reverse_external_buffer]
+
+ queue.enqueue_read_buffer(buf, 0, 3 * sizeof(int), data);
+ BOOST_CHECK_EQUAL(data[0], 3);
+ BOOST_CHECK_EQUAL(data[1], 2);
+ BOOST_CHECK_EQUAL(data[2], 1);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_clamp_range.cpp b/src/boost/libs/compute/test/test_clamp_range.cpp
new file mode 100644
index 00000000..985ae2d6
--- /dev/null
+++ b/src/boost/libs/compute/test/test_clamp_range.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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 TestClampRange
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/experimental/clamp_range.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(clamp_float_range)
+{
+ float data[] = { 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f };
+ compute::vector<float> input(data, data + 8, queue);
+
+ compute::vector<float> result(8, context);
+ compute::experimental::clamp_range(
+ input.begin(),
+ input.end(),
+ result.begin(),
+ 3.f, // low
+ 6.f, // high
+ queue
+ );
+ CHECK_RANGE_EQUAL(
+ float, 8, result,
+ (3.f, 3.f, 3.f, 4.f, 5.f, 6.f, 6.f, 6.f)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_closure.cpp b/src/boost/libs/compute/test/test_closure.cpp
new file mode 100644
index 00000000..0747cec7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_closure.cpp
@@ -0,0 +1,223 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestClosure
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/closure.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/algorithm/transform_reduce.hpp>
+#include <boost/compute/container/array.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(add_two)
+{
+ int two = 2;
+ BOOST_COMPUTE_CLOSURE(int, add_two, (int x), (two),
+ {
+ return x + two;
+ });
+
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(), add_two, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (3, 4, 5, 6));
+}
+
+BOOST_AUTO_TEST_CASE(add_two_and_pi)
+{
+ int two = 2;
+ float pi = 3.14f;
+ BOOST_COMPUTE_CLOSURE(float, add_two_and_pi, (float x), (two, pi),
+ {
+ return x + two + pi;
+ });
+
+ float data[] = { 1.9f, 2.2f, 3.4f, 4.7f };
+ compute::vector<float> vector(data, data + 4, queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(), add_two_and_pi, queue
+ );
+
+ std::vector<float> results(4);
+ compute::copy(vector.begin(), vector.end(), results.begin(), queue);
+ BOOST_CHECK_CLOSE(results[0], 7.04f, 1e-6);
+ BOOST_CHECK_CLOSE(results[1], 7.34f, 1e-6);
+ BOOST_CHECK_CLOSE(results[2], 8.54f, 1e-6);
+ BOOST_CHECK_CLOSE(results[3], 9.84f, 1e-6);
+}
+
+BOOST_AUTO_TEST_CASE(add_y)
+{
+ // setup input and output vectors
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> input(data, data + 4, queue);
+ compute::vector<int> output(4, context);
+
+ // make closure which adds 'y' to each value
+ int y = 2;
+ BOOST_COMPUTE_CLOSURE(int, add_y, (int x), (y),
+ {
+ return x + y;
+ });
+
+ compute::transform(
+ input.begin(), input.end(), output.begin(), add_y, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (3, 4, 5, 6));
+
+ // change y and run again
+ y = 4;
+
+ compute::transform(
+ input.begin(), input.end(), output.begin(), add_y, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (5, 6, 7, 8));
+}
+
+BOOST_AUTO_TEST_CASE(scale_add_vec)
+{
+ const int N = 10;
+ float s = 4.5;
+ compute::vector<float> a(N, context);
+ compute::vector<float> b(N, context);
+ a.assign(N, 1.0f, queue);
+ b.assign(N, 2.0f, queue);
+
+ BOOST_COMPUTE_CLOSURE(float, scaleAddVec, (float b, float a), (s),
+ {
+ return b * s + a;
+ });
+ compute::transform(b.begin(), b.end(), a.begin(), b.begin(), scaleAddVec, queue);
+}
+
+BOOST_AUTO_TEST_CASE(capture_vector)
+{
+ int data[] = { 6, 7, 8, 9 };
+ compute::vector<int> vec(data, data + 4, queue);
+
+ BOOST_COMPUTE_CLOSURE(int, get_vec, (int i), (vec),
+ {
+ return vec[i];
+ });
+
+ // run using a counting iterator to copy from vec to output
+ compute::vector<int> output(4, context);
+ compute::transform(
+ compute::make_counting_iterator(0),
+ compute::make_counting_iterator(4),
+ output.begin(),
+ get_vec,
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (6, 7, 8, 9));
+
+ // fill vec with 4's and run again
+ compute::fill(vec.begin(), vec.end(), 4, queue);
+ compute::transform(
+ compute::make_counting_iterator(0),
+ compute::make_counting_iterator(4),
+ output.begin(),
+ get_vec,
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (4, 4, 4, 4));
+}
+
+BOOST_AUTO_TEST_CASE(capture_array)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::array<int, 4> array(context);
+ compute::copy(data, data + 4, array.begin(), queue);
+
+ BOOST_COMPUTE_CLOSURE(int, negative_array_value, (int i), (array),
+ {
+ return -array[i];
+ });
+
+ compute::vector<int> output(4, context);
+ compute::transform(
+ compute::make_counting_iterator(0),
+ compute::make_counting_iterator(4),
+ output.begin(),
+ negative_array_value,
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (-1, -2, -3, -4));
+}
+
+BOOST_AUTO_TEST_CASE(triangle_area)
+{
+ using compute::uint4_;
+ using compute::float4_;
+
+ compute::vector<uint4_> triangle_indices(context);
+ compute::vector<float4_> triangle_vertices(context);
+
+ triangle_vertices.push_back(float4_(0, 0, 0, 1), queue);
+ triangle_vertices.push_back(float4_(1, 1, 0, 1), queue);
+ triangle_vertices.push_back(float4_(1, 0, 0, 1), queue);
+ triangle_vertices.push_back(float4_(2, 0, 0, 1), queue);
+
+ triangle_indices.push_back(uint4_(0, 1, 2, 0), queue);
+ triangle_indices.push_back(uint4_(2, 1, 3, 0), queue);
+
+ queue.finish();
+
+ BOOST_COMPUTE_CLOSURE(float, triangle_area, (const uint4_ i), (triangle_vertices),
+ {
+ // load triangle vertices
+ const float4 a = triangle_vertices[i.x];
+ const float4 b = triangle_vertices[i.y];
+ const float4 c = triangle_vertices[i.z];
+
+ // return area of triangle
+ return length(cross(b-a, c-a)) / 2;
+ });
+
+ // compute area of each triangle
+ compute::vector<float> triangle_areas(triangle_indices.size(), context);
+
+ compute::transform(
+ triangle_indices.begin(),
+ triangle_indices.end(),
+ triangle_areas.begin(),
+ triangle_area,
+ queue
+ );
+
+ // compute total area of all triangles
+ float total_area = 0;
+
+ compute::transform_reduce(
+ triangle_indices.begin(),
+ triangle_indices.end(),
+ &total_area,
+ triangle_area,
+ compute::plus<float>(),
+ queue
+ );
+ BOOST_CHECK_CLOSE(total_area, 1.f, 1e-6);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_command_queue.cpp b/src/boost/libs/compute/test/test_command_queue.cpp
new file mode 100644
index 00000000..dc409795
--- /dev/null
+++ b/src/boost/libs/compute/test/test_command_queue.cpp
@@ -0,0 +1,352 @@
+//---------------------------------------------------------------------------//
+// 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 TestCommandQueue
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+#include <boost/compute/detail/diagnostic.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(get_context)
+{
+ BOOST_VERIFY(queue.get_context() == context);
+ BOOST_VERIFY(queue.get_info<CL_QUEUE_CONTEXT>() == context.get());
+}
+
+BOOST_AUTO_TEST_CASE(get_device)
+{
+ BOOST_VERIFY(queue.get_info<CL_QUEUE_DEVICE>() == device.get());
+}
+
+BOOST_AUTO_TEST_CASE(equality_operator)
+{
+ compute::command_queue queue1(context, device);
+ BOOST_CHECK(queue1 == queue1);
+
+ compute::command_queue queue2 = queue1;
+ BOOST_CHECK(queue1 == queue2);
+
+ compute::command_queue queue3(context, device);
+ BOOST_CHECK(queue1 != queue3);
+}
+
+BOOST_AUTO_TEST_CASE(event_profiling)
+{
+ bc::command_queue queue(context, device, bc::command_queue::enable_profiling);
+
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ bc::buffer buffer(context, sizeof(data));
+
+ bc::event event =
+ queue.enqueue_write_buffer_async(buffer,
+ 0,
+ sizeof(data),
+ static_cast<const void *>(data));
+ queue.finish();
+
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_queued);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_submit);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_start);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_end);
+}
+
+BOOST_AUTO_TEST_CASE(kernel_profiling)
+{
+ // create queue with profiling enabled
+ boost::compute::command_queue queue(
+ context, device, boost::compute::command_queue::enable_profiling
+ );
+
+ // input data
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::buffer buffer(context, sizeof(data));
+
+ // copy input data to device
+ queue.enqueue_write_buffer(buffer, 0, sizeof(data), data);
+
+ // setup kernel
+ const char source[] =
+ "__kernel void iscal(__global int *buffer, int alpha)\n"
+ "{\n"
+ " buffer[get_global_id(0)] *= alpha;\n"
+ "}\n";
+
+ boost::compute::program program =
+ boost::compute::program::create_with_source(source, context);
+ program.build();
+
+ boost::compute::kernel kernel(program, "iscal");
+ kernel.set_arg(0, buffer);
+ kernel.set_arg(1, 2);
+
+ // execute kernel
+ size_t global_work_offset = 0;
+ size_t global_work_size = 8;
+
+ boost::compute::event event =
+ queue.enqueue_nd_range_kernel(kernel,
+ size_t(1),
+ &global_work_offset,
+ &global_work_size,
+ 0);
+
+ // wait until kernel is finished
+ event.wait();
+
+ // check profiling information
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_queued);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_submit);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_start);
+ event.get_profiling_info<cl_ulong>(bc::event::profiling_command_end);
+
+ // read results back to host
+ queue.enqueue_read_buffer(buffer, 0, sizeof(data), data);
+
+ // check results
+ BOOST_CHECK_EQUAL(data[0], 2);
+ BOOST_CHECK_EQUAL(data[1], 4);
+ BOOST_CHECK_EQUAL(data[2], 6);
+ BOOST_CHECK_EQUAL(data[3], 8);
+ BOOST_CHECK_EQUAL(data[4], 10);
+ BOOST_CHECK_EQUAL(data[5], 12);
+ BOOST_CHECK_EQUAL(data[6], 14);
+ BOOST_CHECK_EQUAL(data[7], 16);
+}
+
+BOOST_AUTO_TEST_CASE(construct_from_cl_command_queue)
+{
+ // create cl_command_queue
+ cl_command_queue cl_queue;
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+ if (device.check_version(2, 0)){ // runtime check
+ cl_queue =
+ clCreateCommandQueueWithProperties(context, device.id(), 0, 0);
+ } else
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+ {
+ // Suppress deprecated declarations warning
+ BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
+ cl_queue =
+ clCreateCommandQueue(context, device.id(), 0, 0);
+ BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
+ }
+ BOOST_VERIFY(cl_queue);
+
+ // create boost::compute::command_queue
+ boost::compute::command_queue queue(cl_queue);
+
+ // check queue
+ BOOST_CHECK(queue.get_context() == context);
+ BOOST_CHECK(cl_command_queue(queue) == cl_queue);
+
+ // cleanup cl_command_queue
+ clReleaseCommandQueue(cl_queue);
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
+BOOST_AUTO_TEST_CASE(write_buffer_rect)
+{
+ REQUIRES_OPENCL_VERSION(1, 1);
+
+ // skip this test on AMD GPUs due to a buggy implementation
+ // of the clEnqueueWriteBufferRect() function
+ if(device.vendor() == "Advanced Micro Devices, Inc." &&
+ device.type() & boost::compute::device::gpu){
+ std::cerr << "skipping write_buffer_rect test on AMD GPU" << std::endl;
+ return;
+ }
+
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::buffer buffer(context, 8 * sizeof(int));
+
+ // copy every other value to the buffer
+ size_t buffer_origin[] = { 0, 0, 0 };
+ size_t host_origin[] = { 0, 0, 0 };
+ size_t region[] = { sizeof(int), sizeof(int), 1 };
+
+ queue.enqueue_write_buffer_rect(
+ buffer,
+ buffer_origin,
+ host_origin,
+ region,
+ sizeof(int),
+ 0,
+ 2 * sizeof(int),
+ 0,
+ data
+ );
+
+ // check output values
+ int output[4];
+ queue.enqueue_read_buffer(buffer, 0, 4 * sizeof(int), output);
+ BOOST_CHECK_EQUAL(output[0], 1);
+ BOOST_CHECK_EQUAL(output[1], 3);
+ BOOST_CHECK_EQUAL(output[2], 5);
+ BOOST_CHECK_EQUAL(output[3], 7);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
+
+static bool nullary_kernel_executed = false;
+
+static void nullary_kernel()
+{
+ nullary_kernel_executed = true;
+}
+
+BOOST_AUTO_TEST_CASE(native_kernel)
+{
+ cl_device_exec_capabilities exec_capabilities =
+ device.get_info<CL_DEVICE_EXECUTION_CAPABILITIES>();
+ if(!(exec_capabilities & CL_EXEC_NATIVE_KERNEL)){
+ std::cerr << "skipping native_kernel test: "
+ << "device does not support CL_EXEC_NATIVE_KERNEL"
+ << std::endl;
+ return;
+ }
+
+ compute::vector<int> vector(1000, context);
+ compute::fill(vector.begin(), vector.end(), 42, queue);
+ BOOST_CHECK_EQUAL(nullary_kernel_executed, false);
+ queue.enqueue_native_kernel(&nullary_kernel);
+ queue.finish();
+ BOOST_CHECK_EQUAL(nullary_kernel_executed, true);
+}
+
+BOOST_AUTO_TEST_CASE(copy_with_wait_list)
+{
+ int data1[] = { 1, 3, 5, 7 };
+ int data2[] = { 2, 4, 6, 8 };
+
+ compute::buffer buf1(context, 4 * sizeof(int));
+ compute::buffer buf2(context, 4 * sizeof(int));
+
+ compute::event write_event1 =
+ queue.enqueue_write_buffer_async(buf1, 0, buf1.size(), data1);
+
+ compute::event write_event2 =
+ queue.enqueue_write_buffer_async(buf2, 0, buf2.size(), data2);
+
+ compute::event read_event1 =
+ queue.enqueue_read_buffer_async(buf1, 0, buf1.size(), data2, write_event1);
+
+ compute::event read_event2 =
+ queue.enqueue_read_buffer_async(buf2, 0, buf2.size(), data1, write_event2);
+
+ read_event1.wait();
+ read_event2.wait();
+
+ CHECK_HOST_RANGE_EQUAL(int, 4, data1, (2, 4, 6, 8));
+ CHECK_HOST_RANGE_EQUAL(int, 4, data2, (1, 3, 5, 7));
+}
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+BOOST_AUTO_TEST_CASE(enqueue_kernel_with_extents)
+{
+ using boost::compute::dim;
+ using boost::compute::uint_;
+
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void foo(__global int *output1, __global int *output2)
+ {
+ output1[get_global_id(0)] = get_local_id(0);
+ output2[get_global_id(1)] = get_local_id(1);
+ }
+ );
+
+ compute::kernel kernel =
+ compute::kernel::create_with_source(source, "foo", context);
+
+ compute::vector<uint_> output1(4, context);
+ compute::vector<uint_> output2(4, context);
+
+ kernel.set_arg(0, output1);
+ kernel.set_arg(1, output2);
+
+ queue.enqueue_nd_range_kernel(kernel, dim(0, 0), dim(4, 4), dim(1, 1));
+
+ CHECK_RANGE_EQUAL(int, 4, output1, (0, 0, 0, 0));
+ CHECK_RANGE_EQUAL(int, 4, output2, (0, 0, 0, 0));
+
+ // Maximum number of work-items that can be specified in each
+ // dimension of the work-group to clEnqueueNDRangeKernel.
+ std::vector<size_t> max_work_item_sizes =
+ device.get_info<CL_DEVICE_MAX_WORK_ITEM_SIZES>();
+
+ if(max_work_item_sizes[0] < size_t(2)) {
+ return;
+ }
+
+ queue.enqueue_nd_range_kernel(kernel, dim(0, 0), dim(4, 4), dim(2, 1));
+
+ CHECK_RANGE_EQUAL(int, 4, output1, (0, 1, 0, 1));
+ CHECK_RANGE_EQUAL(int, 4, output2, (0, 0, 0, 0));
+
+ if(max_work_item_sizes[1] < size_t(2)) {
+ return;
+ }
+
+ queue.enqueue_nd_range_kernel(kernel, dim(0, 0), dim(4, 4), dim(2, 2));
+
+ CHECK_RANGE_EQUAL(int, 4, output1, (0, 1, 0, 1));
+ CHECK_RANGE_EQUAL(int, 4, output2, (0, 1, 0, 1));
+}
+#endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(get_default_device_queue)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ boost::compute::command_queue default_device_queue(
+ context, device,
+ boost::compute::command_queue::on_device |
+ boost::compute::command_queue::on_device_default |
+ boost::compute::command_queue::enable_out_of_order_execution
+ );
+ BOOST_CHECK_NO_THROW(queue.get_info<CL_QUEUE_DEVICE_DEFAULT>());
+ BOOST_CHECK_EQUAL(
+ queue.get_default_device_queue(),
+ default_device_queue
+ );
+}
+
+BOOST_AUTO_TEST_CASE(set_as_default_device_queue)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ boost::compute::command_queue new_default_device_queue(
+ context, device,
+ boost::compute::command_queue::on_device |
+ boost::compute::command_queue::enable_out_of_order_execution
+ );
+ new_default_device_queue.set_as_default_device_queue();
+ BOOST_CHECK_EQUAL(
+ queue.get_default_device_queue(),
+ new_default_device_queue
+ );
+}
+#endif
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_complex.cpp b/src/boost/libs/compute/test/test_complex.cpp
new file mode 100644
index 00000000..35e143d1
--- /dev/null
+++ b/src/boost/libs/compute/test/test_complex.cpp
@@ -0,0 +1,173 @@
+//---------------------------------------------------------------------------//
+// 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 TestComplex
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/complex.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+
+#include "context_setup.hpp"
+
+// copies a vector of complex<float>'s on the host to the device
+BOOST_AUTO_TEST_CASE(copy_complex_vector)
+{
+ std::vector<std::complex<float> > host_vector;
+ host_vector.push_back(std::complex<float>(1.0f, 2.0f));
+ host_vector.push_back(std::complex<float>(-2.0f, 1.0f));
+ host_vector.push_back(std::complex<float>(1.0f, -2.0f));
+ host_vector.push_back(std::complex<float>(-2.0f, -1.0f));
+
+ boost::compute::vector<std::complex<float> > device_vector(context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+ queue.finish();
+ BOOST_CHECK_EQUAL(std::complex<float>(device_vector[0]), std::complex<float>(1.0f, 2.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(device_vector[1]), std::complex<float>(-2.0f, 1.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(device_vector[2]), std::complex<float>(1.0f, -2.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(device_vector[3]), std::complex<float>(-2.0f, -1.0f));
+}
+
+// fills a vector of complex<float>'s on the device with a constant value
+BOOST_AUTO_TEST_CASE(fill_complex_vector)
+{
+ boost::compute::vector<std::complex<float> > vector(6, context);
+ boost::compute::fill(
+ vector.begin(),
+ vector.end(),
+ std::complex<float>(2.0f, 5.0f),
+ queue
+ );
+ queue.finish();
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[0]), std::complex<float>(2.0f, 5.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[1]), std::complex<float>(2.0f, 5.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[2]), std::complex<float>(2.0f, 5.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[3]), std::complex<float>(2.0f, 5.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[4]), std::complex<float>(2.0f, 5.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(vector[5]), std::complex<float>(2.0f, 5.0f));
+}
+
+// extracts the real and imag components of a vector of complex<float>'s using
+// transform with the real() and imag() functions
+BOOST_AUTO_TEST_CASE(extract_real_and_imag)
+{
+ boost::compute::vector<std::complex<float> > vector(context);
+ vector.push_back(std::complex<float>(1.0f, 3.0f), queue);
+ vector.push_back(std::complex<float>(3.0f, 1.0f), queue);
+ vector.push_back(std::complex<float>(5.0f, -1.0f), queue);
+ vector.push_back(std::complex<float>(7.0f, -3.0f), queue);
+ vector.push_back(std::complex<float>(9.0f, -5.0f), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(5));
+
+ boost::compute::vector<float> reals(5, context);
+ boost::compute::transform(
+ vector.begin(),
+ vector.end(),
+ reals.begin(),
+ boost::compute::real<float>(),
+ queue
+ );
+ queue.finish();
+ BOOST_CHECK_EQUAL(float(reals[0]), float(1.0f));
+ BOOST_CHECK_EQUAL(float(reals[1]), float(3.0f));
+ BOOST_CHECK_EQUAL(float(reals[2]), float(5.0f));
+ BOOST_CHECK_EQUAL(float(reals[3]), float(7.0f));
+ BOOST_CHECK_EQUAL(float(reals[4]), float(9.0f));
+
+ boost::compute::vector<float> imags(5, context);
+ boost::compute::transform(
+ vector.begin(),
+ vector.end(),
+ imags.begin(),
+ boost::compute::imag<float>(),
+ queue
+ );
+ queue.finish();
+ BOOST_CHECK_EQUAL(float(imags[0]), float(3.0f));
+ BOOST_CHECK_EQUAL(float(imags[1]), float(1.0f));
+ BOOST_CHECK_EQUAL(float(imags[2]), float(-1.0f));
+ BOOST_CHECK_EQUAL(float(imags[3]), float(-3.0f));
+ BOOST_CHECK_EQUAL(float(imags[4]), float(-5.0f));
+}
+
+// compute the complex conjugate of a vector of complex<float>'s
+BOOST_AUTO_TEST_CASE(complex_conj)
+{
+ boost::compute::vector<std::complex<float> > input(context);
+ input.push_back(std::complex<float>(1.0f, 3.0f), queue);
+ input.push_back(std::complex<float>(3.0f, 1.0f), queue);
+ input.push_back(std::complex<float>(5.0f, -1.0f), queue);
+ input.push_back(std::complex<float>(7.0f, -3.0f), queue);
+ input.push_back(std::complex<float>(9.0f, -5.0f), queue);
+ BOOST_CHECK_EQUAL(input.size(), size_t(5));
+
+ boost::compute::vector<std::complex<float> > output(5, context);
+ boost::compute::transform(
+ input.begin(),
+ input.end(),
+ output.begin(),
+ boost::compute::conj<float>(),
+ queue
+ );
+ queue.finish();
+ BOOST_CHECK_EQUAL(std::complex<float>(output[0]), std::complex<float>(1.0f, -3.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(output[1]), std::complex<float>(3.0f, -1.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(output[2]), std::complex<float>(5.0f, 1.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(output[3]), std::complex<float>(7.0f, 3.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(output[4]), std::complex<float>(9.0f, 5.0f));
+}
+
+// check type_name() for std::complex
+BOOST_AUTO_TEST_CASE(complex_type_name)
+{
+ BOOST_CHECK(
+ std::strcmp(
+ boost::compute::type_name<std::complex<float> >(),
+ "float2"
+ ) == 0
+ );
+}
+
+BOOST_AUTO_TEST_CASE(transform_multiply)
+{
+ boost::compute::vector<std::complex<float> > x(context);
+ x.push_back(std::complex<float>(1.0f, 2.0f), queue);
+ x.push_back(std::complex<float>(-2.0f, 5.0f), queue);
+
+ boost::compute::vector<std::complex<float> > y(context);
+ y.push_back(std::complex<float>(3.0f, 4.0f), queue);
+ y.push_back(std::complex<float>(2.0f, -1.0f), queue);
+
+ boost::compute::vector<std::complex<float> > z(2, context);
+
+ // z = x * y
+ boost::compute::transform(
+ x.begin(),
+ x.end(),
+ y.begin(),
+ z.begin(),
+ boost::compute::multiplies<std::complex<float> >(),
+ queue
+ );
+ queue.finish();
+
+ BOOST_CHECK_EQUAL(std::complex<float>(z[0]), std::complex<float>(-5.0f, 10.0f));
+ BOOST_CHECK_EQUAL(std::complex<float>(z[1]), std::complex<float>(1.0f, 12.0f));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_constant_iterator.cpp b/src/boost/libs/compute/test/test_constant_iterator.cpp
new file mode 100644
index 00000000..96cf29db
--- /dev/null
+++ b/src/boost/libs/compute/test/test_constant_iterator.cpp
@@ -0,0 +1,96 @@
+//---------------------------------------------------------------------------//
+// 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 TestConstantIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::constant_iterator<int>::value_type,
+ int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::constant_iterator<float>::value_type,
+ float
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(distance)
+{
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_constant_iterator(128, 0),
+ boost::compute::make_constant_iterator(128, 10)
+ ),
+ std::ptrdiff_t(10)
+ );
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_constant_iterator(256, 5),
+ boost::compute::make_constant_iterator(256, 10)
+ ),
+ std::ptrdiff_t(5)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy(
+ boost::compute::make_constant_iterator(42, 0),
+ boost::compute::make_constant_iterator(42, 10),
+ vector.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(
+ int, 10, vector,
+ (42, 42, 42, 42, 42, 42, 42, 42, 42, 42)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(fill_with_copy_doctest)
+{
+//! [fill_with_copy]
+using boost::compute::make_constant_iterator;
+
+boost::compute::vector<int> result(5, context);
+
+boost::compute::copy(
+ make_constant_iterator(42, 0),
+ make_constant_iterator(42, result.size()),
+ result.begin(),
+ queue
+);
+
+// result == { 42, 42, 42, 42, 42 }
+//! [fill_with_copy]
+
+ CHECK_RANGE_EQUAL(int, 5, result, (42, 42, 42, 42, 42));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_context.cpp b/src/boost/libs/compute/test/test_context.cpp
new file mode 100644
index 00000000..8155dd2e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_context.cpp
@@ -0,0 +1,67 @@
+//---------------------------------------------------------------------------//
+// 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 TestContext
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(construct_from_cl_context)
+{
+ cl_device_id id = device.id();
+
+ // create cl_context
+ cl_context ctx = clCreateContext(0, 1, &id, 0, 0, 0);
+ BOOST_VERIFY(ctx);
+
+ // create boost::compute::context
+ boost::compute::context context(ctx);
+
+ // check context
+ BOOST_CHECK(cl_context(context) == ctx);
+
+ // cleanup cl_context
+ clReleaseContext(ctx);
+}
+
+#ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+BOOST_AUTO_TEST_CASE(move_constructor)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context1(device);
+ BOOST_VERIFY(cl_context(context1) != cl_context());
+
+ boost::compute::context context2(std::move(context1));
+ BOOST_VERIFY(cl_context(context2) != cl_context());
+ BOOST_VERIFY(cl_context(context1) == cl_context());
+}
+#endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+BOOST_AUTO_TEST_CASE(multiple_devices)
+{
+ const std::vector<compute::platform> &platforms = compute::system::platforms();
+ for(size_t i = 0; i < platforms.size(); i++){
+ const compute::platform &platform = platforms[i];
+
+ // create a context for containing all devices in the platform
+ compute::context ctx(platform.devices());
+
+ // check device count
+ BOOST_CHECK_EQUAL(ctx.get_devices().size(), platform.device_count());
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_context_error.cpp b/src/boost/libs/compute/test/test_context_error.cpp
new file mode 100644
index 00000000..29186479
--- /dev/null
+++ b/src/boost/libs/compute/test/test_context_error.cpp
@@ -0,0 +1,25 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Fabian Köhler <fabian2804@googlemail.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 TestContextError
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/exception/context_error.hpp>
+
+BOOST_AUTO_TEST_CASE(what)
+{
+ boost::compute::context context = boost::compute::system::default_context();
+ boost::compute::context_error error(&context, "Test", 0, 0);
+ BOOST_CHECK_EQUAL(std::string(error.what()), std::string("Test"));
+ BOOST_CHECK(*error.get_context_ptr() == context);
+ BOOST_CHECK(error.get_private_info_ptr() == 0);
+ BOOST_CHECK(error.get_private_info_size() == 0);
+}
diff --git a/src/boost/libs/compute/test/test_copy.cpp b/src/boost/libs/compute/test/test_copy.cpp
new file mode 100644
index 00000000..1ceb7853
--- /dev/null
+++ b/src/boost/libs/compute/test/test_copy.cpp
@@ -0,0 +1,411 @@
+//---------------------------------------------------------------------------//
+// 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 TestCopy
+#include <boost/test/unit_test.hpp>
+
+#include <list>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <iterator>
+#include <iostream>
+
+#include <boost/compute/svm.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+#include <boost/compute/iterator/detail/swizzle_iterator.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(copy_on_device)
+{
+ float data[] = { 6.1f, 10.2f, 19.3f, 25.4f };
+ bc::vector<float> a(4, context);
+ bc::copy(data, data + 4, a.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 4, a, (6.1f, 10.2f, 19.3f, 25.4f));
+
+ bc::vector<float> b(4, context);
+ bc::fill(b.begin(), b.end(), 0, queue);
+ CHECK_RANGE_EQUAL(float, 4, b, (0.0f, 0.0f, 0.0f, 0.0f));
+
+ bc::copy(a.begin(), a.end(), b.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 4, b, (6.1f, 10.2f, 19.3f, 25.4f));
+
+ bc::vector<float> c(context);
+ bc::copy(c.begin(), c.end(), b.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 4, b, (6.1f, 10.2f, 19.3f, 25.4f));
+}
+
+BOOST_AUTO_TEST_CASE(copy_on_device_device_ptr)
+{
+ float data[] = { 6.1f, 10.2f, 19.3f, 25.4f };
+ bc::vector<float> a(4, context);
+ bc::copy(data, data + 4, a.begin(), queue);
+ CHECK_RANGE_EQUAL(float, 4, a, (6.1f, 10.2f, 19.3f, 25.4f));
+
+ bc::vector<float> b(4, context);
+ bc::detail::device_ptr<float> b_ptr(b.get_buffer(), size_t(0));
+
+ // buffer_iterator -> device_ptr
+ bc::copy(a.begin(), a.end(), b_ptr, queue);
+ CHECK_RANGE_EQUAL(float, 4, b, (6.1f, 10.2f, 19.3f, 25.4f));
+
+ bc::vector<float> c(4, context);
+ bc::fill(c.begin(), c.end(), 0.0f, queue);
+ bc::detail::device_ptr<float> c_ptr(c.get_buffer(), size_t(2));
+
+ // device_ptr -> device_ptr
+ bc::copy(b_ptr, b_ptr + 2, c_ptr, queue);
+ CHECK_RANGE_EQUAL(float, 4, c, (0.0f, 0.0f, 6.1f, 10.2f));
+
+ // device_ptr -> buffer_iterator
+ bc::copy(c_ptr, c_ptr + 2, a.begin() + 2, queue);
+ CHECK_RANGE_EQUAL(float, 4, a, (6.1f, 10.2f, 6.1f, 10.2f));
+}
+
+BOOST_AUTO_TEST_CASE(copy_on_host)
+{
+ int data[] = { 2, 4, 6, 8 };
+ std::vector<int> vector(4);
+ compute::copy(data, data + 4, vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (2, 4, 6, 8));
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ int data[] = { 1, 2, 5, 6 };
+ bc::vector<int> vector(4, context);
+ bc::copy(data, data + 4, vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (1, 2, 5, 6));
+
+ std::vector<int> host_vector(4);
+ bc::copy(vector.begin(), vector.end(), host_vector.begin(), queue);
+ BOOST_CHECK_EQUAL(host_vector[0], 1);
+ BOOST_CHECK_EQUAL(host_vector[1], 2);
+ BOOST_CHECK_EQUAL(host_vector[2], 5);
+ BOOST_CHECK_EQUAL(host_vector[3], 6);
+}
+
+BOOST_AUTO_TEST_CASE(empty_copy)
+{
+ int data[] = { 1, 2, 5, 6 };
+ bc::vector<int> a(4, context);
+ bc::vector<int> b(context);
+ std::vector<int> c;
+
+ bc::copy(data, data + 4, a.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 2, 5, 6));
+
+ bc::copy(b.begin(), b.end(), a.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 2, 5, 6));
+
+ bc::copy(c.begin(), c.end(), a.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 2, 5, 6));
+
+ bc::future<bc::vector<int>::iterator> future =
+ bc::copy_async(c.begin(), c.end(), a.begin(), queue);
+ if(future.valid())
+ future.wait();
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 2, 5, 6));
+}
+
+// Test copying from a std::list to a bc::vector. This differs from
+// the test copying from std::vector because std::list has non-contigous
+// storage for its data values.
+BOOST_AUTO_TEST_CASE(copy_from_host_list)
+{
+ int data[] = { -4, 12, 9, 0 };
+ std::list<int> host_list(data, data + 4);
+
+ bc::vector<int> vector(4, context);
+ bc::copy(host_list.begin(), host_list.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (-4, 12, 9, 0));
+}
+
+BOOST_AUTO_TEST_CASE(copy_n_int)
+{
+ int data[] = { 1, 2, 3, 4, 5 };
+ bc::vector<int> a(data, data + 5, queue);
+
+ bc::vector<int> b(5, context);
+ bc::fill(b.begin(), b.end(), 0, queue);
+ bc::copy_n(a.begin(), 3, b.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 5, b, (1, 2, 3, 0, 0));
+
+ bc::copy_n(b.begin(), 4, a.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 5, a, (1, 2, 3, 0, 5));
+}
+
+BOOST_AUTO_TEST_CASE(copy_swizzle_iterator)
+{
+ using bc::int2_;
+ using bc::int4_;
+
+ int data[] = { 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 1, 2, 3,
+ 4, 5, 6, 7 };
+
+ bc::vector<int4_> input(reinterpret_cast<int4_*>(data),
+ reinterpret_cast<int4_*>(data) + 4,
+ queue);
+ BOOST_CHECK_EQUAL(input.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int4_, 4, input,
+ (int4_(1, 2, 3, 4),
+ int4_(5, 6, 7, 8),
+ int4_(9, 1, 2, 3),
+ int4_(4, 5, 6, 7))
+ );
+
+ bc::vector<int4_> output4(4, context);
+ bc::copy(
+ bc::detail::make_swizzle_iterator<4>(input.begin(), "wzyx"),
+ bc::detail::make_swizzle_iterator<4>(input.end(), "wzyx"),
+ output4.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int4_, 4, output4,
+ (int4_(4, 3, 2, 1),
+ int4_(8, 7, 6, 5),
+ int4_(3, 2, 1, 9),
+ int4_(7, 6, 5, 4))
+ );
+
+ bc::vector<int2_> output2(4, context);
+ bc::copy(
+ bc::detail::make_swizzle_iterator<2>(input.begin(), "xz"),
+ bc::detail::make_swizzle_iterator<2>(input.end(), "xz"),
+ output2.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int2_, 4, output2,
+ (int2_(1, 3),
+ int2_(5, 7),
+ int2_(9, 2),
+ int2_(4, 6))
+ );
+
+ bc::vector<int> output1(4, context);
+ bc::copy(
+ bc::detail::make_swizzle_iterator<1>(input.begin(), "y"),
+ bc::detail::make_swizzle_iterator<1>(input.end(), "y"),
+ output1.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output1, (2, 6, 1, 5));
+}
+
+BOOST_AUTO_TEST_CASE(copy_int_async)
+{
+ // setup host data
+ int host_data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ typedef int* host_iterator;
+
+ // setup device data
+ bc::vector<int> device_data(8, context);
+ typedef bc::vector<int>::iterator device_iterator;
+
+ // copy data to device
+ bc::future<device_iterator> host_to_device_future =
+ bc::copy_async(host_data, host_data + 8, device_data.begin(), queue);
+
+ // wait for copy to complete
+ host_to_device_future.wait();
+
+ // check results
+ CHECK_RANGE_EQUAL(int, 8, device_data, (1, 2, 3, 4, 5, 6, 7, 8));
+ BOOST_VERIFY(host_to_device_future.get() == device_data.end());
+
+ // fill host data with zeros
+ std::fill(host_data, host_data + 8, int(0));
+
+ // copy data back to host
+ bc::future<host_iterator> device_to_host_future =
+ bc::copy_async(device_data.begin(), device_data.end(), host_data, queue);
+
+ // wait for copy to complete
+ device_to_host_future.wait();
+
+ // check results
+ BOOST_CHECK_EQUAL(host_data[0], int(1));
+ BOOST_CHECK_EQUAL(host_data[1], int(2));
+ BOOST_CHECK_EQUAL(host_data[2], int(3));
+ BOOST_CHECK_EQUAL(host_data[3], int(4));
+ BOOST_CHECK_EQUAL(host_data[4], int(5));
+ BOOST_CHECK_EQUAL(host_data[5], int(6));
+ BOOST_CHECK_EQUAL(host_data[6], int(7));
+ BOOST_CHECK_EQUAL(host_data[7], int(8));
+ BOOST_VERIFY(device_to_host_future.get() == host_data + 8);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_back_inserter)
+{
+ compute::vector<int> device_vector(5, context);
+ compute::iota(device_vector.begin(), device_vector.end(), 10, queue);
+
+ std::vector<int> host_vector;
+ compute::copy(
+ device_vector.begin(),
+ device_vector.end(),
+ std::back_inserter(host_vector),
+ queue
+ );
+
+ BOOST_CHECK_EQUAL(host_vector.size(), size_t(5));
+ BOOST_CHECK_EQUAL(host_vector[0], 10);
+ BOOST_CHECK_EQUAL(host_vector[1], 11);
+ BOOST_CHECK_EQUAL(host_vector[2], 12);
+ BOOST_CHECK_EQUAL(host_vector[3], 13);
+ BOOST_CHECK_EQUAL(host_vector[4], 14);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_stringstream)
+{
+ std::stringstream stream;
+
+ int data[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
+ compute::vector<int> vector(data, data + 8, queue);
+
+ compute::copy(
+ vector.begin(),
+ vector.end(),
+ std::ostream_iterator<int>(stream, " "),
+ queue
+ );
+ BOOST_CHECK_EQUAL(stream.str(), std::string("2 3 4 5 6 7 8 9 "));
+}
+
+BOOST_AUTO_TEST_CASE(check_copy_type)
+{
+ // copy from host to device and ensure clEnqueueWriteBuffer() is used
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> a(8, context);
+ compute::future<void> future =
+ compute::copy_async(data, data + 8, a.begin(), queue);
+ BOOST_CHECK(
+ future.get_event().get_command_type() == CL_COMMAND_WRITE_BUFFER
+ );
+ future.wait();
+ CHECK_RANGE_EQUAL(int, 8, a, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // copy on the device and ensure clEnqueueCopyBuffer() is used
+ compute::vector<int> b(8, context);
+ future = compute::copy_async(a.begin(), a.end(), b.begin(), queue);
+ BOOST_CHECK(
+ future.get_event().get_command_type() == CL_COMMAND_COPY_BUFFER
+ );
+ future.wait();
+ CHECK_RANGE_EQUAL(int, 8, b, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // copy between vectors of different types on the device and ensure
+ // that the copy kernel is used
+ compute::vector<short> c(8, context);
+ future = compute::copy_async(a.begin(), a.end(), c.begin(), queue);
+ BOOST_CHECK(
+ future.get_event().get_command_type() == CL_COMMAND_NDRANGE_KERNEL
+ );
+ future.wait();
+ CHECK_RANGE_EQUAL(short, 8, c, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // copy from device to host and ensure clEnqueueReadBuffer() is used
+ future = compute::copy_async(b.begin(), b.end(), data, queue);
+ BOOST_CHECK(
+ future.get_event().get_command_type() == CL_COMMAND_READ_BUFFER
+ );
+ future.wait();
+ CHECK_HOST_RANGE_EQUAL(int, 8, data, (1, 2, 3, 4, 5, 6, 7, 8));
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+BOOST_AUTO_TEST_CASE(copy_svm_ptr)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using boost::compute::int_;
+
+ if(bug_in_svmmemcpy(device)){
+ std::cerr << "skipping copy_svm_ptr test case" << std::endl;
+ return;
+ }
+
+ int_ data[] = { 1, 3, 2, 4 };
+
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+ compute::copy(data, data + 4, ptr, queue);
+
+ int_ output[] = { 0, 0, 0, 0 };
+ compute::copy(ptr, ptr + 4, output, queue);
+ CHECK_HOST_RANGE_EQUAL(int_, 4, output, (1, 3, 2, 4));
+
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_svm_ptr)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using boost::compute::int_;
+
+ if(bug_in_svmmemcpy(device)){
+ std::cerr << "skipping copy_svm_ptr test case" << std::endl;
+ return;
+ }
+
+ int_ data[] = { 1, 3, 2, 4 };
+
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+ boost::compute::future<void> future =
+ compute::copy_async(data, data + 4, ptr, queue);
+ future.wait();
+
+ int_ output[] = { 0, 0, 0, 0 };
+ future =
+ compute::copy_async(ptr, ptr + 4, output, queue);
+ future.wait();
+ CHECK_HOST_RANGE_EQUAL(int_, 4, output, (1, 3, 2, 4));
+
+ compute::svm_free(context, ptr);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+
+BOOST_AUTO_TEST_CASE(copy_to_vector_bool)
+{
+ using compute::uchar_;
+
+ compute::vector<uchar_> vec(2, context);
+
+ // copy to device
+ bool data[] = {true, false};
+ compute::copy(data, data + 2, vec.begin(), queue);
+ BOOST_CHECK(static_cast<bool>(vec[0]) == true);
+ BOOST_CHECK(static_cast<bool>(vec[1]) == false);
+
+ // copy to host
+ std::vector<bool> host_vec(vec.size());
+ compute::copy(vec.begin(), vec.end(), host_vec.begin(), queue);
+ BOOST_CHECK(host_vec[0] == true);
+ BOOST_CHECK(host_vec[1] == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_copy_if.cpp b/src/boost/libs/compute/test/test_copy_if.cpp
new file mode 100644
index 00000000..2a65bb08
--- /dev/null
+++ b/src/boost/libs/compute/test/test_copy_if.cpp
@@ -0,0 +1,119 @@
+//---------------------------------------------------------------------------//
+// 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 TestCopyIf
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(copy_if_int)
+{
+ int data[] = { 1, 6, 3, 5, 8, 2, 4 };
+ bc::vector<int> input(data, data + 7, queue);
+
+ bc::vector<int> output(input.size(), context);
+ bc::fill(output.begin(), output.end(), -1, queue);
+
+ using ::boost::compute::_1;
+
+ bc::vector<int>::iterator iter =
+ bc::copy_if(input.begin(), input.end(),
+ output.begin(), _1 < 5, queue);
+ BOOST_VERIFY(iter == output.begin() + 4);
+ CHECK_RANGE_EQUAL(int, 7, output, (1, 3, 2, 4, -1, -1, -1));
+
+ bc::fill(output.begin(), output.end(), 42, queue);
+ iter =
+ bc::copy_if(input.begin(), input.end(),
+ output.begin(), _1 * 2 >= 10, queue);
+ BOOST_VERIFY(iter == output.begin() + 3);
+ CHECK_RANGE_EQUAL(int, 7, output, (6, 5, 8, 42, 42, 42, 42));
+}
+
+BOOST_AUTO_TEST_CASE(copy_if_odd)
+{
+ int data[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 };
+ bc::vector<int> input(data, data + 10, queue);
+
+ using ::boost::compute::_1;
+
+ bc::vector<int> odds(input.size(), context);
+ bc::vector<int>::iterator odds_end =
+ bc::copy_if(input.begin(), input.end(),
+ odds.begin(), _1 % 2 == 1, queue);
+ BOOST_CHECK(odds_end == odds.begin() + 6);
+ CHECK_RANGE_EQUAL(int, 6, odds, (1, 3, 5, 1, 3, 5));
+
+ bc::vector<int> evens(input.size(), context);
+ bc::vector<int>::iterator evens_end =
+ bc::copy_if(input.begin(), input.end(),
+ evens.begin(), _1 % 2 == 0, queue);
+ BOOST_CHECK(evens_end == evens.begin() + 4);
+ CHECK_RANGE_EQUAL(int, 4, evens, (2, 4, 2, 4));
+}
+
+BOOST_AUTO_TEST_CASE(clip_points_below_plane)
+{
+ float data[] = { 1.0f, 2.0f, 3.0f, 0.0f,
+ -1.0f, 2.0f, 3.0f, 0.0f,
+ -2.0f, -3.0f, 4.0f, 0.0f,
+ 4.0f, -3.0f, 2.0f, 0.0f };
+ bc::vector<bc::float4_> points(reinterpret_cast<bc::float4_ *>(data),
+ reinterpret_cast<bc::float4_ *>(data) + 4,
+ queue);
+
+ // create output vector filled with (0, 0, 0, 0)
+ bc::vector<bc::float4_> output(points.size(), context);
+ bc::fill(output.begin(), output.end(),
+ bc::float4_(0.0f, 0.0f, 0.0f, 0.0f), queue);
+
+ // define the plane (at origin, +X normal)
+ bc::float4_ plane_origin(0.0f, 0.0f, 0.0f, 0.0f);
+ bc::float4_ plane_normal(1.0f, 0.0f, 0.0f, 0.0f);
+
+ using ::boost::compute::_1;
+ using ::boost::compute::lambda::dot;
+
+ bc::vector<bc::float4_>::const_iterator iter =
+ bc::copy_if(points.begin(),
+ points.end(),
+ output.begin(),
+ dot(_1 - plane_origin, plane_normal) > 0.0f,
+ queue);
+ BOOST_CHECK(iter == output.begin() + 2);
+}
+
+BOOST_AUTO_TEST_CASE(copy_index_if_int)
+{
+ int data[] = { 1, 6, 3, 5, 8, 2, 4 };
+ compute::vector<int> input(data, data + 7, queue);
+
+ compute::vector<int> output(input.size(), context);
+ compute::fill(output.begin(), output.end(), -1, queue);
+
+ using ::boost::compute::_1;
+ using ::boost::compute::detail::copy_index_if;
+
+ compute::vector<int>::iterator iter =
+ copy_index_if(input.begin(), input.end(), output.begin(),
+ _1 < 5, queue);
+ BOOST_VERIFY(iter == output.begin() + 4);
+ CHECK_RANGE_EQUAL(int, 7, output, (0, 2, 5, 6, -1, -1, -1));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_copy_type_mismatch.cpp b/src/boost/libs/compute/test/test_copy_type_mismatch.cpp
new file mode 100644
index 00000000..49305a6d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_copy_type_mismatch.cpp
@@ -0,0 +1,1380 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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.
+//---------------------------------------------------------------------------//
+
+// Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
+// parameters for copy algorithm without any undesirable consequences (like
+// saving modified values of those parameters).
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#endif
+
+#define BOOST_TEST_MODULE TestCopyTypeMismatch
+#include <boost/test/unit_test.hpp>
+
+#include <list>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <iterator>
+#include <iostream>
+
+#include <boost/compute/svm.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/device_ptr.hpp>
+#include <boost/compute/memory/svm_ptr.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(is_same_ignore_const)
+{
+ BOOST_STATIC_ASSERT((
+ boost::compute::detail::is_same_value_type<
+ std::vector<int>::iterator,
+ compute::buffer_iterator<int>
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::compute::detail::is_same_value_type<
+ std::vector<int>::const_iterator,
+ compute::buffer_iterator<int>
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::compute::detail::is_same_value_type<
+ std::vector<int>::iterator,
+ compute::buffer_iterator<const int>
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::compute::detail::is_same_value_type<
+ std::vector<int>::const_iterator,
+ compute::buffer_iterator<const int>
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_double)
+{
+ if(!device.supports_extension("cl_khr_fp64")) {
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ using compute::double_;
+ using compute::float_;
+
+ float_ host[] = { 6.1f, 10.2f, 19.3f, 25.4f };
+ bc::vector<double_> device_vector(4, context);
+
+ // copy host float data to double device vector
+ bc::copy(host, host + 4, device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(double_, 4, device_vector, (6.1f, 10.2f, 19.3f, 25.4f));
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+// HOST -> DEVICE
+
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_mapping_device_vector)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(4, context);
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_device_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_convert_on_host)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by casting input data on host and performing
+ // normal copy host->device (since types match now)
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_with_transform)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by mapping input data to the device memory
+ // and using transform operation for casting & copying
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 0);
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ compute::future<void> future =
+ bc::copy_async(host, host + 4, device_vector.begin(), queue);
+ future.wait();
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int_empty)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<int_> device_vector(size_t(4), int_(1), queue);
+
+ // copy nothing to int device vector
+ compute::future<bc::vector<int_>::iterator > future =
+ bc::copy_async(host, host, device_vector.begin(), queue);
+ if(future.valid()) {
+ future.wait();
+ }
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ int_(1),
+ int_(1),
+ int_(1),
+ int_(1)
+ )
+ );
+}
+
+// Test copying from a std::list to a bc::vector. This differs from
+// the test copying from std::vector because std::list has non-contiguous
+// storage for its data values.
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_device_map)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_device_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ std::list<float_> host(data, data + 4);
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ bc::copy(host.begin(), host.end(), device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+// Test copying from a std::list to a bc::vector. This differs from
+// the test copying from std::vector because std::list has non-contiguous
+// storage for its data values.
+BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_convert_on_host)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by casting input data on host and performing
+ // normal copy host->device (since types match now)
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ std::list<float_> host(data, data + 4);
+ bc::vector<int_> device_vector(4, context);
+
+ // copy host float data to int device vector
+ bc::copy(host.begin(), host.end(), device_vector.begin(), queue);
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+// SVM requires OpenCL 2.0
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_map)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_device_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ float_ host[] = { 5.1f, -10.3f, 19.4f, 26.7f };
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, ptr, queue);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(5.1f),
+ static_cast<int_>(-10.3f),
+ static_cast<int_>(19.4f),
+ static_cast<int_>(26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_convert_on_host)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ if(bug_in_svmmemcpy(device)){
+ std::cerr << "skipping svmmemcpy test case" << std::endl;
+ return;
+ }
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by casting input data on host and performing
+ // normal copy host->device (since types match now)
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ host[] = { 0.1f, 10.3f, 9.4f, -26.7f };
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, ptr, queue);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(0.1f),
+ static_cast<int_>(10.3f),
+ static_cast<int_>(9.4f),
+ static_cast<int_>(-26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_with_transform)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_device_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by mapping input data to the device memory
+ // and using transform operation (copy kernel) for casting & copying
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 0);
+
+ float_ host[] = { 4.1f, -11.3f, 219.4f, -26.7f };
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int device vector
+ bc::copy(host, host + 4, ptr, queue);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(4.1f),
+ static_cast<int_>(-11.3f),
+ static_cast<int_>(219.4f),
+ static_cast<int_>(-26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_to_device_svm_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ float_ host[] = { 44.1f, -14.3f, 319.4f, -26.7f };
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int device vector
+ compute::future<void> future =
+ bc::copy_async(host, host + 4, ptr, queue);
+ future.wait();
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(44.1f),
+ static_cast<int_>(-14.3f),
+ static_cast<int_>(319.4f),
+ static_cast<int_>(-26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+}
+#endif
+
+// DEVICE -> DEVICE
+
+BOOST_AUTO_TEST_CASE(copy_on_device_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_fvector(data, data + 4, queue);
+ bc::vector<int_> device_ivector(4, context);
+
+ // copy device float vector to device int vector
+ bc::copy(
+ device_fvector.begin(),
+ device_fvector.end(),
+ device_ivector.begin(),
+ queue
+ );
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_ivector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_fvector(data, data + 4, queue);
+ bc::vector<int_> device_ivector(4, context);
+
+ // copy device float vector to device int vector
+ compute::future<void> future =
+ bc::copy_async(
+ device_fvector.begin(),
+ device_fvector.end(),
+ device_ivector.begin(),
+ queue
+ );
+ future.wait();
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_ivector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int_empty)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_fvector(data, data + 4, queue);
+ bc::vector<int_> device_ivector(size_t(4), int_(1), queue);
+
+ // copy device float vector to device int vector
+ compute::future<void> future =
+ bc::copy_async(
+ device_fvector.begin(),
+ device_fvector.begin(),
+ device_ivector.begin(),
+ queue
+ );
+ if(future.valid()) {
+ future.wait();
+ }
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_ivector,
+ (
+ int_(1),
+ int_(1),
+ int_(1),
+ int_(1)
+ )
+ );
+}
+
+// SVM requires OpenCL 2.0
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+BOOST_AUTO_TEST_CASE(copy_on_device_buffer_to_svm_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int svm memory
+ bc::copy(device_vector.begin(), device_vector.end(), ptr, queue);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(65.1f),
+ static_cast<int_>(-110.2f),
+ static_cast<int_>(-19.3f),
+ static_cast<int_>(26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_buffer_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, 11.2f, 19.3f, 6.7f };
+ bc::vector<int_> device_vector(4, context);
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm data to int device vector
+ bc::copy(ptr, ptr + 4, device_vector.begin(), queue);
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(11.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(6.7f)
+ )
+ );
+
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_svm_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 0.1f, -10.2f, -1.3f, 2.7f };
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+ compute::svm_ptr<int_> ptr2 = compute::svm_alloc<int_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm to int svm
+ bc::copy(ptr, ptr + 4, ptr2, queue);
+
+ queue.enqueue_svm_map(ptr2.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr2.get()),
+ (
+ static_cast<int_>(0.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(-1.3f),
+ static_cast<int_>(2.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr2.get()).wait();
+
+ compute::svm_free(context, ptr);
+ compute::svm_free(context, ptr2);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_on_device_buffer_to_svm_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+ compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
+
+ // copy host float data to int svm memory
+ compute::future<bc::svm_ptr<int_> > future =
+ bc::copy_async(device_vector.begin(), device_vector.end(), ptr, queue);
+ future.wait();
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr.get()),
+ (
+ static_cast<int_>(65.1f),
+ static_cast<int_>(-110.2f),
+ static_cast<int_>(-19.3f),
+ static_cast<int_>(26.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_buffer_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
+ bc::vector<int_> device_vector(4, context);
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm data to int device vector
+ compute::future<bc::vector<int_>::iterator > future =
+ bc::copy_async(ptr, ptr + 4, device_vector.begin(), queue);
+ future.wait();
+
+ CHECK_RANGE_EQUAL(
+ int_,
+ 4,
+ device_vector,
+ (
+ static_cast<int_>(65.1f),
+ static_cast<int_>(-110.2f),
+ static_cast<int_>(-19.3f),
+ static_cast<int_>(26.7f)
+ )
+ );
+
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_svm_float_to_int)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 0.1f, -10.2f, -1.3f, 2.7f };
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+ compute::svm_ptr<int_> ptr2 = compute::svm_alloc<int_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm to int svm
+ compute::future<bc::svm_ptr<int_> > future =
+ bc::copy_async(ptr, ptr + 4, ptr2, queue);
+ future.wait();
+
+ queue.enqueue_svm_map(ptr2.get(), 4 * sizeof(cl_int), CL_MAP_READ);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ static_cast<int_*>(ptr2.get()),
+ (
+ static_cast<int_>(0.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(-1.3f),
+ static_cast<int_>(2.7f)
+ )
+ );
+ queue.enqueue_svm_unmap(ptr2.get()).wait();
+
+ compute::svm_free(context, ptr);
+ compute::svm_free(context, ptr2);
+}
+#endif
+
+// DEVICE -> HOST
+
+BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::vector<int_> host_vector(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_map)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_host_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::vector<int_> host_vector(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_host)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by copying input device vector to temporary
+ // host vector of the same type and then copying from that temporary
+ // vector to result using std::copy()
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::vector<int_> host_vector(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_device)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by mapping output data to the device memory
+ // and using transform operation for casting & copying
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 0);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::vector<int_> host_vector(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+// Test copying from a bc::vector to a std::list . This differs from
+// the test copying to std::vector because std::list has non-contiguous
+// storage for its data values.
+BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_map)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_host_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::list<int_> host_list(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_list.begin(), queue);
+
+ int_ expected[4] = {
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ host_list.begin(), host_list.end(),
+ expected, expected + 4
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+// Test copying from a bc::vector to a std::list . This differs from
+// the test copying to std::vector because std::list has non-contiguous
+// storage for its data values.
+BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_covert_on_host)
+{
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by copying input device vector to temporary
+ // host vector of the same type and then copying from that temporary
+ // vector to result using std::copy()
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+
+ std::list<int_> host_list(4);
+ // copy device float vector to int host vector
+ bc::copy(device_vector.begin(), device_vector.end(), host_list.begin(), queue);
+ int_ expected[4] = {
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ host_list.begin(), host_list.end(),
+ expected, expected + 4
+ );
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+ std::vector<int_> host_vector(device_vector.size());
+
+ // copy device float vector to host int vector
+ compute::future<void> future =
+ bc::copy_async(
+ device_vector.begin(),
+ device_vector.end(),
+ host_vector.begin(),
+ queue
+ );
+ future.wait();
+
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(-10.2f),
+ static_cast<int_>(19.3f),
+ static_cast<int_>(25.4f)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int_empty)
+{
+ using compute::int_;
+ using compute::float_;
+
+ float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
+ bc::vector<float_> device_vector(data, data + 4, queue);
+ std::vector<int_> host_vector(device_vector.size(), int_(1));
+
+ // copy device float vector to host int vector
+ compute::future<void> future =
+ bc::copy_async(
+ device_vector.begin(),
+ device_vector.begin(),
+ host_vector.begin(),
+ queue
+ );
+ if(future.valid()) {
+ future.wait();
+ }
+
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ int_(1),
+ int_(1),
+ int_(1),
+ int_(1)
+ )
+ );
+}
+
+// SVM requires OpenCL 2.0
+#if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
+BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_map)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+
+ // force copy_to_host_map (mapping device vector to the host)
+ parameters->set(cache_key, "map_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, 1.2f, 1.3f, -66.7f };
+ std::vector<int_> host_vector(4, 0);
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm data to int host vector
+ bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
+
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(1.2f),
+ static_cast<int_>(1.3f),
+ static_cast<int_>(-66.7f)
+ )
+ );
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_convert_on_host)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ if(bug_in_svmmemcpy(device)){
+ std::cerr << "skipping svmmemcpy test case" << std::endl;
+ return;
+ }
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by copying input device vector to temporary
+ // host vector of the same type and then copying from that temporary
+ // vector to result using std::copy()
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 1024);
+
+ float_ data[] = { 6.1f, 1.2f, 1.3f, 766.7f };
+ std::vector<int_> host_vector(4, 0);
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm data to int host vector
+ bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
+
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(6.1f),
+ static_cast<int_>(1.2f),
+ static_cast<int_>(1.3f),
+ static_cast<int_>(766.7f)
+ )
+ );
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_transform)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ using compute::int_;
+ using compute::uint_;
+ using compute::float_;
+
+ std::string cache_key =
+ std::string("__boost_compute_copy_to_host_float_int");
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "map_copy_threshold", 0);
+ uint_ direct_copy_threshold =
+ parameters->get(cache_key, "direct_copy_threshold", 0);
+
+ // force copying by copying input device vector to temporary
+ // host vector of the same type and then copying from that temporary
+ // vector to result using std::copy()
+ parameters->set(cache_key, "map_copy_threshold", 0);
+ parameters->set(cache_key, "direct_copy_threshold", 0);
+
+ float_ data[] = { 0.1f, 11.2f, 1.3f, -66.7f };
+ std::vector<int_> host_vector(4, 0);
+ compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
+
+ queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 4; i++) {
+ static_cast<float_*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get()).wait();
+
+ // copy host float svm data to int host vector
+ bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
+
+ CHECK_HOST_RANGE_EQUAL(
+ int_,
+ 4,
+ host_vector.begin(),
+ (
+ static_cast<int_>(0.1f),
+ static_cast<int_>(11.2f),
+ static_cast<int_>(1.3f),
+ static_cast<int_>(-66.7f)
+ )
+ );
+
+ compute::svm_free(context, ptr);
+
+ // restore
+ parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
+ parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
+}
+#endif
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_count.cpp b/src/boost/libs/compute/test/test_count.cpp
new file mode 100644
index 00000000..d1fb3aea
--- /dev/null
+++ b/src/boost/libs/compute/test/test_count.cpp
@@ -0,0 +1,221 @@
+//---------------------------------------------------------------------------//
+// 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 TestCount
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/count.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(count_int)
+{
+ int data[] = { 1, 2, 1, 2, 3 };
+ bc::vector<int> vector(data, data + 5, queue);
+ BOOST_CHECK_EQUAL(bc::count(vector.begin(), vector.end(), 1, queue), size_t(2));
+ BOOST_CHECK_EQUAL(bc::count(vector.begin(), vector.end(), 2, queue), size_t(2));
+ BOOST_CHECK_EQUAL(bc::count(vector.begin(), vector.end(), 3, queue), size_t(1));
+ BOOST_CHECK_EQUAL(bc::count(vector.begin() + 1, vector.end(), 1, queue), size_t(1));
+ BOOST_CHECK_EQUAL(bc::count(vector.begin() + 1, vector.end() - 1, 3, queue), size_t(0));
+ BOOST_CHECK_EQUAL(bc::count(vector.begin() + 1, vector.end() - 1, 2, queue), size_t(2));
+}
+
+BOOST_AUTO_TEST_CASE(count_constant_int_range)
+{
+ BOOST_CHECK_EQUAL(
+ bc::count(bc::make_constant_iterator(18, 0),
+ bc::make_constant_iterator(18, 5),
+ 18,
+ queue),
+ size_t(5)
+ );
+
+ BOOST_CHECK_EQUAL(
+ bc::count(bc::make_constant_iterator(19, 0),
+ bc::make_constant_iterator(19, 5),
+ 18,
+ queue),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_if_greater_than_two)
+{
+ float data[] = { 1.0f, 2.5f, -1.0f, 3.0f, 5.0f, -8.0f };
+ bc::vector<float> vector(data, data + 5, queue);
+
+ BOOST_CHECK_EQUAL(
+ bc::count_if(vector.begin(), vector.end(), bc::_1 > 2.0f, queue),
+ size_t(3)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_int4)
+{
+ int data[] = { 1, 2, 3, 4,
+ 4, 5, 6, 7,
+ 7, 8, 9, 1,
+ 1, 2, 3, 4,
+ 4, 5, 6, 7,
+ 0, 3, 2, 2 };
+ bc::vector<bc::int4_> vector(reinterpret_cast<bc::int4_ *>(data),
+ reinterpret_cast<bc::int4_ *>(data) + 6,
+ queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(6));
+
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(1, 2, 3, 4), queue),
+ size_t(2)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(4, 5, 6, 7), queue),
+ size_t(2)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(7, 8, 9, 1), queue),
+ size_t(1)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(0, 3, 2, 2), queue),
+ size_t(1)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(3, 4, 4, 5), queue),
+ size_t(0)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(1, 2, 3, 0), queue),
+ size_t(0)
+ );
+ BOOST_CHECK_EQUAL(
+ bc::count(vector.begin(), vector.end(), bc::int4_(1, 9, 8, 7), queue),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_newlines)
+{
+ std::string string = "abcdefg\nhijklmn\nopqrs\ntuv\nwxyz\n";
+ compute::vector<char> data(string.size(), context);
+ compute::copy(string.begin(), string.end(), data.begin(), queue);
+
+ BOOST_CHECK_EQUAL(
+ compute::count(data.begin(), data.end(), '\n', queue),
+ size_t(5)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_uchar)
+{
+ using boost::compute::uchar_;
+
+ unsigned char data[] = { 0x00, 0x10, 0x2F, 0x10, 0x01, 0x00, 0x01, 0x00 };
+ compute::vector<uchar_> vector(8, context);
+ compute::copy(data, data + 8, vector.begin(), queue);
+
+ BOOST_CHECK_EQUAL(
+ compute::count(vector.begin(), vector.end(), 0x00, queue),
+ size_t(3)
+ );
+ BOOST_CHECK_EQUAL(
+ compute::count(vector.begin(), vector.end(), 0x10, queue),
+ size_t(2)
+ );
+ BOOST_CHECK_EQUAL(
+ compute::count(vector.begin(), vector.end(), 0x2F, queue),
+ size_t(1)
+ );
+ BOOST_CHECK_EQUAL(
+ compute::count(vector.begin(), vector.end(), 0x01, queue),
+ size_t(2)
+ );
+ BOOST_CHECK_EQUAL(
+ compute::count(vector.begin(), vector.end(), 0xFF, queue),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_vector_component)
+{
+ int data[] = {
+ 1, 2,
+ 3, 4,
+ 5, 6,
+ 7, 8
+ };
+
+ using boost::compute::int2_;
+
+ compute::vector<int2_> vector(4, context);
+ compute::copy(
+ reinterpret_cast<int2_ *>(data),
+ reinterpret_cast<int2_ *>(data) + 4,
+ vector.begin(),
+ queue
+ );
+
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::get;
+
+ BOOST_CHECK_EQUAL(
+ compute::count_if(vector.begin(), vector.end(), get<0>(_1) < 4, queue),
+ size_t(2)
+ );
+ BOOST_CHECK_EQUAL(
+ compute::count_if(vector.begin(), vector.end(), get<1>(_1) > 3, queue),
+ size_t(3)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_if_odd)
+{
+ compute::vector<int> vec(2048, context);
+ compute::iota(vec.begin(), vec.end(), 0, queue);
+
+ BOOST_COMPUTE_FUNCTION(bool, is_odd, (int x),
+ {
+ return x & 1;
+ });
+
+ BOOST_CHECK_EQUAL(
+ compute::count_if(vec.begin(), vec.end(), is_odd, queue), vec.size() / 2
+ );
+}
+
+BOOST_AUTO_TEST_CASE(count_if_with_reduce)
+{
+ compute::vector<int> vec(2048, context);
+ compute::iota(vec.begin(), vec.end(), 0, queue);
+
+ using boost::compute::lambda::_1;
+
+ BOOST_CHECK_EQUAL(
+ compute::detail::count_if_with_reduce(
+ vec.begin(), vec.end(), _1 > 1024, queue
+ ),
+ size_t(1023)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_counting_iterator.cpp b/src/boost/libs/compute/test/test_counting_iterator.cpp
new file mode 100644
index 00000000..46c24ad4
--- /dev/null
+++ b/src/boost/libs/compute/test/test_counting_iterator.cpp
@@ -0,0 +1,100 @@
+//---------------------------------------------------------------------------//
+// 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 TestCountingIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::counting_iterator<int>::value_type,
+ int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::counting_iterator<float>::value_type,
+ float
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(distance)
+{
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_counting_iterator(0),
+ boost::compute::make_counting_iterator(10)
+ ),
+ std::ptrdiff_t(10)
+ );
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_counting_iterator(5),
+ boost::compute::make_counting_iterator(10)
+ ),
+ std::ptrdiff_t(5)
+ );
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_counting_iterator(-5),
+ boost::compute::make_counting_iterator(5)
+ ),
+ std::ptrdiff_t(10)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy(
+ boost::compute::make_counting_iterator(1),
+ boost::compute::make_counting_iterator(11),
+ vector.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(
+ int, 10, vector,
+ (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(iota_with_copy_doctest)
+{
+//! [iota_with_copy]
+using boost::compute::make_counting_iterator;
+
+boost::compute::vector<int> result(5, context);
+
+boost::compute::copy(
+ make_counting_iterator(1), make_counting_iterator(6), result.begin(), queue
+);
+
+// result == { 1, 2, 3, 4, 5 }
+//! [iota_with_copy]
+
+ CHECK_RANGE_EQUAL(int, 5, result, (1, 2, 3, 4, 5));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_device.cpp b/src/boost/libs/compute/test/test_device.cpp
new file mode 100644
index 00000000..bc370c1e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_device.cpp
@@ -0,0 +1,293 @@
+//---------------------------------------------------------------------------//
+// 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 TestDevice
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/detail/nvidia_compute_capability.hpp>
+
+#include "opencl_version_check.hpp"
+
+BOOST_AUTO_TEST_CASE(null_device)
+{
+ boost::compute::device null;
+ BOOST_CHECK(null.id() == cl_device_id());
+ BOOST_CHECK(null.get() == cl_device_id());
+}
+
+BOOST_AUTO_TEST_CASE(default_device_doctest)
+{
+//! [default_gpu]
+boost::compute::device gpu = boost::compute::system::default_device();
+//! [default_gpu]
+
+ BOOST_CHECK(gpu.id());
+}
+
+BOOST_AUTO_TEST_CASE(device_platform)
+{
+ boost::compute::platform p = boost::compute::system::platforms().at(0);
+ BOOST_CHECK(p == p.devices().at(0).platform());
+}
+
+BOOST_AUTO_TEST_CASE(get_device_name)
+{
+ boost::compute::device gpu = boost::compute::system::default_device();
+ if(gpu.id()){
+ BOOST_CHECK(!gpu.name().empty());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(equality_operator)
+{
+ boost::compute::device device1 = boost::compute::system::default_device();
+ BOOST_CHECK(device1 == device1);
+
+ boost::compute::device device2 = device1;
+ BOOST_CHECK(device1 == device2);
+}
+
+BOOST_AUTO_TEST_CASE(get_max_work_item_sizes)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+
+ std::vector<size_t> max_work_item_sizes =
+ device.get_info<std::vector<size_t> >(CL_DEVICE_MAX_WORK_ITEM_SIZES);
+ BOOST_CHECK_GE(max_work_item_sizes.size(), size_t(3));
+ BOOST_CHECK_GE(max_work_item_sizes[0], size_t(1));
+ BOOST_CHECK_GE(max_work_item_sizes[1], size_t(1));
+ BOOST_CHECK_GE(max_work_item_sizes[2], size_t(1));
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+
+// returns true if the device supports the partitioning type
+bool supports_partition_type(const boost::compute::device &device,
+ cl_device_partition_property type)
+{
+ const std::vector<cl_device_partition_property> properties =
+ device.get_info<std::vector<cl_device_partition_property> >(
+ CL_DEVICE_PARTITION_PROPERTIES
+ );
+
+ return std::find(properties.begin(),
+ properties.end(),
+ type) != properties.end();
+}
+
+BOOST_AUTO_TEST_CASE(partition_device_equally)
+{
+ // get default device and ensure it has at least two compute units
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(device.compute_units() < 2){
+ std::cout << "skipping test: "
+ << "device does not have enough compute units"
+ << std::endl;
+ return;
+ }
+
+ // check that the device supports partitioning equally
+ if(!supports_partition_type(device, CL_DEVICE_PARTITION_EQUALLY)){
+ std::cout << "skipping test: "
+ << "device does not support CL_DEVICE_PARTITION_EQUALLY"
+ << std::endl;
+ return;
+ }
+
+ // ensure device is not a sub-device
+ BOOST_CHECK(device.is_subdevice() == false);
+
+ // partition default device into sub-devices with one compute unit each
+ std::vector<boost::compute::device>
+ sub_devices = device.partition_equally(1);
+ BOOST_CHECK_EQUAL(sub_devices.size(), size_t(device.compute_units()));
+
+ // verify each of the sub-devices
+ for(size_t i = 0; i < sub_devices.size(); i++){
+ const boost::compute::device &sub_device = sub_devices[i];
+
+ // ensure parent device id is correct
+ cl_device_id parent_id =
+ sub_device.get_info<cl_device_id>(CL_DEVICE_PARENT_DEVICE);
+ BOOST_CHECK(parent_id == device.id());
+
+ // ensure device is a sub-device
+ BOOST_CHECK(sub_device.is_subdevice() == true);
+
+ // check number of compute units
+ BOOST_CHECK_EQUAL(sub_device.compute_units(), size_t(1));
+ }
+}
+
+// used to sort devices by number of compute units
+bool compare_compute_units(const boost::compute::device &a,
+ const boost::compute::device &b)
+{
+ return a.compute_units() < b.compute_units();
+}
+
+BOOST_AUTO_TEST_CASE(partition_by_counts)
+{
+ // get default device and ensure it has at least four compute units
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(device.compute_units() < 4){
+ std::cout << "skipping test: "
+ << "device does not have enough compute units"
+ << std::endl;
+ return;
+ }
+
+ // check that the device supports partitioning by counts
+ if(!supports_partition_type(device, CL_DEVICE_PARTITION_BY_COUNTS)){
+ std::cout << "skipping test: "
+ << "device does not support CL_DEVICE_PARTITION_BY_COUNTS"
+ << std::endl;
+ return;
+ }
+
+ // ensure device is not a sub-device
+ BOOST_CHECK(device.is_subdevice() == false);
+
+ // create vector of sub-device compute unit counts
+ std::vector<size_t> counts;
+ counts.push_back(2);
+ counts.push_back(1);
+ counts.push_back(1);
+
+ // partition default device into sub-devices according to counts
+ std::vector<boost::compute::device>
+ sub_devices = device.partition_by_counts(counts);
+ BOOST_CHECK_EQUAL(sub_devices.size(), size_t(3));
+
+ // sort sub-devices by number of compute units (see issue #185)
+ std::sort(sub_devices.begin(), sub_devices.end(), compare_compute_units);
+
+ // verify each of the sub-devices
+ BOOST_CHECK_EQUAL(sub_devices[0].compute_units(), size_t(1));
+ BOOST_CHECK_EQUAL(sub_devices[1].compute_units(), size_t(1));
+ BOOST_CHECK_EQUAL(sub_devices[2].compute_units(), size_t(2));
+}
+
+BOOST_AUTO_TEST_CASE(partition_by_affinity_domain)
+{
+ // get default device and ensure it has at least two compute units
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(device.compute_units() < 2){
+ std::cout << "skipping test: "
+ << "device does not have enough compute units"
+ << std::endl;
+ return;
+ }
+
+ // check that the device supports splitting by affinity domains
+ if(!supports_partition_type(device, CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE)){
+ std::cout << "skipping test: "
+ << "device does not support partitioning by affinity domain"
+ << std::endl;
+ return;
+ }
+
+ // ensure device is not a sub-device
+ BOOST_CHECK(device.is_subdevice() == false);
+
+ std::vector<boost::compute::device> sub_devices =
+ device.partition_by_affinity_domain(
+ CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE);
+ BOOST_CHECK(sub_devices.size() > 0);
+ BOOST_CHECK(sub_devices[0].is_subdevice() == true);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
+
+BOOST_AUTO_TEST_CASE(nvidia_compute_capability)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+ int major, minor;
+ boost::compute::detail::get_nvidia_compute_capability(device, major, minor);
+ boost::compute::detail::check_nvidia_compute_capability(device, 3, 0);
+}
+
+BOOST_AUTO_TEST_CASE(get_info_specializations)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+
+ std::cout << device.get_info<CL_DEVICE_NAME>() << std::endl;
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(get_host_timer)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ BOOST_CHECK(device.get_host_timer() != 0);
+
+ #ifndef BOOST_COMPUTE_NO_HDR_CHRONO
+ typedef std::chrono::milliseconds stdms;
+ BOOST_CHECK(device.get_host_timer<stdms>().count() != 0);
+ #endif
+
+ #ifndef BOOST_COMPUTE_NO_BOOST_CHRONO
+ typedef boost::chrono::milliseconds bms;
+ BOOST_CHECK(device.get_host_timer<bms>().count() != 0);
+ #endif
+}
+
+BOOST_AUTO_TEST_CASE(get_device_and_host_timer)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ typedef std::pair<boost::compute::ulong_, boost::compute::ulong_> dah_timer;
+ dah_timer timer;
+ BOOST_CHECK_NO_THROW(timer = device.get_device_and_host_timer());
+ BOOST_CHECK(timer.first != 0);
+ BOOST_CHECK(timer.second != 0);
+
+ #ifndef BOOST_COMPUTE_NO_HDR_CHRONO
+ typedef std::chrono::milliseconds stdms;
+ BOOST_CHECK(device.get_device_and_host_timer<stdms>().first.count() != 0);
+ BOOST_CHECK(device.get_device_and_host_timer<stdms>().second.count() != 0);
+ #endif
+
+ #ifndef BOOST_COMPUTE_NO_BOOST_CHRONO
+ typedef boost::chrono::milliseconds bms;
+ BOOST_CHECK(device.get_device_and_host_timer<bms>().first.count() != 0);
+ BOOST_CHECK(device.get_device_and_host_timer<bms>().second.count() != 0);
+ #endif
+}
+
+BOOST_AUTO_TEST_CASE(get_info_opencl21_queries)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ BOOST_CHECK(!device.get_info<CL_DEVICE_IL_VERSION>().empty());
+ BOOST_CHECK(device.get_info<CL_DEVICE_MAX_NUM_SUB_GROUPS>() > 0);
+ BOOST_CHECK_NO_THROW(
+ device.get_info<CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS>()
+ );
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_1
diff --git a/src/boost/libs/compute/test/test_discard_iterator.cpp b/src/boost/libs/compute/test/test_discard_iterator.cpp
new file mode 100644
index 00000000..94a3d700
--- /dev/null
+++ b/src/boost/libs/compute/test/test_discard_iterator.cpp
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestDiscardIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/discard_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::discard_iterator::value_type, void
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(distance)
+{
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_discard_iterator(0),
+ boost::compute::make_discard_iterator(10)
+ ),
+ std::ptrdiff_t(10)
+ );
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_discard_iterator(5),
+ boost::compute::make_discard_iterator(10)
+ ),
+ std::ptrdiff_t(5)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discard_copy)
+{
+ boost::compute::vector<int> vector(10, context);
+ boost::compute::fill(vector.begin(), vector.end(), 42, queue);
+
+ boost::compute::copy(
+ vector.begin(), vector.end(),
+ boost::compute::make_discard_iterator(),
+ queue
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discard_copy_if)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+
+ using boost::compute::lambda::_1;
+
+ boost::compute::discard_iterator end = boost::compute::copy_if(
+ vector.begin(), vector.end(),
+ boost::compute::make_discard_iterator(),
+ _1 > 4,
+ queue
+ );
+ BOOST_CHECK(std::distance(boost::compute::discard_iterator(), end) == 4);
+}
+
+BOOST_AUTO_TEST_CASE(discard_fill)
+{
+ boost::compute::fill(
+ boost::compute::make_discard_iterator(0),
+ boost::compute::make_discard_iterator(100),
+ 42,
+ queue
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_discrete_distribution.cpp b/src/boost/libs/compute/test/test_discrete_distribution.cpp
new file mode 100644
index 00000000..6c4b8d71
--- /dev/null
+++ b/src/boost/libs/compute/test/test_discrete_distribution.cpp
@@ -0,0 +1,237 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestDiscreteDistribution
+#include <boost/test/unit_test.hpp>
+
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/discrete_distribution.hpp>
+#include <boost/compute/lambda.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(discrete_distribution_doctest)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<uint_> vec(100, context);
+
+//! [generate]
+// initialize the default random engine
+boost::compute::default_random_engine engine(queue);
+
+// initialize weights
+int weights[] = {2, 2};
+
+// setup the discrete distribution to produce integers 0 and 1
+// with equal weights
+boost::compute::discrete_distribution<uint_> distribution(weights, weights+2);
+
+// generate the random values and store them to 'vec'
+distribution.generate(vec.begin(), vec.end(), engine, queue);
+// ! [generate]
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 > 1, queue
+ ),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discrete_distribution)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ size_t size = 100;
+ boost::compute::vector<uint_> vec(size, context);
+
+ // initialize the default random engine
+ boost::compute::default_random_engine engine(queue);
+
+ // initialize weights
+ int weights[] = {10, 40, 40, 10};
+
+ // setup the discrete distribution
+ boost::compute::discrete_distribution<uint_> distribution(
+ weights, weights + 4
+ );
+
+ std::vector<double> p = distribution.probabilities();
+ BOOST_CHECK_CLOSE(p[0], double(0.1), 0.001);
+ BOOST_CHECK_CLOSE(p[1], double(0.4), 0.001);
+ BOOST_CHECK_CLOSE(p[2], double(0.4), 0.001);
+ BOOST_CHECK_CLOSE(p[3], double(0.1), 0.001);
+
+ BOOST_CHECK_EQUAL((distribution.min)(), uint_(0));
+ BOOST_CHECK_EQUAL((distribution.max)(), uint_(3));
+
+ // generate the random values and store them to 'vec'
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 < 4, queue
+ ),
+ size
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discrete_distribution_default_ctor)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ size_t size = 100;
+ boost::compute::vector<uint_> vec(size, context);
+
+ // initialize the default random engine
+ boost::compute::default_random_engine engine(queue);
+
+ // call default constructor
+ boost::compute::discrete_distribution<uint_> distribution;
+
+ std::vector<double> p = distribution.probabilities();
+ BOOST_CHECK_CLOSE(p[0], double(1), 0.001);
+
+ // generate the random values and store them to 'vec'
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 == 0, queue
+ ),
+ size
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discrete_distribution_one_weight)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ size_t size = 100;
+ boost::compute::vector<uint_> vec(size, context);
+
+ // initialize the default random engine
+ boost::compute::default_random_engine engine(queue);
+
+ std::vector<int> weights(1, 1);
+ // call default constructor
+ boost::compute::discrete_distribution<uint_> distribution(
+ weights.begin(), weights.end()
+ );
+
+ std::vector<double> p = distribution.probabilities();
+ BOOST_CHECK_CLOSE(p[0], double(1), 0.001);
+
+ BOOST_CHECK_EQUAL((distribution.min)(), uint_(0));
+ BOOST_CHECK_EQUAL((distribution.max)(), uint_(0));
+
+ // generate the random values and store them to 'vec'
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 == 0, queue
+ ),
+ size
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discrete_distribution_empty_weights)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ size_t size = 100;
+ boost::compute::vector<uint_> vec(size, context);
+
+ // initialize the default random engine
+ boost::compute::default_random_engine engine(queue);
+
+ std::vector<int> weights;
+ // weights.begin() == weights.end()
+ boost::compute::discrete_distribution<uint_> distribution(
+ weights.begin(), weights.end()
+ );
+
+ std::vector<double> p = distribution.probabilities();
+ BOOST_CHECK_CLOSE(p[0], double(1), 0.001);
+
+ BOOST_CHECK_EQUAL((distribution.min)(), uint_(0));
+ BOOST_CHECK_EQUAL((distribution.max)(), uint_(0));
+
+ // generate the random values and store them to 'vec'
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 == 0, queue
+ ),
+ size
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discrete_distribution_uchar)
+{
+ using boost::compute::uchar_;
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ size_t size = 100;
+ boost::compute::vector<uchar_> uchar_vec(size, context);
+ boost::compute::vector<uint_> uint_vec(size, context);
+
+ // initialize the default random engine
+ boost::compute::default_random_engine engine(queue);
+
+ // initialize weights
+ std::vector<int> weights(258, 0);
+ weights[257] = 1;
+
+ // setup the discrete distribution
+ boost::compute::discrete_distribution<uchar_> distribution(
+ weights.begin(), weights.end()
+ );
+
+ BOOST_CHECK_EQUAL((distribution.min)(), uchar_(0));
+ BOOST_CHECK_EQUAL((distribution.max)(), uchar_(255));
+
+ // generate the random uchar_ values to the uchar_ vector
+ distribution.generate(uchar_vec.begin(), uchar_vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ uchar_vec.begin(), uchar_vec.end(), _1 == uchar_(1), queue
+ ),
+ size
+ );
+
+ // generate the random uchar_ values to the uint_ vector
+ distribution.generate(uint_vec.begin(), uint_vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ uint_vec.begin(), uint_vec.end(), _1 == uint_(1), queue
+ ),
+ size
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_dynamic_bitset.cpp b/src/boost/libs/compute/test/test_dynamic_bitset.cpp
new file mode 100644
index 00000000..1afb905b
--- /dev/null
+++ b/src/boost/libs/compute/test/test_dynamic_bitset.cpp
@@ -0,0 +1,96 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestDynamicBitset
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/dynamic_bitset.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(set_and_test)
+{
+ compute::dynamic_bitset<> bits(1024, queue);
+
+ bits.set(1, queue);
+ BOOST_CHECK(bits.test(1, queue) == true);
+ BOOST_CHECK(bits.test(2, queue) == false);
+
+ bits.set(1, false, queue);
+ BOOST_CHECK(bits.test(1, queue) == false);
+ BOOST_CHECK(bits.test(2, queue) == false);
+}
+
+BOOST_AUTO_TEST_CASE(count)
+{
+ compute::dynamic_bitset<> bits(1024, queue);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(0));
+
+ bits.set(1, queue);
+ bits.set(8, queue);
+ bits.set(129, queue);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(3));
+
+ bits.set(8, false, queue);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(2));
+
+ bits.reset(queue);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(0));
+}
+
+BOOST_AUTO_TEST_CASE(resize)
+{
+ compute::dynamic_bitset<> bits(0, queue);
+ BOOST_CHECK_EQUAL(bits.size(), size_t(0));
+ BOOST_CHECK_EQUAL(bits.empty(), true);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(0));
+
+ bits.resize(100, queue);
+ BOOST_CHECK_EQUAL(bits.size(), size_t(100));
+ BOOST_CHECK_EQUAL(bits.empty(), false);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(0));
+
+ bits.set(42, true, queue);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(1));
+
+ bits.resize(0, queue);
+ BOOST_CHECK_EQUAL(bits.size(), size_t(0));
+ BOOST_CHECK_EQUAL(bits.empty(), true);
+ BOOST_CHECK_EQUAL(bits.count(queue), size_t(0));
+}
+
+BOOST_AUTO_TEST_CASE(none_and_any)
+{
+ compute::dynamic_bitset<> bits(1024, queue);
+ BOOST_CHECK(bits.any(queue) == false);
+ BOOST_CHECK(bits.none(queue) == true);
+
+ bits.set(1023, queue);
+ BOOST_CHECK(bits.any(queue) == true);
+ BOOST_CHECK(bits.none(queue) == false);
+
+ bits.set(1023, false, queue);
+ BOOST_CHECK(bits.any(queue) == false);
+ BOOST_CHECK(bits.none(queue) == true);
+
+ bits.set(1, queue);
+ BOOST_CHECK(bits.any(queue) == true);
+ BOOST_CHECK(bits.none(queue) == false);
+
+ bits.reset(queue);
+ BOOST_CHECK(bits.any(queue) == false);
+ BOOST_CHECK(bits.none(queue) == true);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_equal.cpp b/src/boost/libs/compute/test/test_equal.cpp
new file mode 100644
index 00000000..0b568c91
--- /dev/null
+++ b/src/boost/libs/compute/test/test_equal.cpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// 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 TestEqual
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/equal.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/container/string.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(equal_int)
+{
+ int data1[] = { 1, 2, 3, 4, 5, 6 };
+ int data2[] = { 1, 2, 3, 7, 5, 6 };
+
+ boost::compute::vector<int> vector1(data1, data1 + 6, queue);
+ boost::compute::vector<int> vector2(data2, data2 + 6, queue);
+
+ BOOST_CHECK(boost::compute::equal(vector1.begin(), vector1.end(),
+ vector2.begin(), queue) == false);
+ BOOST_CHECK(boost::compute::equal(vector1.begin(), vector1.begin() + 2,
+ vector2.begin(), queue) == true);
+ BOOST_CHECK(boost::compute::equal(vector1.begin() + 4, vector1.end(),
+ vector2.begin() + 4, queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(equal_string)
+{
+ boost::compute::string a = "abcdefghijk";
+ boost::compute::string b = "abcdefghijk";
+ boost::compute::string c = "abcdezghijk";
+
+ BOOST_CHECK(boost::compute::equal(a.begin(), a.end(), b.begin(), queue) == true);
+ BOOST_CHECK(boost::compute::equal(a.begin(), a.end(), c.begin(), queue) == false);
+}
+
+BOOST_AUTO_TEST_CASE(equal_different_range_sizes)
+{
+ boost::compute::vector<int> a(10, context);
+ boost::compute::vector<int> b(20, context);
+
+ boost::compute::fill(a.begin(), a.end(), 3, queue);
+ boost::compute::fill(b.begin(), b.end(), 3, queue);
+
+ BOOST_CHECK(boost::compute::equal(a.begin(), a.end(), b.begin(), b.end(), queue) == false);
+ BOOST_CHECK(boost::compute::equal(a.begin(), a.end(), a.begin(), a.end(), queue) == true);
+ BOOST_CHECK(boost::compute::equal(b.begin(), b.end(), a.begin(), a.end(), queue) == false);
+ BOOST_CHECK(boost::compute::equal(b.begin(), b.end(), b.begin(), b.end(), queue) == true);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_equal_range.cpp b/src/boost/libs/compute/test/test_equal_range.cpp
new file mode 100644
index 00000000..981d22ca
--- /dev/null
+++ b/src/boost/libs/compute/test/test_equal_range.cpp
@@ -0,0 +1,73 @@
+//---------------------------------------------------------------------------//
+// 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 TestEqualRange
+#include <boost/test/unit_test.hpp>
+
+#include <utility>
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/equal_range.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(equal_range_int)
+{
+ int data[] = { 1, 2, 2, 2, 3, 3, 4, 5 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+
+ typedef boost::compute::vector<int>::iterator iterator;
+
+ std::pair<iterator, iterator> range0 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(0), queue);
+ BOOST_CHECK(range0.first == vector.begin());
+ BOOST_CHECK(range0.second == vector.begin());
+ BOOST_CHECK_EQUAL(std::distance(range0.first, range0.second), ptrdiff_t(0));
+
+ std::pair<iterator, iterator> range1 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(1), queue);
+ BOOST_CHECK(range1.first == vector.begin());
+ BOOST_CHECK(range1.second == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(std::distance(range1.first, range1.second), ptrdiff_t(1));
+
+ std::pair<iterator, iterator> range2 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(2), queue);
+ BOOST_CHECK(range2.first == vector.begin() + 1);
+ BOOST_CHECK(range2.second == vector.begin() + 4);
+ BOOST_CHECK_EQUAL(std::distance(range2.first, range2.second), ptrdiff_t(3));
+
+ std::pair<iterator, iterator> range3 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(3), queue);
+ BOOST_CHECK(range3.first == vector.begin() + 4);
+ BOOST_CHECK(range3.second == vector.begin() + 6);
+ BOOST_CHECK_EQUAL(std::distance(range3.first, range3.second), ptrdiff_t(2));
+
+ std::pair<iterator, iterator> range4 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(4), queue);
+ BOOST_CHECK(range4.first == vector.begin() + 6);
+ BOOST_CHECK(range4.second == vector.begin() + 7);
+ BOOST_CHECK_EQUAL(std::distance(range4.first, range4.second), ptrdiff_t(1));
+
+ std::pair<iterator, iterator> range5 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(5), queue);
+ BOOST_CHECK(range5.first == vector.begin() + 7);
+ BOOST_CHECK(range5.second == vector.end());
+ BOOST_CHECK_EQUAL(std::distance(range5.first, range5.second), ptrdiff_t(1));
+
+ std::pair<iterator, iterator> range6 =
+ boost::compute::equal_range(vector.begin(), vector.end(), int(6), queue);
+ BOOST_CHECK(range6.first == vector.end());
+ BOOST_CHECK(range6.second == vector.end());
+ BOOST_CHECK_EQUAL(std::distance(range6.first, range6.second), ptrdiff_t(0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_event.cpp b/src/boost/libs/compute/test/test_event.cpp
new file mode 100644
index 00000000..9077c2a2
--- /dev/null
+++ b/src/boost/libs/compute/test/test_event.cpp
@@ -0,0 +1,143 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestEvent
+#include <boost/test/unit_test.hpp>
+
+#include <vector>
+
+#ifdef BOOST_COMPUTE_USE_CPP11
+#include <mutex>
+#include <future>
+#endif // BOOST_COMPUTE_USE_CPP11
+
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/event.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(null_event)
+{
+ boost::compute::event null;
+ BOOST_CHECK(null.get() == cl_event());
+}
+
+#if defined(BOOST_COMPUTE_CL_VERSION_1_1) && defined(BOOST_COMPUTE_USE_CPP11)
+std::mutex callback_mutex;
+std::condition_variable callback_condition_variable;
+static bool callback_invoked = false;
+
+static void BOOST_COMPUTE_CL_CALLBACK
+callback(cl_event event, cl_int status, void *user_data)
+{
+ std::lock_guard<std::mutex> lock(callback_mutex);
+ callback_invoked = true;
+ callback_condition_variable.notify_one();
+}
+
+BOOST_AUTO_TEST_CASE(event_callback)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ // ensure callback has not yet been executed
+ BOOST_CHECK_EQUAL(callback_invoked, false);
+
+ // enqueue marker and set callback to be invoked
+ boost::compute::event marker = queue.enqueue_marker();
+ marker.set_callback(callback);
+ marker.wait();
+
+ // wait up to one second for the callback to be executed
+ std::unique_lock<std::mutex> lock(callback_mutex);
+ callback_condition_variable.wait_for(
+ lock, std::chrono::seconds(1), [&](){ return callback_invoked; }
+ );
+
+ // ensure callback has been executed
+ BOOST_CHECK_EQUAL(callback_invoked, true);
+}
+
+BOOST_AUTO_TEST_CASE(lambda_callback)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ bool lambda_invoked = false;
+
+ boost::compute::event marker = queue.enqueue_marker();
+ marker.set_callback([&](){
+ std::lock_guard<std::mutex> lock(callback_mutex);
+ lambda_invoked = true;
+ callback_condition_variable.notify_one();
+ });
+ marker.wait();
+
+ // wait up to one second for the callback to be executed
+ std::unique_lock<std::mutex> lock(callback_mutex);
+ callback_condition_variable.wait_for(
+ lock, std::chrono::seconds(1), [&](){ return lambda_invoked; }
+ );
+ BOOST_CHECK_EQUAL(lambda_invoked, true);
+}
+
+BOOST_AUTO_TEST_CASE(future_then_callback)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ bool callback_invoked = false;
+
+ boost::compute::future<void> future(queue.enqueue_marker());
+ future.then([&](){
+ std::lock_guard<std::mutex> lock(callback_mutex);
+ callback_invoked = true;
+ callback_condition_variable.notify_one();
+ });
+ future.wait();
+
+ // wait up to one second for the callback to be executed
+ std::unique_lock<std::mutex> lock(callback_mutex);
+ callback_condition_variable.wait_for(
+ lock, std::chrono::seconds(1), [&](){ return callback_invoked; }
+ );
+ BOOST_CHECK_EQUAL(callback_invoked, true);
+}
+
+void BOOST_COMPUTE_CL_CALLBACK
+event_promise_fulfiller_callback(cl_event event, cl_int status, void *user_data)
+{
+ auto *promise = static_cast<std::promise<void> *>(user_data);
+ promise->set_value();
+ delete promise;
+}
+
+BOOST_AUTO_TEST_CASE(event_to_std_future)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ // enqueue an asynchronous copy to the device
+ std::vector<float> vector(1000, 3.14f);
+ boost::compute::buffer buffer(context, 1000 * sizeof(float));
+ auto event = queue.enqueue_write_buffer_async(
+ buffer, 0, 1000 * sizeof(float), vector.data()
+ );
+
+ // create a promise and future to be set by the callback
+ auto *promise = new std::promise<void>;
+ std::future<void> future = promise->get_future();
+ event.set_callback(event_promise_fulfiller_callback, CL_COMPLETE, promise);
+
+ // ensure commands are submitted to the device before waiting
+ queue.flush();
+
+ // wait for future to become ready
+ future.wait();
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_extents.cpp b/src/boost/libs/compute/test/test_extents.cpp
new file mode 100644
index 00000000..38ab092f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_extents.cpp
@@ -0,0 +1,100 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestExtents
+#include <boost/test/unit_test.hpp>
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/extents.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+BOOST_AUTO_TEST_CASE(initialize)
+{
+ compute::extents<1> one(1);
+ BOOST_CHECK_EQUAL(one[0], size_t(1));
+
+ compute::extents<3> xyz = compute::dim(1, 2, 3);
+ BOOST_CHECK_EQUAL(xyz[0], size_t(1));
+ BOOST_CHECK_EQUAL(xyz[1], size_t(2));
+ BOOST_CHECK_EQUAL(xyz[2], size_t(3));
+}
+#endif
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ BOOST_CHECK_EQUAL(compute::extents<1>().size(), size_t(1));
+ BOOST_CHECK_EQUAL(compute::extents<2>().size(), size_t(2));
+ BOOST_CHECK_EQUAL(compute::extents<3>().size(), size_t(3));
+}
+
+BOOST_AUTO_TEST_CASE(subscript_operator)
+{
+ compute::extents<3> xyz;
+ BOOST_CHECK_EQUAL(xyz[0], size_t(0));
+ BOOST_CHECK_EQUAL(xyz[1], size_t(0));
+ BOOST_CHECK_EQUAL(xyz[2], size_t(0));
+
+ xyz[0] = size_t(10);
+ xyz[1] = size_t(20);
+ xyz[2] = size_t(30);
+ BOOST_CHECK_EQUAL(xyz[0], size_t(10));
+ BOOST_CHECK_EQUAL(xyz[1], size_t(20));
+ BOOST_CHECK_EQUAL(xyz[2], size_t(30));
+}
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+BOOST_AUTO_TEST_CASE(data)
+{
+ compute::extents<3> xyz = compute::dim(5, 6, 7);
+ BOOST_CHECK_EQUAL(xyz.data()[0], size_t(5));
+ BOOST_CHECK_EQUAL(xyz.data()[1], size_t(6));
+ BOOST_CHECK_EQUAL(xyz.data()[2], size_t(7));
+}
+
+BOOST_AUTO_TEST_CASE(linear)
+{
+ compute::extents<2> uv = compute::dim(16, 16);
+ BOOST_CHECK_EQUAL(uv.linear(), size_t(256));
+}
+
+BOOST_AUTO_TEST_CASE(equality_operator)
+{
+ BOOST_CHECK(compute::dim(10, 20) == compute::dim(10, 20));
+ BOOST_CHECK(compute::dim(20, 10) != compute::dim(10, 20));
+}
+
+BOOST_AUTO_TEST_CASE(empty_dim)
+{
+ BOOST_CHECK(compute::dim<0>() == compute::dim());
+ BOOST_CHECK(compute::dim<1>() == compute::dim(0));
+ BOOST_CHECK(compute::dim<2>() == compute::dim(0, 0));
+ BOOST_CHECK(compute::dim<3>() == compute::dim(0, 0, 0));
+}
+
+BOOST_AUTO_TEST_CASE(copy_to_vector)
+{
+ compute::extents<3> exts = compute::dim(4, 5, 6);
+
+ std::vector<size_t> vec(3);
+ std::copy(exts.begin(), exts.end(), vec.begin());
+ BOOST_CHECK_EQUAL(vec[0], size_t(4));
+ BOOST_CHECK_EQUAL(vec[1], size_t(5));
+ BOOST_CHECK_EQUAL(vec[2], size_t(6));
+}
+#endif
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_extrema.cpp b/src/boost/libs/compute/test/test_extrema.cpp
new file mode 100644
index 00000000..7f339d66
--- /dev/null
+++ b/src/boost/libs/compute/test/test_extrema.cpp
@@ -0,0 +1,396 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+// Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
+// parameters for copy algorithm without any undesirable consequences (like
+// saving modified values of those parameters).
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#endif
+
+#define BOOST_TEST_MODULE TestExtrema
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/algorithm/min_element.hpp>
+#include <boost/compute/algorithm/minmax_element.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/detail/parameter_cache.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(empyt_min)
+{
+ using boost::compute::int_;
+
+ boost::compute::vector<int_> vector(size_t(16), int_(0), queue);
+ boost::compute::vector<int_>::iterator min_iter =
+ boost::compute::min_element(vector.begin(), vector.begin(), queue);
+ BOOST_CHECK(min_iter == vector.begin());
+
+ min_iter =
+ boost::compute::min_element(vector.begin(), vector.begin() + 1, queue);
+ BOOST_CHECK(min_iter == vector.begin());
+}
+
+BOOST_AUTO_TEST_CASE(int_min_max)
+{
+ using boost::compute::int_;
+ using boost::compute::uint_;
+
+ boost::compute::vector<int_> vector(size_t(4096), int_(0), queue);
+ boost::compute::iota(vector.begin(), (vector.begin() + 512), 1, queue);
+ boost::compute::fill((vector.end() - 512), vector.end(), 513, queue);
+
+ boost::compute::vector<int_>::iterator min_iter =
+ boost::compute::min_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(min_iter == vector.begin() + 512);
+ BOOST_CHECK_EQUAL((vector.begin() + 512).read(queue), 0);
+ BOOST_CHECK_EQUAL(min_iter.read(queue), 0);
+
+ boost::compute::vector<int_>::iterator max_iter =
+ boost::compute::max_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(max_iter == vector.end() - 512);
+ BOOST_CHECK_EQUAL((vector.end() - 512).read(queue), 513);
+ BOOST_CHECK_EQUAL(max_iter.read(queue), 513);
+
+ // compare function
+ boost::compute::less<int_> lessint;
+
+ // test minmax_element
+ std::pair<
+ boost::compute::vector<int_>::iterator,
+ boost::compute::vector<int_>::iterator
+ > minmax_iter =
+ boost::compute::minmax_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK_EQUAL((minmax_iter.first).read(queue), 0);
+ BOOST_CHECK_EQUAL((minmax_iter.second).read(queue), 513);
+
+ minmax_iter =
+ boost::compute::minmax_element(vector.begin(), vector.end(), lessint, queue);
+ BOOST_CHECK_EQUAL((minmax_iter.first).read(queue), 0);
+ BOOST_CHECK_EQUAL((minmax_iter.second).read(queue), 513);
+
+ // find_extrama_on_cpu
+
+ // make sure find_extrama_on_cpu is used, no serial_find_extrema
+ std::string cache_key =
+ "__boost_find_extrema_cpu_4";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_find_extrema_threshold", 0);
+ // force find_extrama_on_cpu
+ parameters->set(cache_key, "serial_find_extrema_threshold", 16);
+
+ min_iter = boost::compute::detail::find_extrema_on_cpu(
+ vector.begin(), vector.end(), lessint, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 512);
+ BOOST_CHECK_EQUAL((vector.begin() + 512).read(queue), 0);
+ BOOST_CHECK_EQUAL(min_iter.read(queue), 0);
+
+ max_iter = boost::compute::detail::find_extrema_on_cpu(
+ vector.begin(), vector.end(), lessint, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.end() - 512);
+ BOOST_CHECK_EQUAL((vector.end() - 512).read(queue), 513);
+ BOOST_CHECK_EQUAL(max_iter.read(queue), 513);
+
+ // restore
+ parameters->set(cache_key, "serial_find_extrema_threshold", map_copy_threshold);
+
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all further tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ // find_extrama_with_reduce
+ min_iter = boost::compute::detail::find_extrema_with_reduce(
+ vector.begin(), vector.end(), lessint, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 512);
+ BOOST_CHECK_EQUAL((vector.begin() + 512).read(queue), 0);
+ BOOST_CHECK_EQUAL(min_iter.read(queue), 0);
+
+ max_iter = boost::compute::detail::find_extrema_with_reduce(
+ vector.begin(), vector.end(), lessint, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.end() - 512);
+ BOOST_CHECK_EQUAL((vector.end() - 512).read(queue), 513);
+ BOOST_CHECK_EQUAL(max_iter.read(queue), 513);
+
+ // find_extram_with_atomics
+ min_iter = boost::compute::detail::find_extrema_with_atomics(
+ vector.begin(), vector.end(), lessint, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 512);
+ BOOST_CHECK_EQUAL((vector.begin() + 512).read(queue), 0);
+ BOOST_CHECK_EQUAL(min_iter.read(queue), 0);
+
+ max_iter = boost::compute::detail::find_extrema_with_atomics(
+ vector.begin(), vector.end(), lessint, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.end() - 512);
+ BOOST_CHECK_EQUAL((vector.end() - 512).read(queue), 513);
+ BOOST_CHECK_EQUAL(max_iter.read(queue), 513);
+}
+
+BOOST_AUTO_TEST_CASE(int2_min_max_custom_comparision_function)
+{
+ using boost::compute::int2_;
+ using boost::compute::uint_;
+
+ boost::compute::vector<int2_> vector(context);
+ vector.push_back(int2_(1, 10), queue);
+ vector.push_back(int2_(2, -100), queue);
+ vector.push_back(int2_(3, 30), queue);
+ vector.push_back(int2_(4, 20), queue);
+ vector.push_back(int2_(5, 5), queue);
+ vector.push_back(int2_(6, -80), queue);
+ vector.push_back(int2_(7, 21), queue);
+ vector.push_back(int2_(8, -5), queue);
+
+ BOOST_COMPUTE_FUNCTION(bool, compare_second, (const int2_ a, const int2_ b),
+ {
+ return a.y < b.y;
+ });
+
+ boost::compute::vector<int2_>::iterator min_iter =
+ boost::compute::min_element(
+ vector.begin(), vector.end(), compare_second, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*min_iter, int2_(2, -100));
+
+ boost::compute::vector<int2_>::iterator max_iter =
+ boost::compute::max_element(
+ vector.begin(), vector.end(), compare_second, queue
+ );
+ BOOST_CHECK(max_iter == vector.begin() + 2);
+ BOOST_CHECK_EQUAL(*max_iter, int2_(3, 30));
+
+ // find_extrama_on_cpu
+
+ // make sure find_extrama_on_cpu is used, no serial_find_extrema
+ std::string cache_key =
+ "__boost_find_extrema_cpu_8";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_find_extrema_threshold", 0);
+ // force find_extrama_on_cpu
+ parameters->set(cache_key, "serial_find_extrema_threshold", 16);
+
+ min_iter = boost::compute::detail::find_extrema_on_cpu(
+ vector.begin(), vector.end(), compare_second, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*min_iter, int2_(2, -100));
+
+ max_iter = boost::compute::detail::find_extrema_on_cpu(
+ vector.begin(), vector.end(), compare_second, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.begin() + 2);
+ BOOST_CHECK_EQUAL(*max_iter, int2_(3, 30));
+
+ // restore
+ parameters->set(cache_key, "serial_find_extrema_threshold", map_copy_threshold);
+
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all further tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ // find_extrama_with_reduce
+ min_iter = boost::compute::detail::find_extrema_with_reduce(
+ vector.begin(), vector.end(), compare_second, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*min_iter, int2_(2, -100));
+
+ max_iter = boost::compute::detail::find_extrema_with_reduce(
+ vector.begin(), vector.end(), compare_second, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.begin() + 2);
+ BOOST_CHECK_EQUAL(*max_iter, int2_(3, 30));
+
+ // find_extram_with_atomics
+ min_iter = boost::compute::detail::find_extrema_with_atomics(
+ vector.begin(), vector.end(), compare_second, true /* find minimum */, queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*min_iter, int2_(2, -100));
+
+ max_iter = boost::compute::detail::find_extrema_with_atomics(
+ vector.begin(), vector.end(), compare_second, false /* find minimum */, queue
+ );
+ BOOST_CHECK(max_iter == vector.begin() + 2);
+ BOOST_CHECK_EQUAL(*max_iter, int2_(3, 30));
+}
+
+BOOST_AUTO_TEST_CASE(iota_min_max)
+{
+ boost::compute::vector<int> vector(5000, context);
+
+ // fill with 0 -> 4999
+ boost::compute::iota(vector.begin(), vector.end(), 0, queue);
+
+ boost::compute::vector<int>::iterator min_iter =
+ boost::compute::min_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(min_iter == vector.begin());
+ BOOST_CHECK_EQUAL(*min_iter, 0);
+
+ boost::compute::vector<int>::iterator max_iter =
+ boost::compute::max_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(max_iter == vector.end() - 1);
+ BOOST_CHECK_EQUAL(*max_iter, 4999);
+
+ min_iter =
+ boost::compute::min_element(
+ vector.begin() + 1000,
+ vector.end() - 1000,
+ queue
+ );
+ BOOST_CHECK(min_iter == vector.begin() + 1000);
+ BOOST_CHECK_EQUAL(*min_iter, 1000);
+
+ max_iter =
+ boost::compute::max_element(
+ vector.begin() + 1000,
+ vector.end() - 1000,
+ queue
+ );
+ BOOST_CHECK(max_iter == vector.begin() + 3999);
+ BOOST_CHECK_EQUAL(*max_iter, 3999);
+
+ // fill with -2500 -> 2499
+ boost::compute::iota(vector.begin(), vector.end(), -2500, queue);
+ min_iter =
+ boost::compute::min_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(min_iter == vector.begin());
+ BOOST_CHECK_EQUAL(*min_iter, -2500);
+
+ max_iter =
+ boost::compute::max_element(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(max_iter == vector.end() - 1);
+ BOOST_CHECK_EQUAL(*max_iter, 2499);
+}
+
+// uses max_element() and length() to find the longest 2d vector
+BOOST_AUTO_TEST_CASE(max_vector_length)
+{
+ float data[] = { -1.5f, 3.2f,
+ 10.0f, 0.0f,
+ -4.2f, 2.0f,
+ 0.0f, 0.5f,
+ 1.9f, 1.9f };
+ boost::compute::vector<boost::compute::float2_> vector(
+ reinterpret_cast<boost::compute::float2_ *>(data),
+ reinterpret_cast<boost::compute::float2_ *>(data) + 5,
+ queue
+ );
+
+ // find length of the longest vector
+ typedef boost::compute::transform_iterator<
+ boost::compute::vector<boost::compute::float2_>::iterator,
+ boost::compute::length<boost::compute::float2_>
+ > length_transform_iter;
+
+ length_transform_iter max_iter =
+ boost::compute::max_element(
+ boost::compute::make_transform_iterator(
+ vector.begin(),
+ boost::compute::length<boost::compute::float2_>()
+ ),
+ boost::compute::make_transform_iterator(
+ vector.end(),
+ boost::compute::length<boost::compute::float2_>()
+ ),
+ queue
+ );
+ BOOST_CHECK(
+ max_iter == boost::compute::make_transform_iterator(
+ vector.begin() + 1,
+ boost::compute::length<boost::compute::float2_>()
+ )
+ );
+ BOOST_CHECK(max_iter.base() == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*max_iter, float(10.0));
+
+ // find length of the shortest vector
+ length_transform_iter min_iter =
+ boost::compute::min_element(
+ boost::compute::make_transform_iterator(
+ vector.begin(),
+ boost::compute::length<boost::compute::float2_>()
+ ),
+ boost::compute::make_transform_iterator(
+ vector.end(),
+ boost::compute::length<boost::compute::float2_>()
+ ),
+ queue
+ );
+ BOOST_CHECK(
+ min_iter == boost::compute::make_transform_iterator(
+ vector.begin() + 3,
+ boost::compute::length<boost::compute::float2_>()
+ )
+ );
+ BOOST_CHECK(min_iter.base() == vector.begin() + 3);
+ BOOST_CHECK_EQUAL(*min_iter, float(0.5));
+}
+
+// uses max_element() and popcount() to find the value with the most 1 bits
+BOOST_AUTO_TEST_CASE(max_bits_set)
+{
+ using boost::compute::uint_;
+
+ uint_ data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ boost::compute::vector<uint_> vector(data, data + 10, queue);
+
+ boost::compute::vector<uint_>::iterator iter =
+ boost::compute::max_element(
+ boost::compute::make_transform_iterator(
+ vector.begin(),
+ boost::compute::popcount<uint_>()
+ ),
+ boost::compute::make_transform_iterator(
+ vector.end(),
+ boost::compute::popcount<uint_>()
+ ),
+ queue
+ ).base();
+
+ BOOST_CHECK(iter == vector.begin() + 7);
+ BOOST_CHECK_EQUAL(uint_(*iter), uint_(7));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_fill.cpp b/src/boost/libs/compute/test/test_fill.cpp
new file mode 100644
index 00000000..bc58e6cb
--- /dev/null
+++ b/src/boost/libs/compute/test/test_fill.cpp
@@ -0,0 +1,333 @@
+//---------------------------------------------------------------------------//
+// 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 TestFill
+#include <boost/test/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+#include <boost/mpl/list.hpp>
+
+#include <iostream>
+
+#include <boost/compute/algorithm/equal.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/fill_n.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/svm.hpp>
+#include <boost/compute/type_traits.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+typedef boost::mpl::list
+ <bc::char_, bc::uchar_, bc::int_, bc::uint_,
+ bc::long_, bc::ulong_, bc::float_, bc::double_>
+ scalar_types;
+
+template<class T>
+inline void test_fill(T v1, T v2, T v3, bc::command_queue queue) {
+ if(boost::is_same<typename bc::scalar_type<T>::type, bc::double_>::value &&
+ !queue.get_device().supports_extension("cl_khr_fp64")) {
+ std::cerr << "Skipping test_fill<" << bc::type_name<T>() << ">() "
+ "on device which doesn't support cl_khr_fp64" << std::endl;
+ return;
+ }
+
+ bc::vector<T> vector(4, queue.get_context());
+ bc::fill(vector.begin(), vector.end(), v1, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v1, v1, v1, v1));
+
+ vector.resize(1000, queue);
+ bc::fill(vector.begin(), vector.end(), v2, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.front(), v2);
+ BOOST_CHECK_EQUAL(vector.back(), v2);
+
+ bc::fill(vector.begin() + 500, vector.end(), v3, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.front(), v2);
+ BOOST_CHECK_EQUAL(vector[499], v2);
+ BOOST_CHECK_EQUAL(vector[500], v3);
+ BOOST_CHECK_EQUAL(vector.back(), v3);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_scalar, S, scalar_types )
+{
+ S v1 = S(1.5f);
+ S v2 = S(2.5f);
+ S v3 = S(42.0f);
+ test_fill(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_vec2, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 2>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+
+ T v1 = T(s1, s2);
+ T v2 = T(s3, s4);
+ T v3 = T(s2, s1);
+ test_fill(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_vec4, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 4>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+
+ T v1 = T(s1, s2, s3, s4);
+ T v2 = T(s3, s4, s1, s2);
+ T v3 = T(s4, s3, s2, s1);
+ test_fill(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_vec8, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 8>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+ S s5 = S(122.5f);
+ S s6 = S(131.5f);
+ S s7 = S(142.0f);
+ S s8 = S(254.0f);
+
+ T v1 = T(s1, s2, s3, s4, s5, s6, s7, s8);
+ T v2 = T(s3, s4, s1, s2, s7, s8, s5, s6);
+ T v3 = T(s4, s3, s2, s1, s8, s7, s6, s5);
+ test_fill(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_vec16, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 16>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+ S s5 = S(122.5f);
+ S s6 = S(131.5f);
+ S s7 = S(142.0f);
+ S s8 = S(254.0f);
+
+ T v1 = T(s1, s2, s3, s4, s5, s6, s7, s8, s1, s2, s3, s4, s5, s6, s7, s8);
+ T v2 = T(s3, s4, s1, s2, s7, s8, s5, s6, s4, s3, s2, s1, s8, s7, s6, s5);
+ T v3 = T(s4, s3, s2, s1, s8, s7, s6, s5, s8, s7, s6, s5, s4, s3, s2, s1);
+ test_fill(v1, v2, v3, queue);
+}
+
+template<class T>
+inline void test_fill_n(T v1, T v2, T v3, bc::command_queue queue) {
+ if(boost::is_same<typename bc::scalar_type<T>::type, bc::double_>::value &&
+ !queue.get_device().supports_extension("cl_khr_fp64")) {
+ std::cerr << "Skipping test_fill_n<" << bc::type_name<T>() << ">() "
+ "on device which doesn't support cl_khr_fp64" << std::endl;
+ return;
+ }
+
+ bc::vector<T> vector(4, queue.get_context());
+ bc::fill_n(vector.begin(), 4, v1, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v1, v1, v1, v1));
+
+ bc::fill_n(vector.begin(), 3, v2, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v2, v2, v2, v1));
+
+ bc::fill_n(vector.begin() + 1, 2, v3, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v2, v3, v3, v1));
+
+ bc::fill_n(vector.begin(), 4, v2, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v2, v2, v2, v2));
+
+ // fill last element
+ bc::fill_n(vector.end() - 1, 1, v3, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v2, v2, v2, v3));
+
+ // fill first element
+ bc::fill_n(vector.begin(), 1, v1, queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(T, 4, vector, (v1, v2, v2, v3));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_n_scalar, S, scalar_types )
+{
+ S v1 = S(1.5f);
+ S v2 = S(2.5f);
+ S v3 = S(42.0f);
+ test_fill_n(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_n_vec2, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 2>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+
+ T v1 = T(s1, s2);
+ T v2 = T(s3, s4);
+ T v3 = T(s2, s1);
+ test_fill_n(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_n_vec4, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 4>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+
+ T v1 = T(s1, s2, s3, s4);
+ T v2 = T(s3, s4, s1, s2);
+ T v3 = T(s4, s3, s2, s1);
+ test_fill_n(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_n_vec8, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 8>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+ S s5 = S(122.5f);
+ S s6 = S(131.5f);
+ S s7 = S(142.0f);
+ S s8 = S(254.0f);
+
+ T v1 = T(s1, s2, s3, s4, s5, s6, s7, s8);
+ T v2 = T(s3, s4, s1, s2, s7, s8, s5, s6);
+ T v3 = T(s4, s3, s2, s1, s8, s7, s6, s5);
+ test_fill_n(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE( fill_n_vec16, S, scalar_types )
+{
+ typedef typename bc::make_vector_type<S, 16>::type T;
+ S s1 = S(1.5f);
+ S s2 = S(2.5f);
+ S s3 = S(42.0f);
+ S s4 = S(84.0f);
+ S s5 = S(122.5f);
+ S s6 = S(131.5f);
+ S s7 = S(142.0f);
+ S s8 = S(254.0f);
+
+ T v1 = T(s1, s2, s3, s4, s5, s6, s7, s8, s1, s2, s3, s4, s5, s6, s7, s8);
+ T v2 = T(s3, s4, s1, s2, s7, s8, s5, s6, s4, s3, s2, s1, s8, s7, s6, s5);
+ T v3 = T(s4, s3, s2, s1, s8, s7, s6, s5, s8, s7, s6, s5, s4, s3, s2, s1);
+ test_fill_n(v1, v2, v3, queue);
+}
+
+BOOST_AUTO_TEST_CASE(check_fill_type)
+{
+ bc::vector<int> vector(5, context);
+ bc::future<void> future =
+ bc::fill_async(vector.begin(), vector.end(), 42, queue);
+ future.wait();
+
+ #ifdef BOOST_COMPUTE_CL_VERSION_1_2
+ BOOST_CHECK_EQUAL(
+ future.get_event().get_command_type(),
+ device.check_version(1,2) ? CL_COMMAND_FILL_BUFFER : CL_COMMAND_NDRANGE_KERNEL
+ );
+ #else
+ BOOST_CHECK(
+ future.get_event().get_command_type() == CL_COMMAND_NDRANGE_KERNEL
+ );
+ #endif
+}
+
+BOOST_AUTO_TEST_CASE(fill_clone_buffer)
+{
+ int data[] = { 1, 2, 3, 4 };
+ bc::vector<int> vec(data, data + 4, queue);
+ CHECK_RANGE_EQUAL(int, 4, vec, (1, 2, 3, 4));
+
+ bc::buffer cloned_buffer = vec.get_buffer().clone(queue);
+ BOOST_CHECK(
+ bc::equal(
+ vec.begin(),
+ vec.end(),
+ bc::make_buffer_iterator<int>(cloned_buffer, 0),
+ queue
+ )
+ );
+
+ bc::fill(vec.begin(), vec.end(), 5, queue);
+ BOOST_CHECK(
+ !bc::equal(
+ vec.begin(),
+ vec.end(),
+ bc::make_buffer_iterator<int>(cloned_buffer, 0),
+ queue
+ )
+ );
+
+ bc::fill(
+ bc::make_buffer_iterator<int>(cloned_buffer, 0),
+ bc::make_buffer_iterator<int>(cloned_buffer, 4),
+ 5,
+ queue
+ );
+ BOOST_CHECK(
+ bc::equal(
+ vec.begin(),
+ vec.end(),
+ bc::make_buffer_iterator<int>(cloned_buffer, 0),
+ queue
+ )
+ );
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+BOOST_AUTO_TEST_CASE(fill_svm_buffer)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ size_t size = 4;
+ bc::svm_ptr<cl_int> ptr =
+ bc::svm_alloc<cl_int>(context, size * sizeof(cl_int));
+ bc::fill_n(ptr, size * sizeof(cl_int), 42, queue);
+
+ queue.enqueue_svm_map(ptr.get(), size * sizeof(cl_int), CL_MAP_READ);
+ for(size_t i = 0; i < size; i++) {
+ BOOST_CHECK_EQUAL(static_cast<cl_int*>(ptr.get())[i], 42);
+ }
+ queue.enqueue_svm_unmap(ptr.get());
+
+ bc::svm_free(context, ptr);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+
+BOOST_AUTO_TEST_CASE(empty_fill)
+{
+ bc::vector<int> vec(0, context);
+ bc::fill(vec.begin(), vec.end(), 42, queue);
+ bc::fill_async(vec.begin(), vec.end(), 42, queue);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_find.cpp b/src/boost/libs/compute/test/test_find.cpp
new file mode 100644
index 00000000..d17823f8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_find.cpp
@@ -0,0 +1,107 @@
+//---------------------------------------------------------------------------//
+// 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 TestFind
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/find_if_not.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_buffer_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(find_int)
+{
+ int data[] = { 9, 15, 1, 4, 9, 9, 4, 15, 12, 1 };
+ bc::vector<int> vector(data, data + 10, queue);
+
+ bc::vector<int>::iterator iter =
+ bc::find(vector.begin(), vector.end(), 4, queue);
+ BOOST_CHECK(iter == vector.begin() + 3);
+ BOOST_CHECK_EQUAL(*iter, 4);
+
+ iter = bc::find(vector.begin(), vector.end(), 12, queue);
+ BOOST_CHECK(iter == vector.begin() + 8);
+ BOOST_CHECK_EQUAL(*iter, 12);
+
+ iter = bc::find(vector.begin(), vector.end(), 1, queue);
+ BOOST_CHECK(iter == vector.begin() + 2);
+ BOOST_CHECK_EQUAL(*iter, 1);
+
+ iter = bc::find(vector.begin(), vector.end(), 9, queue);
+ BOOST_CHECK(iter == vector.begin());
+ BOOST_CHECK_EQUAL(*iter, 9);
+
+ iter = bc::find(vector.begin(), vector.end(), 100, queue);
+ BOOST_CHECK(iter == vector.end());
+}
+
+BOOST_AUTO_TEST_CASE(find_int2)
+{
+ using bc::int2_;
+
+ int data[] = { 1, 2, 4, 5, 7, 8 };
+ bc::vector<int2_> vector(
+ reinterpret_cast<int2_ *>(data),
+ reinterpret_cast<int2_ *>(data) + 3,
+ queue
+ );
+ CHECK_RANGE_EQUAL(int2_, 3, vector, (int2_(1, 2), int2_(4, 5), int2_(7, 8)));
+
+ bc::vector<int2_>::iterator iter =
+ bc::find(vector.begin(), vector.end(), int2_(4, 5), queue);
+ BOOST_CHECK(iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*iter, int2_(4, 5));
+
+ iter = bc::find(vector.begin(), vector.end(), int2_(10, 11), queue);
+ BOOST_CHECK(iter == vector.end());
+}
+
+BOOST_AUTO_TEST_CASE(find_if_not_int)
+{
+ int data[] = { 2, 4, 6, 8, 1, 3, 5, 7, 9 };
+ bc::vector<int> vector(data, data + 9, queue);
+
+ bc::vector<int>::iterator iter =
+ bc::find_if_not(vector.begin(), vector.end(), bc::_1 == 2, queue);
+ BOOST_CHECK(iter == vector.begin() + 1);
+ BOOST_CHECK_EQUAL(*iter, 4);
+}
+
+BOOST_AUTO_TEST_CASE(find_point_by_distance)
+{
+ using boost::compute::float2_;
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::distance;
+
+ float2_ points[] = {
+ float2_(0, 0), float2_(2, 2), float2_(4, 4), float2_(8, 8)
+ };
+ compute::vector<float2_> vec(points, points + 4, queue);
+
+ compute::vector<float2_>::iterator iter =
+ compute::find_if(vec.begin(), vec.end(), distance(_1, float2_(5, 5)) < 1.5f, queue);
+ BOOST_CHECK(iter == vec.begin() + 2);
+
+ float2_ value;
+ compute::copy_n(iter, 1, &value, queue);
+ BOOST_CHECK_EQUAL(value, float2_(4, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_find_end.cpp b/src/boost/libs/compute/test/test_find_end.cpp
new file mode 100644
index 00000000..6ef050d0
--- /dev/null
+++ b/src/boost/libs/compute/test/test_find_end.cpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestFindEnd
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/find_end.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(find_end_int)
+{
+ bc::int_ data[] = {1, 4, 2, 6, 3, 2, 6, 3, 4, 6};
+ bc::vector<bc::int_> vectort(data, data + 10, queue);
+
+ bc::int_ datap[] = {2, 6};
+ bc::vector<bc::int_> vectorp(datap, datap + 2, queue);
+
+ bc::vector<bc::int_>::iterator iter =
+ bc::find_end(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 5);
+
+ vectorp.insert(vectorp.begin() + 1, bc::int_(9), queue);
+
+ iter =
+ bc::find_end(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.end());
+}
+
+BOOST_AUTO_TEST_CASE(find_end_string)
+{
+ bc::char_ text[] = "sdabababacabskjabacab";
+ bc::vector<bc::char_> vectort(text, text + 21, queue);
+
+ bc::char_ pattern[] = "aba";
+ bc::vector<bc::char_> vectorp(pattern, pattern + 3, queue);
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::find_end(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == (vectort.begin() + 15));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_flat_map.cpp b/src/boost/libs/compute/test/test_flat_map.cpp
new file mode 100644
index 00000000..c1f96aa8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_flat_map.cpp
@@ -0,0 +1,147 @@
+//---------------------------------------------------------------------------//
+// 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 TestFlatMap
+#include <boost/test/unit_test.hpp>
+
+#include <utility>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/compute/source.hpp>
+#include <boost/compute/container/flat_map.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/type_traits/type_definition.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(concept_check)
+{
+ BOOST_CONCEPT_ASSERT((boost::Container<boost::compute::flat_map<int, float> >));
+// BOOST_CONCEPT_ASSERT((boost::SimpleAssociativeContainer<boost::compute::flat_map<int, float> >));
+// BOOST_CONCEPT_ASSERT((boost::UniqueAssociativeContainer<boost::compute::flat_map<int, float> >));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<boost::compute::flat_map<int, float>::iterator>));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<boost::compute::flat_map<int, float>::const_iterator>));
+}
+
+BOOST_AUTO_TEST_CASE(insert)
+{
+ boost::compute::flat_map<int, float> map(context);
+ map.insert(std::make_pair(1, 1.1f), queue);
+ map.insert(std::make_pair(-1, -1.1f), queue);
+ map.insert(std::make_pair(3, 3.3f), queue);
+ map.insert(std::make_pair(2, 2.2f), queue);
+ BOOST_CHECK_EQUAL(map.size(), size_t(4));
+ BOOST_CHECK(map.find(-1) == map.begin() + 0);
+ BOOST_CHECK(map.find(1) == map.begin() + 1);
+ BOOST_CHECK(map.find(2) == map.begin() + 2);
+ BOOST_CHECK(map.find(3) == map.begin() + 3);
+
+ map.insert(std::make_pair(2, -2.2f), queue);
+ BOOST_CHECK_EQUAL(map.size(), size_t(4));
+}
+
+BOOST_AUTO_TEST_CASE(at)
+{
+ boost::compute::flat_map<int, float> map(context);
+ map.insert(std::make_pair(1, 1.1f), queue);
+ map.insert(std::make_pair(4, 4.4f), queue);
+ map.insert(std::make_pair(3, 3.3f), queue);
+ map.insert(std::make_pair(2, 2.2f), queue);
+ BOOST_CHECK_EQUAL(float(map.at(1)), float(1.1f));
+ BOOST_CHECK_EQUAL(float(map.at(2)), float(2.2f));
+ BOOST_CHECK_EQUAL(float(map.at(3)), float(3.3f));
+ BOOST_CHECK_EQUAL(float(map.at(4)), float(4.4f));
+}
+
+BOOST_AUTO_TEST_CASE(index_operator)
+{
+ boost::compute::flat_map<int, float> map;
+ map[1] = 1.1f;
+ map[2] = 2.2f;
+ map[3] = 3.3f;
+ map[4] = 4.4f;
+ BOOST_CHECK_EQUAL(float(map[1]), float(1.1f));
+ BOOST_CHECK_EQUAL(float(map[2]), float(2.2f));
+ BOOST_CHECK_EQUAL(float(map[3]), float(3.3f));
+ BOOST_CHECK_EQUAL(float(map[4]), float(4.4f));
+}
+
+BOOST_AUTO_TEST_CASE(custom_kernel)
+{
+ typedef boost::compute::flat_map<int, float> MapType;
+
+ // map from int->float on device
+ MapType map(context);
+ map.insert(std::make_pair(1, 1.2f), queue);
+ map.insert(std::make_pair(3, 3.4f), queue);
+ map.insert(std::make_pair(5, 5.6f), queue);
+ map.insert(std::make_pair(7, 7.8f), queue);
+
+ // simple linear search for key in map
+ const char lookup_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void lookup(__global const MapType *map,
+ const int map_size,
+ const KeyType key,
+ __global ValueType *result)
+ {
+ for(int i = 0; i < map_size; i++){
+ if(map[i].first == key){
+ *result = map[i].second;
+ break;
+ }
+ }
+ }
+ );
+
+ // create program source
+ std::stringstream source;
+
+ // add type definition for map type
+ source << boost::compute::type_definition<MapType::value_type>();
+
+ // add lookup function source
+ source << lookup_source;
+
+ // create lookup program
+ boost::compute::program lookup_program =
+ boost::compute::program::create_with_source(source.str(), context);
+
+ // program build options
+ std::stringstream options;
+ options << "-DMapType=" << boost::compute::type_name<MapType::value_type>()
+ << " -DKeyType=" << boost::compute::type_name<MapType::key_type>()
+ << " -DValueType=" << boost::compute::type_name<MapType::mapped_type>();
+
+ // build lookup program with options
+ lookup_program.build(options.str());
+
+ // create buffer for result value
+ boost::compute::vector<float> result(1, context);
+
+ // create lookup kernel
+ boost::compute::kernel lookup_kernel = lookup_program.create_kernel("lookup");
+
+ // set kernel arguments
+ lookup_kernel.set_arg(0, map.begin().get_buffer()); // map buffer
+ lookup_kernel.set_arg<boost::compute::int_>(
+ 1, static_cast<boost::compute::int_>(map.size())
+ ); // map size
+ lookup_kernel.set_arg<MapType::key_type>(2, 5); // key
+ lookup_kernel.set_arg(3, result.get_buffer()); // result buffer
+
+ // run kernel with a single work-item
+ queue.enqueue_task(lookup_kernel);
+
+ // check result from buffer
+ BOOST_CHECK_EQUAL(result.begin().read(queue), 5.6f);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_flat_set.cpp b/src/boost/libs/compute/test/test_flat_set.cpp
new file mode 100644
index 00000000..798bf4ce
--- /dev/null
+++ b/src/boost/libs/compute/test/test_flat_set.cpp
@@ -0,0 +1,136 @@
+//---------------------------------------------------------------------------//
+// 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 TestFlatSet
+#include <boost/test/unit_test.hpp>
+
+#include <utility>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/flat_set.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(concept_check)
+{
+ BOOST_CONCEPT_ASSERT((boost::Container<bc::flat_set<int> >));
+// BOOST_CONCEPT_ASSERT((boost::SimpleAssociativeContainer<bc::flat_set<int> >));
+// BOOST_CONCEPT_ASSERT((boost::UniqueAssociativeContainer<bc::flat_set<int> >));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<bc::flat_set<int>::iterator>));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<bc::flat_set<int>::const_iterator>));
+}
+
+BOOST_AUTO_TEST_CASE(insert)
+{
+ bc::flat_set<int> set(context);
+ typedef bc::flat_set<int>::iterator iterator;
+ std::pair<iterator, bool> location = set.insert(12, queue);
+ queue.finish();
+ BOOST_CHECK(location.first == set.begin());
+ BOOST_CHECK(location.second == true);
+ BOOST_CHECK_EQUAL(*location.first, 12);
+ BOOST_CHECK_EQUAL(set.size(), size_t(1));
+
+ location = set.insert(12, queue);
+ queue.finish();
+ BOOST_CHECK(location.first == set.begin());
+ BOOST_CHECK(location.second == false);
+ BOOST_CHECK_EQUAL(set.size(), size_t(1));
+
+ location = set.insert(4, queue);
+ queue.finish();
+ BOOST_CHECK(location.first == set.begin());
+ BOOST_CHECK(location.second == true);
+ BOOST_CHECK_EQUAL(set.size(), size_t(2));
+
+ location = set.insert(12, queue);
+ queue.finish();
+ BOOST_CHECK(location.first == set.begin() + 1);
+ BOOST_CHECK(location.second == false);
+ BOOST_CHECK_EQUAL(set.size(), size_t(2));
+
+ location = set.insert(9, queue);
+ queue.finish();
+ BOOST_CHECK(location.first == set.begin() + 1);
+ BOOST_CHECK(location.second == true);
+ BOOST_CHECK_EQUAL(set.size(), size_t(3));
+}
+
+BOOST_AUTO_TEST_CASE(erase)
+{
+ bc::flat_set<int> set(context);
+ typedef bc::flat_set<int>::iterator iterator;
+ set.insert(1, queue);
+ set.insert(2, queue);
+ set.insert(3, queue);
+ set.insert(4, queue);
+ set.insert(5, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(set.size(), size_t(5));
+
+ iterator i = set.erase(set.begin(), queue);
+ queue.finish();
+ BOOST_CHECK(i == set.begin() + 1);
+ BOOST_CHECK_EQUAL(set.size(), size_t(4));
+ BOOST_CHECK_EQUAL(*set.begin(), 2);
+
+ size_t count = set.erase(3, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(count, size_t(1));
+ BOOST_CHECK_EQUAL(set.size(), size_t(3));
+ BOOST_CHECK_EQUAL(*set.begin(), 2);
+
+ count = set.erase(9, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(count, size_t(0));
+ BOOST_CHECK_EQUAL(set.size(), size_t(3));
+ BOOST_CHECK_EQUAL(*set.begin(), 2);
+
+ i = set.erase(set.begin() + 1, queue);
+ queue.finish();
+ BOOST_CHECK(i == set.begin() + 2);
+ BOOST_CHECK_EQUAL(set.size(), size_t(2));
+ BOOST_CHECK_EQUAL(*set.begin(), 2);
+ BOOST_CHECK_EQUAL(*(set.end() - 1), 5);
+
+ set.erase(set.begin(), set.end(), queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(set.size(), size_t(0));
+}
+
+BOOST_AUTO_TEST_CASE(clear)
+{
+ bc::flat_set<float> set;
+ BOOST_CHECK(set.empty() == true);
+ BOOST_CHECK_EQUAL(set.size(), size_t(0));
+
+ set.clear();
+ BOOST_CHECK(set.empty() == true);
+ BOOST_CHECK_EQUAL(set.size(), size_t(0));
+
+ set.insert(3.14f);
+ BOOST_CHECK(set.empty() == false);
+ BOOST_CHECK_EQUAL(set.size(), size_t(1));
+
+ set.insert(4.184f);
+ BOOST_CHECK(set.empty() == false);
+ BOOST_CHECK_EQUAL(set.size(), size_t(2));
+
+ set.clear();
+ BOOST_CHECK(set.empty() == true);
+ BOOST_CHECK_EQUAL(set.size(), size_t(0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_for_each.cpp b/src/boost/libs/compute/test/test_for_each.cpp
new file mode 100644
index 00000000..d695738e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_for_each.cpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// 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 TestForEach
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/for_each.hpp>
+#include <boost/compute/algorithm/for_each_n.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(for_each_nop)
+{
+ bc::vector<int> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), 0, queue);
+
+ BOOST_COMPUTE_FUNCTION(void, nop, (int ignored), {});
+
+ bc::for_each(vector.begin(), vector.end(), nop, queue);
+ queue.finish();
+}
+
+BOOST_AUTO_TEST_CASE(for_each_n_nop)
+{
+ bc::vector<int> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), 0, queue);
+
+ BOOST_COMPUTE_FUNCTION(void, nop, (int ignored), {});
+
+ bc::for_each_n(vector.begin(), vector.size(), nop, queue);
+ queue.finish();
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_function.cpp b/src/boost/libs/compute/test/test_function.cpp
new file mode 100644
index 00000000..63889dcb
--- /dev/null
+++ b/src/boost/libs/compute/test/test_function.cpp
@@ -0,0 +1,209 @@
+//---------------------------------------------------------------------------//
+// 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 TestFunction
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/generate.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/types/pair.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(add_three)
+{
+ BOOST_COMPUTE_FUNCTION(int, add_three, (int x),
+ {
+ return x + 3;
+ });
+
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(), add_three, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (4, 5, 6, 7));
+}
+
+BOOST_AUTO_TEST_CASE(sum_odd_values)
+{
+ BOOST_COMPUTE_FUNCTION(int, add_odd_value, (int sum, int value),
+ {
+ if(value & 1){
+ return sum + value;
+ }
+ else {
+ return sum + 0;
+ }
+ });
+
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> vector(data, data + 8, queue);
+
+ int result = compute::accumulate(
+ vector.begin(), vector.end(), 0, add_odd_value, queue
+ );
+ BOOST_CHECK_EQUAL(result, 16);
+}
+
+BOOST_AUTO_TEST_CASE(sort_pairs)
+{
+ if(device.vendor() == "NVIDIA" && device.platform().name() == "Apple"){
+ // FIXME: this test currently segfaults on NVIDIA GPUs on Apple
+ std::cerr << "skipping sort_pairs test on NVIDIA GPU on Apple platform" << std::endl;
+ return;
+ }
+
+ std::vector<std::pair<int, float> > data;
+ data.push_back(std::make_pair(1, 2.3f));
+ data.push_back(std::make_pair(0, 4.2f));
+ data.push_back(std::make_pair(2, 1.0f));
+
+ compute::vector<std::pair<int, float> > vector(data.begin(), data.end(), queue);
+
+ // sort by first component
+ BOOST_COMPUTE_FUNCTION(bool, compare_first, (std::pair<int, float> a, std::pair<int, float> b),
+ {
+ return a.first < b.first;
+ });
+
+ compute::sort(vector.begin(), vector.end(), compare_first, queue);
+ compute::copy(vector.begin(), vector.end(), data.begin(), queue);
+ BOOST_CHECK(data[0] == std::make_pair(0, 4.2f));
+ BOOST_CHECK(data[1] == std::make_pair(1, 2.3f));
+ BOOST_CHECK(data[2] == std::make_pair(2, 1.0f));
+
+ // sort by second component
+ BOOST_COMPUTE_FUNCTION(bool, compare_second, (std::pair<int, float> a, std::pair<int, float> b),
+ {
+ return a.second < b.second;
+ });
+
+ compute::sort(vector.begin(), vector.end(), compare_second, queue);
+ compute::copy(vector.begin(), vector.end(), data.begin(), queue);
+ BOOST_CHECK(data[0] == std::make_pair(2, 1.0f));
+ BOOST_CHECK(data[1] == std::make_pair(1, 2.3f));
+ BOOST_CHECK(data[2] == std::make_pair(0, 4.2f));
+}
+
+BOOST_AUTO_TEST_CASE(transform_zip_iterator)
+{
+ float float_data[] = { 1.f, 2.f, 3.f, 4.f };
+ compute::vector<float> input_floats(float_data, float_data + 4, queue);
+
+ int int_data[] = { 2, 4, 6, 8 };
+ compute::vector<int> input_ints(int_data, int_data + 4, queue);
+
+ compute::vector<float> results(4, context);
+
+ BOOST_COMPUTE_FUNCTION(float, tuple_pown, (boost::tuple<float, int> x),
+ {
+ return pown(boost_tuple_get(x, 0), boost_tuple_get(x, 1));
+ });
+
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input_floats.begin(), input_ints.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input_floats.end(), input_ints.end())
+ ),
+ results.begin(),
+ tuple_pown,
+ queue
+ );
+
+ float results_data[4];
+ compute::copy(results.begin(), results.end(), results_data, queue);
+ BOOST_CHECK_CLOSE(results_data[0], 1.f, 1e-4);
+ BOOST_CHECK_CLOSE(results_data[1], 16.f, 1e-4);
+ BOOST_CHECK_CLOSE(results_data[2], 729.f, 1e-4);
+ BOOST_CHECK_CLOSE(results_data[3], 65536.f, 1e-4);
+}
+
+static BOOST_COMPUTE_FUNCTION(int, static_function, (int x),
+{
+ return x + 5;
+});
+
+BOOST_AUTO_TEST_CASE(test_static_function)
+{
+ int data[] = { 1, 2, 3, 4};
+ compute::vector<int> vec(data, data + 4, queue);
+
+ compute::transform(
+ vec.begin(), vec.end(), vec.begin(), static_function, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vec, (6, 7, 8, 9));
+}
+
+template<class T>
+inline compute::function<T(T)> make_negate_function()
+{
+ BOOST_COMPUTE_FUNCTION(T, negate, (const T x),
+ {
+ return -x;
+ });
+
+ return negate;
+}
+
+BOOST_AUTO_TEST_CASE(test_templated_function)
+{
+ int int_data[] = { 1, 2, 3, 4 };
+ compute::vector<int> int_vec(int_data, int_data + 4, queue);
+
+ compute::function<int(int)> negate_int = make_negate_function<int>();
+ compute::transform(
+ int_vec.begin(), int_vec.end(), int_vec.begin(), negate_int, queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, int_vec, (-1, -2, -3, -4));
+
+ float float_data[] = { 1.1f, 2.2f, 3.3f, 4.4f };
+ compute::vector<float> float_vec(float_data, float_data + 4, queue);
+
+ compute::function<float(float)> negate_float = make_negate_function<float>();
+ compute::transform(
+ float_vec.begin(), float_vec.end(), float_vec.begin(), negate_float, queue
+ );
+ CHECK_RANGE_EQUAL(float, 4, float_vec, (-1.1f, -2.2f, -3.3f, -4.4f));
+}
+
+BOOST_AUTO_TEST_CASE(define)
+{
+ BOOST_COMPUTE_FUNCTION(int, return_number, (),
+ {
+ return NUMBER;
+ });
+ return_number.define("NUMBER", "4");
+
+ compute::vector<int> vec(1, context);
+ compute::generate(vec.begin(), vec.end(), return_number, queue);
+ CHECK_RANGE_EQUAL(int, 1, vec, (4));
+
+ return_number.define("NUMBER", "2");
+ compute::generate(vec.begin(), vec.end(), return_number, queue);
+ CHECK_RANGE_EQUAL(int, 1, vec, (2));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_function_input_iterator.cpp b/src/boost/libs/compute/test/test_function_input_iterator.cpp
new file mode 100644
index 00000000..b5c315f7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_function_input_iterator.cpp
@@ -0,0 +1,50 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestFunctionInputIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/function_input_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(generate_42_doctest)
+{
+ boost::compute::vector<int> result(4, context);
+
+//! [generate_42]
+BOOST_COMPUTE_FUNCTION(int, ret42, (),
+{
+ return 42;
+});
+
+boost::compute::copy(
+ boost::compute::make_function_input_iterator(ret42, 0),
+ boost::compute::make_function_input_iterator(ret42, result.size()),
+ result.begin(),
+ queue
+);
+
+// result == { 42, 42, 42, 42 }
+//! [generate_42]
+
+ CHECK_RANGE_EQUAL(int, 4, result, (42, 42, 42, 42));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_as.cpp b/src/boost/libs/compute/test/test_functional_as.cpp
new file mode 100644
index 00000000..f1318b0a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_as.cpp
@@ -0,0 +1,59 @@
+//---------------------------------------------------------------------------//
+// 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 TestFunctionalAs
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/as.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(roundtrip_int_float)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> input(8, context);
+ compute::copy_n(data, 8, input.begin(), queue);
+
+ // convert int -> float
+ compute::vector<float> output(8, context);
+ compute::transform(
+ input.begin(),
+ input.end(),
+ output.begin(),
+ compute::as<float>(),
+ queue
+ );
+
+ // zero out input
+ compute::fill(input.begin(), input.end(), 0, queue);
+
+ // convert float -> int
+ compute::transform(
+ output.begin(),
+ output.end(),
+ input.begin(),
+ compute::as<int>(),
+ queue
+ );
+
+ // check values
+ CHECK_RANGE_EQUAL(
+ int, 8, input, (1, 2, 3, 4, 5, 6, 7, 8)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_bind.cpp b/src/boost/libs/compute/test/test_functional_bind.cpp
new file mode 100644
index 00000000..327232d8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_bind.cpp
@@ -0,0 +1,237 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestFunctionalBind
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/bind.hpp>
+#include <boost/compute/functional/common.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/types/struct.hpp>
+
+// simple test struct
+struct data_struct
+{
+ int int_value;
+ float float_value;
+};
+
+BOOST_COMPUTE_ADAPT_STRUCT(data_struct, data_struct, (int_value, float_value))
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+using compute::placeholders::_1;
+using compute::placeholders::_2;
+
+BOOST_AUTO_TEST_CASE(transform_plus_two)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(4, context);
+ compute::copy_n(data, 4, vector.begin(), queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(compute::plus<int>(), _1, 2),
+ queue
+ );
+
+ CHECK_RANGE_EQUAL(int, 4, vector, (3, 4, 5, 6));
+}
+
+BOOST_AUTO_TEST_CASE(transform_pow_two)
+{
+ float data[] = { 2, 3, 4, 5 };
+ compute::vector<float> vector(4, context);
+ compute::copy_n(data, 4, vector.begin(), queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(compute::pow<float>(), 2.0f, _1),
+ queue
+ );
+
+ compute::copy(vector.begin(), vector.end(), data, queue);
+ BOOST_CHECK_CLOSE(data[0], 4.0f, 1e-4);
+ BOOST_CHECK_CLOSE(data[1], 8.0f, 1e-4);
+ BOOST_CHECK_CLOSE(data[2], 16.0f, 1e-4);
+ BOOST_CHECK_CLOSE(data[3], 32.0f, 1e-4);
+}
+
+BOOST_AUTO_TEST_CASE(find_if_equal)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(4, context);
+ compute::copy_n(data, 4, vector.begin(), queue);
+
+ BOOST_CHECK(
+ compute::find_if(
+ vector.begin(), vector.end(),
+ compute::bind(compute::equal_to<int>(), _1, 3),
+ queue
+ ) == vector.begin() + 2
+ );
+}
+
+BOOST_AUTO_TEST_CASE(compare_less_than)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ int count = boost::compute::count_if(
+ vector.begin(), vector.end(),
+ compute::bind(compute::less<int>(), _1, int(3)),
+ queue
+ );
+ BOOST_CHECK_EQUAL(count, 2);
+
+ count = boost::compute::count_if(
+ vector.begin(), vector.end(),
+ compute::bind(compute::less<int>(), int(3), _1),
+ queue
+ );
+ BOOST_CHECK_EQUAL(count, 1);
+}
+
+BOOST_AUTO_TEST_CASE(subtract_ranges)
+{
+ int data1[] = { 1, 2, 3, 4 };
+ int data2[] = { 4, 3, 2, 1 };
+
+ compute::vector<int> vector1(data1, data1 + 4, queue);
+ compute::vector<int> vector2(data2, data2 + 4, queue);
+
+ compute::vector<int> result(4, context);
+
+ compute::transform(
+ vector1.begin(),
+ vector1.end(),
+ vector2.begin(),
+ result.begin(),
+ compute::bind(compute::minus<int>(), _1, _2),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, result, (-3, -1, 1, 3));
+
+ compute::transform(
+ vector1.begin(),
+ vector1.end(),
+ vector2.begin(),
+ result.begin(),
+ compute::bind(compute::minus<int>(), _2, _1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, result, (3, 1, -1, -3));
+
+ compute::transform(
+ vector1.begin(),
+ vector1.end(),
+ vector2.begin(),
+ result.begin(),
+ compute::bind(compute::minus<int>(), 5, _1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, result, (4, 3, 2, 1));
+
+ compute::transform(
+ vector1.begin(),
+ vector1.end(),
+ vector2.begin(),
+ result.begin(),
+ compute::bind(compute::minus<int>(), 5, _2),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, result, (1, 2, 3, 4));
+}
+
+BOOST_AUTO_TEST_CASE(clamp_values)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(compute::clamp<int>(), _1, 2, 3),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (2, 2, 3, 3));
+}
+
+BOOST_AUTO_TEST_CASE(bind_custom_function)
+{
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ BOOST_COMPUTE_FUNCTION(int, x_if_odd_else_y, (int x, int y),
+ {
+ if(x & 1)
+ return x;
+ else
+ return y;
+ });
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(x_if_odd_else_y, _1, 9),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (1, 9, 3, 9));
+
+ compute::copy(
+ data, data + 4, vector.begin(), queue
+ );
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(x_if_odd_else_y, 2, _1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (1, 2, 3, 4));
+}
+
+BOOST_AUTO_TEST_CASE(bind_struct)
+{
+ if(bug_in_struct_assignment(device)){
+ std::cerr << "skipping bind_struct test" << std::endl;
+ return;
+ }
+
+ BOOST_COMPUTE_FUNCTION(int, add_struct_value, (int x, data_struct s),
+ {
+ return s.int_value + x;
+ });
+
+ data_struct data;
+ data.int_value = 3;
+ data.float_value = 4.56f;
+
+ int input[] = { 1, 2, 3, 4 };
+ compute::vector<int> vec(input, input + 4, queue);
+
+ compute::transform(
+ vec.begin(), vec.end(), vec.begin(),
+ compute::bind(add_struct_value, _1, data),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vec, (4, 5, 6, 7));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_convert.cpp b/src/boost/libs/compute/test/test_functional_convert.cpp
new file mode 100644
index 00000000..b3303af3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_convert.cpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// 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 TestFunctionalConvert
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/convert.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(convert_int_float)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> input(8, context);
+ compute::copy_n(data, 8, input.begin(), queue);
+
+ compute::vector<float> output(8, context);
+ compute::transform(
+ input.begin(),
+ input.end(),
+ output.begin(),
+ compute::convert<float>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(
+ float, 8, output, (1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_get.cpp b/src/boost/libs/compute/test/test_functional_get.cpp
new file mode 100644
index 00000000..9536145e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_get.cpp
@@ -0,0 +1,83 @@
+//---------------------------------------------------------------------------//
+// 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 TestFunctionalGet
+#include <boost/test/unit_test.hpp>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/types/pair.hpp>
+#include <boost/compute/types/tuple.hpp>
+#include <boost/compute/types/fundamental.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(get_vector_result_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<0>(compute::float4_)
+ >::type,
+ float
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<1>(compute::int2_)
+ >::type,
+ int
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(get_pair_result_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<0>(std::pair<int, float>)
+ >::type,
+ int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<1>(std::pair<compute::float2_, compute::char4_>)
+ >::type,
+ compute::char4_
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(get_tuple_result_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<0>(boost::tuple<int, int, double>)
+ >::type,
+ int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::result_of<
+ compute::get<2>(boost::tuple<char, int, float>)
+ >::type,
+ float
+ >::value
+ ));
+}
diff --git a/src/boost/libs/compute/test/test_functional_hash.cpp b/src/boost/libs/compute/test/test_functional_hash.cpp
new file mode 100644
index 00000000..e6e1c112
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_hash.cpp
@@ -0,0 +1,42 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestFunctionalHash
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/hash.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(hash_int)
+{
+ using compute::ulong_;
+
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> input_values(data, data + 4, queue);
+ compute::vector<ulong_> hash_values(4, context);
+
+ compute::transform(
+ input_values.begin(),
+ input_values.end(),
+ hash_values.begin(),
+ compute::hash<int>(),
+ queue
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_identity.cpp b/src/boost/libs/compute/test/test_functional_identity.cpp
new file mode 100644
index 00000000..93534c05
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_identity.cpp
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestFunctionalIdentity
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/identity.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(copy_with_identity_transform)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> input(data, data + 8, queue);
+ compute::vector<int> output(8, context);
+
+ compute::transform(
+ input.begin(), input.end(), output.begin(), compute::identity<int>(), queue
+ );
+
+ CHECK_RANGE_EQUAL(
+ int, 8, output, (1, 2, 3, 4, 5, 6, 7, 8)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_popcount.cpp b/src/boost/libs/compute/test/test_functional_popcount.cpp
new file mode 100644
index 00000000..4a15a508
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_popcount.cpp
@@ -0,0 +1,42 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestFunctionalPopcount
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/popcount.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+typedef boost::mpl::list<
+ compute::uchar_, compute::ushort_, compute::uint_, compute::ulong_
+> popcount_test_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(popcount, T, popcount_test_types)
+{
+ compute::vector<T> vec(context);
+ vec.push_back(0x00, queue);
+ vec.push_back(0x01, queue);
+ vec.push_back(0x03, queue);
+ vec.push_back(0xff, queue);
+
+ compute::vector<int> popcounts(vec.size(), context);
+ compute::transform(
+ vec.begin(), vec.end(), popcounts.begin(), compute::popcount<T>(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, popcounts, (0, 1, 2, 8));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_functional_unpack.cpp b/src/boost/libs/compute/test/test_functional_unpack.cpp
new file mode 100644
index 00000000..98460071
--- /dev/null
+++ b/src/boost/libs/compute/test/test_functional_unpack.cpp
@@ -0,0 +1,99 @@
+//---------------------------------------------------------------------------//
+// 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 TestFunctionalUnpack
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/functional/detail/unpack.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(plus_int)
+{
+ int data1[] = { 1, 3, 5, 7 };
+ int data2[] = { 2, 4, 6, 8 };
+
+ compute::vector<int> input1(4, context);
+ compute::vector<int> input2(4, context);
+
+ compute::copy_n(data1, 4, input1.begin(), queue);
+ compute::copy_n(data2, 4, input2.begin(), queue);
+
+ compute::vector<int> output(4, context);
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.begin(), input2.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.end(), input2.end())
+ ),
+ output.begin(),
+ compute::detail::unpack(compute::plus<int>()),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (3, 7, 11, 15));
+}
+
+BOOST_AUTO_TEST_CASE(fma_float)
+{
+ float data1[] = { 1, 3, 5, 7 };
+ float data2[] = { 2, 4, 6, 8 };
+ float data3[] = { 0, 9, 1, 2 };
+
+ compute::vector<float> input1(4, context);
+ compute::vector<float> input2(4, context);
+ compute::vector<float> input3(4, context);
+
+ compute::copy_n(data1, 4, input1.begin(), queue);
+ compute::copy_n(data2, 4, input2.begin(), queue);
+ compute::copy_n(data3, 4, input3.begin(), queue);
+
+ compute::vector<int> output(4, context);
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.begin(), input2.begin(), input3.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.end(), input2.end(), input3.begin())
+ ),
+ output.begin(),
+ compute::detail::unpack(compute::fma<float>()),
+ queue
+ );
+}
+
+BOOST_AUTO_TEST_CASE(subtract_int2)
+{
+ using compute::int2_;
+
+ int data[] = { 4, 2, 5, 1, 6, 3, 7, 0 };
+ compute::vector<int2_> input(4, context);
+ compute::copy_n(reinterpret_cast<int2_ *>(data), 4, input.begin(), queue);
+
+ compute::vector<int> output(4, context);
+ compute::transform(
+ input.begin(),
+ input.end(),
+ output.begin(),
+ compute::detail::unpack(compute::minus<int>()),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, output, (2, 4, 3, 7));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_gather.cpp b/src/boost/libs/compute/test/test_gather.cpp
new file mode 100644
index 00000000..2d6af2c8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_gather.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// 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 TestGather
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_if.hpp>
+#include <boost/compute/algorithm/gather.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(gather_int)
+{
+ int input_data[] = { 1, 2, 3, 4, 5 };
+ compute::vector<int> input(input_data, input_data + 5, queue);
+
+ int indices_data[] = { 0, 4, 1, 3, 2 };
+ compute::vector<int> indices(indices_data, indices_data + 5, queue);
+
+ compute::vector<int> output(5, context);
+ compute::gather(
+ indices.begin(), indices.end(), input.begin(), output.begin(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 5, 2, 4, 3));
+
+ compute::gather(
+ indices.begin() + 1, indices.end(), input.begin(), output.begin(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (5, 2, 4, 3, 3));
+}
+
+BOOST_AUTO_TEST_CASE(copy_index_then_gather)
+{
+ // input data
+ int data[] = { 1, 4, 3, 2, 5, 9, 8, 7 };
+ compute::vector<int> input(data, data + 8, queue);
+
+ // function returning true if the input is odd
+ BOOST_COMPUTE_FUNCTION(bool, is_odd, (int x),
+ {
+ return x % 2 != 0;
+ });
+
+ // copy indices of all odd values
+ compute::vector<int> odds(5, context);
+ compute::detail::copy_index_if(
+ input.begin(), input.end(), odds.begin(), is_odd, queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, odds, (0, 2, 4, 5, 7));
+
+ // gather all odd values
+ compute::vector<int> odd_values(5, context);
+ compute::gather(
+ odds.begin(), odds.end(), input.begin(), odd_values.begin(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, odd_values, (1, 3, 5, 9, 7));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_generate.cpp b/src/boost/libs/compute/test/test_generate.cpp
new file mode 100644
index 00000000..aeec0a72
--- /dev/null
+++ b/src/boost/libs/compute/test/test_generate.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// 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 TestGenerate
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/generate.hpp>
+#include <boost/compute/algorithm/generate_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/pair.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(generate4)
+{
+ bc::vector<int> vector(4, context);
+ bc::fill(vector.begin(), vector.end(), 2, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (2, 2, 2, 2));
+
+ BOOST_COMPUTE_FUNCTION(int, ret4, (void),
+ {
+ return 4;
+ });
+
+ bc::generate(vector.begin(), vector.end(), ret4, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (4, 4, 4, 4));
+}
+
+BOOST_AUTO_TEST_CASE(generate_pair)
+{
+ if(bug_in_struct_assignment(device)){
+ std::cerr << "skipping generate_pair test" << std::endl;
+ return;
+ }
+
+ // in order to use std::pair<T1, T2> with BOOST_COMPUTE_FUNCTION() macro we
+ // need a typedef. otherwise the commas in the type declaration screw it up.
+ typedef std::pair<int, float> pair_type;
+
+ bc::vector<pair_type> vector(3, context);
+
+ BOOST_COMPUTE_FUNCTION(pair_type, generate_pair, (void),
+ {
+ return boost_make_pair(int, 2, float, 3.14f);
+ });
+
+ bc::generate(vector.begin(), vector.end(), generate_pair, queue);
+
+ // check results
+ std::vector<pair_type> host_vector(3);
+ bc::copy(vector.begin(), vector.end(), host_vector.begin(), queue);
+ BOOST_CHECK(host_vector[0] == std::make_pair(2, 3.14f));
+ BOOST_CHECK(host_vector[1] == std::make_pair(2, 3.14f));
+ BOOST_CHECK(host_vector[2] == std::make_pair(2, 3.14f));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_image1d.cpp b/src/boost/libs/compute/test/test_image1d.cpp
new file mode 100644
index 00000000..364d19ed
--- /dev/null
+++ b/src/boost/libs/compute/test/test_image1d.cpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestImage1D
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/image/image1d.hpp>
+#include <boost/compute/utility/dim.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(image1d_get_supported_formats)
+{
+ const std::vector<compute::image_format> formats =
+ compute::image1d::get_supported_formats(context);
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+BOOST_AUTO_TEST_CASE(fill_image1d)
+{
+ REQUIRES_OPENCL_VERSION(1, 2); // device OpenCL version check
+
+ // single-channel unsigned char
+ compute::image_format format(CL_R, CL_UNSIGNED_INT8);
+
+ if(!compute::image1d::is_supported_format(format, context)){
+ std::cerr << "skipping fill_image1d test, image format not supported" << std::endl;
+ return;
+ }
+
+ compute::image1d img(context, 64, format);
+
+ BOOST_CHECK_EQUAL(img.width(), size_t(64));
+ BOOST_CHECK(img.size() == compute::dim(64));
+ BOOST_CHECK(img.format() == format);
+
+ // fill image with '128'
+ compute::uint4_ fill_color(128, 0, 0, 0);
+ queue.enqueue_fill_image(img, &fill_color, img.origin(), img.size());
+
+ // read value of first pixel
+ compute::uchar_ first_pixel = 0;
+ queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel);
+ BOOST_CHECK_EQUAL(first_pixel, compute::uchar_(128));
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
+
+// check type_name() for image1d
+BOOST_AUTO_TEST_CASE(image1d_type_name)
+{
+ BOOST_CHECK(
+ std::strcmp(
+ boost::compute::type_name<boost::compute::image1d>(), "image1d_t"
+ ) == 0
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_image2d.cpp b/src/boost/libs/compute/test/test_image2d.cpp
new file mode 100644
index 00000000..2ae56c47
--- /dev/null
+++ b/src/boost/libs/compute/test/test_image2d.cpp
@@ -0,0 +1,226 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestImage2D
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/utility/dim.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(image2d_get_supported_formats)
+{
+ const std::vector<compute::image_format> formats =
+ compute::image2d::get_supported_formats(context);
+}
+
+BOOST_AUTO_TEST_CASE(create_image_doctest)
+{
+ try {
+//! [create_image]
+// create 8-bit RGBA image format
+boost::compute::image_format rgba8(CL_RGBA, CL_UNSIGNED_INT8);
+
+// create 640x480 image object
+boost::compute::image2d img(context, 640, 480, rgba8);
+//! [create_image]
+
+ // verify image has been created and format is correct
+ BOOST_CHECK(img.get() != cl_mem());
+ BOOST_CHECK(img.format() == rgba8);
+ BOOST_CHECK_EQUAL(img.width(), size_t(640));
+ BOOST_CHECK_EQUAL(img.height(), size_t(480));
+ }
+ catch(compute::opencl_error &e){
+ if(e.error_code() == CL_IMAGE_FORMAT_NOT_SUPPORTED){
+ // image format not supported by device
+ return;
+ }
+
+ // some other error, rethrow
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(get_info)
+{
+ compute::image_format format(CL_RGBA, CL_UNSIGNED_INT8);
+
+ if(!compute::image2d::is_supported_format(format, context)){
+ std::cerr << "skipping get_info test, image format not supported" << std::endl;
+ return;
+ }
+
+ compute::image2d image(
+ context, 48, 64, format, compute::image2d::read_only
+ );
+
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_WIDTH), size_t(48));
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_HEIGHT), size_t(64));
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_DEPTH), size_t(0));
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_ROW_PITCH), size_t(48*4));
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_SLICE_PITCH), size_t(0));
+ BOOST_CHECK_EQUAL(image.get_info<size_t>(CL_IMAGE_ELEMENT_SIZE), size_t(4));
+
+ BOOST_CHECK(image.format() == format);
+ BOOST_CHECK_EQUAL(image.width(), size_t(48));
+ BOOST_CHECK_EQUAL(image.height(), size_t(64));
+}
+
+BOOST_AUTO_TEST_CASE(clone_image)
+{
+ compute::image_format format(CL_RGBA, CL_UNORM_INT8);
+
+ if(!compute::image2d::is_supported_format(format, context)){
+ std::cerr << "skipping clone_image test, image format not supported" << std::endl;
+ return;
+ }
+
+ // image data
+ unsigned int data[] = { 0x0000ffff, 0xff00ffff,
+ 0x00ff00ff, 0xffffffff };
+
+ // create image on the device
+ compute::image2d image(context, 2, 2, format);
+
+ // ensure we have a valid image object
+ BOOST_REQUIRE(image.get() != cl_mem());
+
+ // copy image data to the device
+ queue.enqueue_write_image(image, image.origin(), image.size(), data);
+
+ // clone image
+ compute::image2d copy = image.clone(queue);
+
+ // ensure image format is the same
+ BOOST_CHECK(copy.format() == image.format());
+
+ // read cloned image data back to the host
+ unsigned int cloned_data[4];
+ queue.enqueue_read_image(copy, image.origin(), image.size(), cloned_data);
+
+ // ensure original data and cloned data are the same
+ BOOST_CHECK_EQUAL(cloned_data[0], data[0]);
+ BOOST_CHECK_EQUAL(cloned_data[1], data[1]);
+ BOOST_CHECK_EQUAL(cloned_data[2], data[2]);
+ BOOST_CHECK_EQUAL(cloned_data[3], data[3]);
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+BOOST_AUTO_TEST_CASE(fill_image)
+{
+ REQUIRES_OPENCL_VERSION(1, 2); // device OpenCL version check
+
+ compute::image_format format(CL_RGBA, CL_UNSIGNED_INT8);
+
+ if(!compute::image2d::is_supported_format(format, context)){
+ std::cerr << "skipping fill_image test, image format not supported" << std::endl;
+ return;
+ }
+
+ compute::image2d img(context, 640, 480, format);
+
+ // fill image with black
+ compute::uint4_ black(0, 0, 0, 255);
+ queue.enqueue_fill_image(img, &black, img.origin(), img.size());
+
+ // read value of first pixel
+ compute::uchar4_ first_pixel;
+ queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel);
+ BOOST_CHECK_EQUAL(first_pixel, compute::uchar4_(0, 0, 0, 255));
+
+ // fill image with white
+ compute::uint4_ white(255, 255, 255, 255);
+ queue.enqueue_fill_image(img, &white, img.origin(), img.size());
+
+ // read value of first pixel
+ queue.enqueue_read_image(img, compute::dim(0), compute::dim(1), &first_pixel);
+ BOOST_CHECK_EQUAL(first_pixel, compute::uchar4_(255, 255, 255, 255));
+}
+#endif
+
+// check type_name() for image2d
+BOOST_AUTO_TEST_CASE(image2d_type_name)
+{
+ BOOST_CHECK(
+ std::strcmp(
+ boost::compute::type_name<boost::compute::image2d>(), "image2d_t"
+ ) == 0
+ );
+}
+
+BOOST_AUTO_TEST_CASE(map_image)
+{
+ compute::image_format format(CL_RGBA, CL_UNSIGNED_INT8);
+
+ if(!compute::image2d::is_supported_format(format, context)){
+ std::cerr << "skipping clone_image test, image format not supported" << std::endl;
+ return;
+ }
+
+ // create image on the device
+ compute::image2d image(context, 2, 2, format);
+
+ // ensure we have a valid image object
+ BOOST_REQUIRE(image.get() != cl_mem());
+
+ size_t row_pitch = 0;
+ size_t slice_pitch = 0;
+
+ // write map image
+ compute::uint_* ptr = static_cast<compute::uint_*>(
+ queue.enqueue_map_image(image, CL_MAP_WRITE, image.origin(),
+ image.size(), row_pitch, slice_pitch)
+ );
+
+ BOOST_CHECK_EQUAL(row_pitch, size_t(2*4));
+
+ // image data
+ compute::uint_ data[] = { 0x0000ffff, 0xff00ffff,
+ 0x00ff00ff, 0xffffffff };
+
+ // copy data to image
+ for(size_t i = 0; i < 4; i++){
+ *(ptr+i) = data[i];
+ }
+
+ // unmap
+ queue.enqueue_unmap_image(image, static_cast<void*>(ptr));
+
+ // read map image
+ compute::event map_event;
+ ptr = static_cast<compute::uint_*>(
+ queue.enqueue_map_image_async(image, CL_MAP_READ, image.origin(),
+ image.size(), row_pitch, slice_pitch,
+ map_event)
+ );
+
+ map_event.wait();
+
+ BOOST_CHECK(map_event.get_status() == CL_COMPLETE);
+ BOOST_CHECK_EQUAL(row_pitch, size_t(2*4));
+
+ // checking
+ for(size_t i = 0; i < 4; i++){
+ BOOST_CHECK_EQUAL(*(ptr+i), data[i]);
+ }
+
+ // unmap
+ queue.enqueue_unmap_image(image, static_cast<void*>(ptr));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_image3d.cpp b/src/boost/libs/compute/test/test_image3d.cpp
new file mode 100644
index 00000000..ee1cc15d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_image3d.cpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestImage3D
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/image/image3d.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(image3d_get_supported_formats)
+{
+ const std::vector<compute::image_format> formats =
+ compute::image3d::get_supported_formats(context);
+}
+
+// check type_name() for image3d
+BOOST_AUTO_TEST_CASE(image3d_type_name)
+{
+ BOOST_CHECK(
+ std::strcmp(
+ boost::compute::type_name<boost::compute::image3d>(), "image3d_t"
+ ) == 0
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_image_sampler.cpp b/src/boost/libs/compute/test/test_image_sampler.cpp
new file mode 100644
index 00000000..14b01381
--- /dev/null
+++ b/src/boost/libs/compute/test/test_image_sampler.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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 TestImageSampler
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/image/image_sampler.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(get_context)
+{
+ if(!supports_image_samplers(device)){
+ std::cerr << "skipping get_context test" << std::endl;
+ return;
+ }
+
+ compute::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST);
+ BOOST_CHECK(sampler.get_context() == context);
+}
+
+BOOST_AUTO_TEST_CASE(get_info)
+{
+ if(!supports_image_samplers(device)){
+ std::cerr << "skipping get_info test" << std::endl;
+ return;
+ }
+
+ compute::image_sampler sampler(context, true, CL_ADDRESS_NONE, CL_FILTER_NEAREST);
+ BOOST_CHECK_EQUAL(sampler.get_info<bool>(CL_SAMPLER_NORMALIZED_COORDS), true);
+ BOOST_CHECK_EQUAL(
+ sampler.get_info<cl_addressing_mode>(CL_SAMPLER_ADDRESSING_MODE),
+ cl_addressing_mode(CL_ADDRESS_NONE)
+ );
+ BOOST_CHECK_EQUAL(
+ sampler.get_info<cl_filter_mode>(CL_SAMPLER_FILTER_MODE),
+ cl_filter_mode(CL_FILTER_NEAREST)
+ );
+
+ sampler = compute::image_sampler(context, false, CL_ADDRESS_CLAMP, CL_FILTER_LINEAR);
+ BOOST_CHECK_EQUAL(sampler.get_info<bool>(CL_SAMPLER_NORMALIZED_COORDS), false);
+ BOOST_CHECK_EQUAL(
+ sampler.get_info<cl_addressing_mode>(CL_SAMPLER_ADDRESSING_MODE),
+ cl_addressing_mode(CL_ADDRESS_CLAMP)
+ );
+ BOOST_CHECK_EQUAL(
+ sampler.get_info<cl_filter_mode>(CL_SAMPLER_FILTER_MODE),
+ cl_filter_mode(CL_FILTER_LINEAR)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_includes.cpp b/src/boost/libs/compute/test/test_includes.cpp
new file mode 100644
index 00000000..9ecc42d0
--- /dev/null
+++ b/src/boost/libs/compute/test/test_includes.cpp
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestIncludes
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/includes.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(includes_int)
+{
+ int dataset1[] = {1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 10};
+ bc::vector<bc::int_> set1(dataset1, dataset1 + 12, queue);
+
+ int dataset2[] = {2, 4, 5, 6};
+ bc::vector<bc::int_> set2(dataset2, dataset2 + 4, queue);
+
+ bool includes = bc::includes(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 4, queue);
+ BOOST_VERIFY(includes == true);
+
+ set2[3] = 7;
+ includes = bc::includes(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 4, queue);
+ BOOST_VERIFY(includes == false);
+}
+
+BOOST_AUTO_TEST_CASE(includes_string)
+{
+ char string1[] = "abcccdddeeff";
+ bc::vector<bc::char_> set1(string1, string1 + 12, queue);
+
+ char string2[] = "bccdf";
+ bc::vector<bc::char_> set2(string2, string2 + 5, queue);
+
+ bool includes = bc::includes(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 5, queue);
+ BOOST_VERIFY(includes == true);
+
+ set2[0] = 'g';
+ includes = bc::includes(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 4, queue);
+ BOOST_VERIFY(includes == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_inner_product.cpp b/src/boost/libs/compute/test/test_inner_product.cpp
new file mode 100644
index 00000000..0c2d82c6
--- /dev/null
+++ b/src/boost/libs/compute/test/test_inner_product.cpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// 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 TestInnerProduct
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/inner_product.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(inner_product_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);
+
+ int product = bc::inner_product(input1.begin(),
+ input1.end(),
+ input2.begin(),
+ 0,
+ queue);
+ BOOST_CHECK_EQUAL(product, 300);
+}
+
+BOOST_AUTO_TEST_CASE(inner_product_counting_iterator)
+{
+ BOOST_CHECK_EQUAL(
+ boost::compute::inner_product(
+ boost::compute::make_counting_iterator<int>(0),
+ boost::compute::make_counting_iterator<int>(100),
+ boost::compute::make_counting_iterator<int>(0),
+ 0,
+ queue
+ ),
+ 328350
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_inplace_merge.cpp b/src/boost/libs/compute/test/test_inplace_merge.cpp
new file mode 100644
index 00000000..f328ec15
--- /dev/null
+++ b/src/boost/libs/compute/test/test_inplace_merge.cpp
@@ -0,0 +1,47 @@
+//---------------------------------------------------------------------------//
+// 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 TestInplaceMerge
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/inplace_merge.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(simple_merge_int)
+{
+ int data[] = { 1, 3, 5, 7, 2, 4, 6, 8 };
+ compute::vector<int> vector(data, data + 8, queue);
+
+ // merge each half in-place
+ compute::inplace_merge(
+ vector.begin(),
+ vector.begin() + 4,
+ vector.end(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, vector, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // run again on already sorted list
+ compute::inplace_merge(
+ vector.begin(),
+ vector.begin() + 4,
+ vector.end(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, vector, (1, 2, 3, 4, 5, 6, 7, 8));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_inplace_reduce.cpp b/src/boost/libs/compute/test/test_inplace_reduce.cpp
new file mode 100644
index 00000000..a0706e3a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_inplace_reduce.cpp
@@ -0,0 +1,138 @@
+//---------------------------------------------------------------------------//
+// 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 TestInplaceReduce
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/detail/inplace_reduce.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(sum_int)
+{
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all inplace_reduce tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ int data[] = { 1, 5, 3, 4, 9, 3, 5, 3 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(33));
+
+ vector.assign(data, data + 8);
+ vector.push_back(3);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(36));
+}
+
+BOOST_AUTO_TEST_CASE(multiply_int)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ int data[] = { 1, 5, 3, 4, 9, 3, 5, 3 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::multiplies<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(24300));
+
+ vector.assign(data, data + 8);
+ vector.push_back(3);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::multiplies<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(72900));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_iota)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ // 1 value
+ boost::compute::vector<int> vector(1, context);
+ boost::compute::iota(vector.begin(), vector.end(), int(0), queue);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(0));
+
+ // 1000 values
+ vector.resize(1000);
+ boost::compute::iota(vector.begin(), vector.end(), int(0), queue);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(499500));
+
+ // 2499 values
+ vector.resize(2499);
+ boost::compute::iota(vector.begin(), vector.end(), int(0), queue);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(3121251));
+
+ // 4096 values
+ vector.resize(4096);
+ boost::compute::iota(vector.begin(), vector.end(), int(0), queue);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(8386560));
+
+ // 5000 values
+ vector.resize(5000);
+ boost::compute::iota(vector.begin(), vector.end(), int(0), queue);
+ boost::compute::detail::inplace_reduce(vector.begin(),
+ vector.end(),
+ boost::compute::plus<int>(),
+ queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int(vector[0]), int(12497500));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_insertion_sort.cpp b/src/boost/libs/compute/test/test_insertion_sort.cpp
new file mode 100644
index 00000000..a9088b5a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_insertion_sort.cpp
@@ -0,0 +1,171 @@
+//---------------------------------------------------------------------------//
+// 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 TestInsertionSort
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/detail/insertion_sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(sort_char_vector)
+{
+ using boost::compute::char_;
+
+ char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
+ boost::compute::vector<char_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(char_, 8, vector, ('\0', '$', '0', '7', 'B', 'F', 'a', 'c'));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uchar_vector)
+{
+ using boost::compute::uchar_;
+
+ uchar_ data[] = { 0x12, 0x00, 0xFF, 0xB4, 0x80, 0x32, 0x64, 0xA2 };
+ boost::compute::vector<uchar_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uchar_, 8, vector, (0x00, 0x12, 0x32, 0x64, 0x80, 0xA2, 0xB4, 0xFF));
+}
+
+BOOST_AUTO_TEST_CASE(sort_short_vector)
+{
+ using boost::compute::short_;
+
+ short_ data[] = { -4, 152, -94, 963, 31002, -456, 0, -2113 };
+ boost::compute::vector<short_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(short_, 8, vector, (-2113, -456, -94, -4, 0, 152, 963, 31002));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ushort_vector)
+{
+ using boost::compute::ushort_;
+
+ ushort_ data[] = { 4, 152, 94, 963, 63202, 34560, 0, 2113 };
+ boost::compute::vector<ushort_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ushort_, 8, vector, (0, 4, 94, 152, 963, 2113, 34560, 63202));
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_vector)
+{
+ int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(int, 8, vector, (-5000, -456, -4, 0, 152, 963, 1112, 75321));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uint_vector)
+{
+ using boost::compute::uint_;
+
+ uint_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<uint_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uint_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_long_vector)
+{
+ using boost::compute::long_;
+
+ long_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<long_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(long_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ulong_vector)
+{
+ using boost::compute::ulong_;
+
+ ulong_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<ulong_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ulong_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_vector)
+{
+ float data[] = { -6023.0f, 152.5f, -63.0f, 1234567.0f, 11.2f,
+ -5000.1f, 0.0f, 14.0f, -8.25f, -0.0f };
+ boost::compute::vector<float> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (-6023.0f, -5000.1f, -63.0f, -8.25f, -0.0f, 0.0f, 11.2f, 14.0f, 152.5f, 1234567.0f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_double_vector)
+{
+ if(!device.supports_extension("cl_khr_fp64")){
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ double data[] = { -6023.0, 152.5, -63.0, 1234567.0, 11.2,
+ -5000.1, 0.0, 14.0, -8.25, -0.0 };
+ boost::compute::vector<double> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::serial_insertion_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ double, 10, vector,
+ (-6023.0, -5000.1, -63.0, -8.25, -0.0, 0.0, 11.2, 14.0, 152.5, 1234567.0)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_invoke.cpp b/src/boost/libs/compute/test/test_invoke.cpp
new file mode 100644
index 00000000..87f3f265
--- /dev/null
+++ b/src/boost/libs/compute/test/test_invoke.cpp
@@ -0,0 +1,59 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestInvoke
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/functional/integer.hpp>
+#include <boost/compute/functional/math.hpp>
+#include <boost/compute/utility/invoke.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(invoke_builtin)
+{
+ BOOST_CHECK_EQUAL(compute::invoke(compute::abs<int>(), queue, -3), 3);
+ BOOST_CHECK_CLOSE(compute::invoke(compute::pow<float>(), queue, 2.f, 8.f), 256.f, 1e-4);
+}
+
+BOOST_AUTO_TEST_CASE(invoke_function)
+{
+ BOOST_COMPUTE_FUNCTION(int, plus_two, (int x),
+ {
+ return x + 2;
+ });
+
+ BOOST_CHECK_EQUAL(compute::invoke(plus_two, queue, 2), 4);
+
+ BOOST_COMPUTE_FUNCTION(float, get_max, (float x, float y),
+ {
+ if(x > y)
+ return x;
+ else
+ return y;
+ });
+
+ BOOST_CHECK_EQUAL(compute::invoke(get_max, queue, 10.f, 20.f), 20.f);
+}
+
+BOOST_AUTO_TEST_CASE(invoke_lambda)
+{
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::_2;
+
+ BOOST_CHECK_EQUAL(compute::invoke(_1 / 2, queue, 4), 2);
+ BOOST_CHECK_EQUAL(compute::invoke(_1 * _2 + 1, queue, 3, 3), 10);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_iota.cpp b/src/boost/libs/compute/test/test_iota.cpp
new file mode 100644
index 00000000..345decec
--- /dev/null
+++ b/src/boost/libs/compute/test/test_iota.cpp
@@ -0,0 +1,90 @@
+//---------------------------------------------------------------------------//
+// 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 TestIota
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/permutation_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(iota_int)
+{
+ bc::vector<int> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (0, 1, 2, 3));
+
+ bc::iota(vector.begin(), vector.end(), 10, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (10, 11, 12, 13));
+
+ bc::iota(vector.begin() + 2, vector.end(), -5, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (10, 11, -5, -4));
+
+ bc::iota(vector.begin(), vector.end() - 2, 4, queue);
+ CHECK_RANGE_EQUAL(int, 4, vector, (4, 5, -5, -4));
+}
+
+BOOST_AUTO_TEST_CASE(iota_doctest)
+{
+ boost::compute::vector<int> vec(3, context);
+
+//! [iota]
+boost::compute::iota(vec.begin(), vec.end(), 0, queue);
+//! [iota]
+
+ CHECK_RANGE_EQUAL(int, 3, vec, (0, 1, 2));
+}
+
+BOOST_AUTO_TEST_CASE(iota_permutation_iterator)
+{
+ bc::vector<int> output(5, context);
+ bc::fill(output.begin(), output.end(), 0, queue);
+
+ int map_data[] = { 2, 0, 1, 4, 3 };
+ bc::vector<int> map(map_data, map_data + 5, queue);
+
+ bc::iota(
+ bc::make_permutation_iterator(output.begin(), map.begin()),
+ bc::make_permutation_iterator(output.end(), map.end()),
+ 1,
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (2, 3, 1, 5, 4));
+}
+
+BOOST_AUTO_TEST_CASE(iota_uint)
+{
+ bc::vector<bc::uint_> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), bc::uint_(0), queue);
+ CHECK_RANGE_EQUAL(bc::uint_, 4, vector, (0, 1, 2, 3));
+}
+
+BOOST_AUTO_TEST_CASE(iota_char)
+{
+ bc::vector<bc::char_> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), bc::uint_(0), queue);
+ CHECK_RANGE_EQUAL(bc::char_, 4, vector, (0, 1, 2, 3));
+}
+
+BOOST_AUTO_TEST_CASE(iota_uchar)
+{
+ bc::vector<bc::uchar_> vector(4, context);
+ bc::iota(vector.begin(), vector.end(), bc::uint_(0), queue);
+ CHECK_RANGE_EQUAL(bc::uchar_, 4, vector, (0, 1, 2, 3));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_is_permutation.cpp b/src/boost/libs/compute/test/test_is_permutation.cpp
new file mode 100644
index 00000000..542a5d0b
--- /dev/null
+++ b/src/boost/libs/compute/test/test_is_permutation.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestIsPermutation
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/is_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(is_permutation_int)
+{
+ bc::int_ dataset1[] = {1, 3, 1, 2, 5};
+ bc::vector<bc::int_> vector1(dataset1, dataset1 + 5, queue);
+
+ bc::int_ dataset2[] = {3, 1, 5, 1, 2};
+ bc::vector<bc::int_> vector2(dataset2, dataset2 + 5, queue);
+
+ bool result =
+ bc::is_permutation(vector1.begin(), vector1.begin() + 5,
+ vector2.begin(), vector2.begin() + 5, queue);
+
+ BOOST_VERIFY(result == true);
+
+ vector2.begin().write(bc::int_(1), queue);
+
+ result = bc::is_permutation(vector1.begin(), vector1.begin() + 5,
+ vector2.begin(), vector2.begin() + 5,
+ queue);
+
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(is_permutation_string)
+{
+ bc::char_ dataset1[] = "abade";
+ bc::vector<bc::char_> vector1(dataset1, dataset1 + 5, queue);
+
+ bc::char_ dataset2[] = "aadeb";
+ bc::vector<bc::char_> vector2(dataset2, dataset2 + 5, queue);
+
+ bool result =
+ bc::is_permutation(vector1.begin(), vector1.begin() + 5,
+ vector2.begin(), vector2.begin() + 5, queue);
+
+ BOOST_VERIFY(result == true);
+
+ vector2.begin().write(bc::char_('b'), queue);
+
+ result = bc::is_permutation(vector1.begin(), vector1.begin() + 5,
+ vector2.begin(), vector2.begin() + 5,
+ queue);
+
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_is_sorted.cpp b/src/boost/libs/compute/test/test_is_sorted.cpp
new file mode 100644
index 00000000..55e75ac1
--- /dev/null
+++ b/src/boost/libs/compute/test/test_is_sorted.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestIsSorted
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(is_sorted_int)
+{
+ compute::vector<int> vec(context);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+
+ vec.push_back(1, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+
+ vec.push_back(2, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+
+ vec.push_back(0, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue) == false);
+
+ vec.push_back(-2, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue) == false);
+
+ compute::sort(vec.begin(), vec.end(), queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+}
+
+BOOST_AUTO_TEST_CASE(is_sorted_ones)
+{
+ compute::vector<int> vec(2048, context);
+ compute::fill(vec.begin(), vec.end(), 1, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+}
+
+BOOST_AUTO_TEST_CASE(is_sorted_iota)
+{
+ // create vector with values from 1..1000
+ compute::vector<int> vec(1000, context);
+ compute::iota(vec.begin(), vec.end(), 1, queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+
+ // reverse the range
+ compute::reverse(vec.begin(), vec.end(), queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue) == false);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), compute::greater<int>(), queue));
+
+ // reverse it back
+ compute::reverse(vec.begin(), vec.end(), queue);
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), queue));
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), compute::greater<int>(), queue) == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_kernel.cpp b/src/boost/libs/compute/test/test_kernel.cpp
new file mode 100644
index 00000000..2ab13b8a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_kernel.cpp
@@ -0,0 +1,335 @@
+//---------------------------------------------------------------------------//
+// 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 TestKernel
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/buffer.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/types.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include "context_setup.hpp"
+#include "check_macros.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(name)
+{
+ compute::kernel foo = compute::kernel::create_with_source(
+ "__kernel void foo(int x) { }", "foo", context
+ );
+ BOOST_CHECK_EQUAL(foo.name(), "foo");
+
+ compute::kernel bar = compute::kernel::create_with_source(
+ "__kernel void bar(float x) { }", "bar", context
+ );
+ BOOST_CHECK_EQUAL(bar.name(), "bar");
+}
+
+BOOST_AUTO_TEST_CASE(arity)
+{
+ compute::kernel foo = compute::kernel::create_with_source(
+ "__kernel void foo(int x) { }", "foo", context
+ );
+ BOOST_CHECK_EQUAL(foo.arity(), size_t(1));
+
+ compute::kernel bar = compute::kernel::create_with_source(
+ "__kernel void bar(float x, float y) { }", "bar", context
+ );
+ BOOST_CHECK_EQUAL(bar.arity(), size_t(2));
+
+ compute::kernel baz = compute::kernel::create_with_source(
+ "__kernel void baz(char x, char y, char z) { }", "baz", context
+ );
+ BOOST_CHECK_EQUAL(baz.arity(), size_t(3));
+}
+
+BOOST_AUTO_TEST_CASE(set_buffer_arg)
+{
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void foo(__global int *x, __global int *y)
+ {
+ x[get_global_id(0)] = -y[get_global_id(0)];
+ }
+ );
+
+ compute::kernel foo =
+ compute::kernel::create_with_source(source, "foo", context);
+
+ compute::buffer x(context, 16);
+ compute::buffer y(context, 16);
+
+ foo.set_arg(0, x);
+ foo.set_arg(1, y.get());
+}
+
+BOOST_AUTO_TEST_CASE(get_work_group_info)
+{
+ const char source[] =
+ "__kernel void sum(__global const float *input,\n"
+ " __global float *output)\n"
+ "{\n"
+ " __local float scratch[16];\n"
+ " const uint gid = get_global_id(0);\n"
+ " const uint lid = get_local_id(0);\n"
+ " if(lid < 16)\n"
+ " scratch[lid] = input[gid];\n"
+ "}\n";
+
+ compute::program program =
+ compute::program::create_with_source(source, context);
+
+ program.build();
+
+ compute::kernel kernel = program.create_kernel("sum");
+
+ using compute::ulong_;
+
+ // get local memory size
+ kernel.get_work_group_info<ulong_>(device, CL_KERNEL_LOCAL_MEM_SIZE);
+
+ // check work group size
+ size_t work_group_size =
+ kernel.get_work_group_info<size_t>(device, CL_KERNEL_WORK_GROUP_SIZE);
+ BOOST_CHECK(work_group_size >= 1);
+}
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+BOOST_AUTO_TEST_CASE(kernel_set_args)
+{
+ compute::kernel k = compute::kernel::create_with_source(
+ "__kernel void test(int x, float y, char z) { }", "test", context
+ );
+
+ k.set_args(4, 2.4f, 'a');
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+// Originally failed to compile on macOS (several types are resolved differently)
+BOOST_AUTO_TEST_CASE(kernel_set_args_mac)
+{
+ compute::kernel k = compute::kernel::create_with_source(
+ "__kernel void test(unsigned int a, unsigned long b) { }", "test", context
+ );
+
+ compute::uint_ a;
+ compute::ulong_ b;
+
+ k.set_arg(0, a);
+ k.set_arg(1, b);
+}
+
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+BOOST_AUTO_TEST_CASE(get_arg_info)
+{
+ REQUIRES_OPENCL_VERSION(1, 2);
+
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void sum_kernel(__global const int *input,
+ const uint size,
+ __global int *result)
+ {
+ int sum = 0;
+ for(uint i = 0; i < size; i++){
+ sum += input[i];
+ }
+ *result = sum;
+ }
+ );
+
+ compute::program program =
+ compute::program::create_with_source(source, context);
+
+ program.build("-cl-kernel-arg-info");
+
+ compute::kernel kernel = program.create_kernel("sum_kernel");
+
+ BOOST_CHECK_EQUAL(kernel.get_info<CL_KERNEL_NUM_ARGS>(), compute::uint_(3));
+
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(0, CL_KERNEL_ARG_TYPE_NAME), "int*");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(0, CL_KERNEL_ARG_NAME), "input");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(1, CL_KERNEL_ARG_TYPE_NAME), "uint");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(1, CL_KERNEL_ARG_NAME), "size");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(2, CL_KERNEL_ARG_TYPE_NAME), "int*");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<std::string>(2, CL_KERNEL_ARG_NAME), "result");
+
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(0), "int*");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(0), "input");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(1), "uint");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(1), "size");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_TYPE_NAME>(2), "int*");
+ BOOST_CHECK_EQUAL(kernel.get_arg_info<CL_KERNEL_ARG_NAME>(2), "result");
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+#ifndef CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR
+ #define CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE
+#endif
+#ifndef CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR
+ #define CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE
+#endif
+BOOST_AUTO_TEST_CASE(get_sub_group_info_ext)
+{
+ compute::kernel k = compute::kernel::create_with_source(
+ "__kernel void test(float x) { }", "test", context
+ );
+
+ // get_sub_group_info(const device&, cl_kernel_sub_group_info, const std::vector<size_t>)
+ std::vector<size_t> local_work_size(2, size_t(64));
+ boost::optional<size_t> count = k.get_sub_group_info<size_t>(
+ device,
+ CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR,
+ local_work_size
+ );
+
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_1
+ if(device.check_version(2, 1))
+ {
+ BOOST_CHECK(count);
+ }
+ else
+ #endif // BOOST_COMPUTE_CL_VERSION_2_1
+ if(device.check_version(2, 0) && device.supports_extension("cl_khr_subgroups"))
+ {
+ // for device with cl_khr_subgroups it should return some value
+ BOOST_CHECK(count);
+ }
+ else
+ {
+ // for device without cl_khr_subgroups ext it should return null optional
+ BOOST_CHECK(count == boost::none);
+ }
+
+ // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t, const void *)
+ count = k.get_sub_group_info<size_t>(
+ device,
+ CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE_KHR,
+ 2 * sizeof(size_t),
+ &local_work_size[0]
+ );
+
+ #ifdef BOOST_COMPUTE_CL_VERSION_2_1
+ if(device.check_version(2, 1))
+ {
+ BOOST_CHECK(count);
+ }
+ else
+ #endif // BOOST_COMPUTE_CL_VERSION_2_1
+ if(device.check_version(2, 0) && device.supports_extension("cl_khr_subgroups"))
+ {
+ // for device with cl_khr_subgroups it should return some value
+ BOOST_CHECK(count);
+ }
+ else
+ {
+ // for device without cl_khr_subgroups ext it should return null optional
+ BOOST_CHECK(count == boost::none);
+ }
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(get_sub_group_info_core)
+{
+ compute::kernel k = compute::kernel::create_with_source(
+ "__kernel void test(float x) { }", "test", context
+ );
+
+ // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t)
+ boost::optional<std::vector<size_t>> local_size =
+ k.get_sub_group_info<std::vector<size_t> >(
+ device,
+ CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT,
+ size_t(1)
+ );
+
+ if(device.check_version(2, 1))
+ {
+ // for 2.1 devices it should return some value
+ BOOST_CHECK(local_size);
+ BOOST_CHECK(local_size.value().size() == 3);
+ }
+ else
+ {
+ // for 1.x and 2.0 devices it should return null optional,
+ // because CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT is not
+ // supported by cl_khr_subgroups (2.0 ext)
+ BOOST_CHECK(local_size == boost::none);
+ }
+
+ // get_sub_group_info(const device&, cl_kernel_sub_group_info, const size_t)
+ boost::optional<size_t> local_size_simple =
+ k.get_sub_group_info<size_t>(
+ device,
+ CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT,
+ size_t(1)
+ );
+
+ if(device.check_version(2, 1))
+ {
+ // for 2.1 devices it should return some value
+ BOOST_CHECK(local_size_simple);
+ }
+ else
+ {
+ // for 1.x and 2.0 devices it should return null optional,
+ // because CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT is not
+ // supported by cl_khr_subgroups (2.0 ext)
+ BOOST_CHECK(local_size_simple == boost::none);
+ }
+
+ // get_sub_group_info(const device&, cl_kernel_sub_group_info)
+ boost::optional<size_t> max =
+ k.get_sub_group_info<size_t>(
+ device,
+ CL_KERNEL_MAX_NUM_SUB_GROUPS
+ );
+
+ if(device.check_version(2, 1))
+ {
+ // for 2.1 devices it should return some value
+ BOOST_CHECK(max);
+ }
+ else
+ {
+ // for 1.x and 2.0 devices it should return null optional,
+ // because CL_KERNEL_MAX_NUM_SUB_GROUPS is not
+ // supported by cl_khr_subgroups (2.0 ext)
+ BOOST_CHECK(max == boost::none);
+ }
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_1
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(clone_kernel)
+{
+ REQUIRES_OPENCL_PLATFORM_VERSION(2, 1);
+
+ compute::kernel k1 = compute::kernel::create_with_source(
+ "__kernel void test(__global int * x) { x[get_global_id(0)] = get_global_id(0); }",
+ "test", context
+ );
+
+ compute::buffer x(context, 5 * sizeof(compute::int_));
+ k1.set_arg(0, x);
+
+ // Clone k1 kernel
+ compute::kernel k2 = k1.clone();
+ // After clone k2 0th argument (__global float * x) should be set,
+ // so we should be able to enqueue k2 kernel without problems
+ queue.enqueue_1d_range_kernel(k2, 0, x.size() / sizeof(compute::int_), 0).wait();
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_1
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_lambda.cpp b/src/boost/libs/compute/test/test_lambda.cpp
new file mode 100644
index 00000000..5fa72ac3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_lambda.cpp
@@ -0,0 +1,617 @@
+//---------------------------------------------------------------------------//
+// 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 TestLambda
+#include <boost/test/unit_test.hpp>
+
+#include <boost/tuple/tuple_io.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/for_each.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/bind.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/types/pair.hpp>
+#include <boost/compute/types/tuple.hpp>
+
+#include "check_macros.hpp"
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(squared_plus_one)
+{
+ bc::vector<int> vector(context);
+ vector.push_back(1, queue);
+ vector.push_back(2, queue);
+ vector.push_back(3, queue);
+ vector.push_back(4, queue);
+ vector.push_back(5, queue);
+
+ // multiply each value by itself and add one
+ bc::transform(vector.begin(),
+ vector.end(),
+ vector.begin(),
+ (bc::_1 * bc::_1) + 1,
+ queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (2, 5, 10, 17, 26));
+}
+
+BOOST_AUTO_TEST_CASE(abs_int)
+{
+ bc::vector<int> vector(context);
+ vector.push_back(-1, queue);
+ vector.push_back(-2, queue);
+ vector.push_back(3, queue);
+ vector.push_back(-4, queue);
+ vector.push_back(5, queue);
+
+ bc::transform(vector.begin(),
+ vector.end(),
+ vector.begin(),
+ abs(bc::_1),
+ queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 3, 4, 5));
+}
+
+template<class Result, class Expr>
+void check_lambda_result(const Expr &)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ typename ::boost::compute::lambda::result_of<Expr>::type,
+ Result
+ >::value
+ ));
+}
+
+template<class Result, class Expr, class Arg1>
+void check_lambda_result(const Expr &, const Arg1 &)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ typename ::boost::compute::lambda::result_of<
+ Expr,
+ typename boost::tuple<Arg1>
+ >::type,
+ Result
+ >::value
+ ));
+}
+
+template<class Result, class Expr, class Arg1, class Arg2>
+void check_lambda_result(const Expr &, const Arg1 &, const Arg2 &)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ typename ::boost::compute::lambda::result_of<
+ Expr,
+ typename boost::tuple<Arg1, Arg2>
+ >::type,
+ Result
+ >::value
+ ));
+}
+
+template<class Result, class Expr, class Arg1, class Arg2, class Arg3>
+void check_lambda_result(const Expr &, const Arg1 &, const Arg2 &, const Arg3 &)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ typename ::boost::compute::lambda::result_of<
+ Expr,
+ typename boost::tuple<Arg1, Arg2, Arg3>
+ >::type,
+ Result
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(result_of)
+{
+ using ::boost::compute::lambda::_1;
+ using ::boost::compute::lambda::_2;
+ using ::boost::compute::lambda::_3;
+
+ namespace proto = ::boost::proto;
+
+ using boost::compute::int_;
+
+ check_lambda_result<int_>(proto::lit(1));
+ check_lambda_result<int_>(proto::lit(1) + 2);
+ check_lambda_result<float>(proto::lit(1.2f));
+ check_lambda_result<float>(proto::lit(1) + 1.2f);
+ check_lambda_result<float>(proto::lit(1) / 2 + 1.2f);
+
+ using boost::compute::float4_;
+ using boost::compute::int4_;
+
+ check_lambda_result<int_>(_1, int_(1));
+ check_lambda_result<float>(_1, float(1.2f));
+ check_lambda_result<float4_>(_1, float4_(1, 2, 3, 4));
+ check_lambda_result<float4_>(2.0f * _1, float4_(1, 2, 3, 4));
+ check_lambda_result<float4_>(_1 * 2.0f, float4_(1, 2, 3, 4));
+
+ check_lambda_result<float>(dot(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
+ check_lambda_result<float>(dot(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
+ check_lambda_result<float>(distance(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
+ check_lambda_result<float>(distance(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
+
+ check_lambda_result<float>(length(_1), float4_(3, 2, 1, 0));
+
+ check_lambda_result<float4_>(cross(_1, _2), float4_(0, 1, 2, 3), float4_(3, 2, 1, 0));
+ check_lambda_result<float4_>(cross(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
+
+ check_lambda_result<float4_>(max(_1, _2), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3));
+ check_lambda_result<float4_>(max(_1, float(1.0f)), float4_(0, 1, 2, 3));
+ check_lambda_result<int4_>(max(_1, int4_(3, 2, 1, 0)), int4_(0, 1, 2, 3));
+ check_lambda_result<int4_>(max(_1, int_(1)), int4_(0, 1, 2, 3));
+ check_lambda_result<float4_>(min(_1, float4_(3, 2, 1, 0)), float4_(0, 1, 2, 3));
+
+ check_lambda_result<float4_>(step(_1, _2), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3));
+ check_lambda_result<int4_>(step(_1, _2), float(3.0f), int4_(0, 1, 2, 3));
+
+ check_lambda_result<float4_>(
+ smoothstep(_1, _2, _3),
+ float4_(3, 2, 1, 0), float4_(3, 2, 1, 0), float4_(0, 1, 2, 3)
+ );
+ check_lambda_result<int4_>(
+ smoothstep(_1, _2, _3),
+ float(2.0f), float(3.0f), int4_(0, 1, 2, 3)
+ );
+
+ check_lambda_result<int4_>(bc::lambda::isinf(_1), float4_(0, 1, 2, 3));
+
+ check_lambda_result<int>(_1 + 2, int(2));
+ check_lambda_result<float>(_1 + 2, float(2.2f));
+
+ check_lambda_result<int>(_1 + _2, int(1), int(2));
+ check_lambda_result<float>(_1 + _2, int(1), float(2.2f));
+
+ check_lambda_result<int>(_1 + _1, int(1));
+ check_lambda_result<float>(_1 * _1, float(1));
+
+ using boost::compute::lambda::get;
+
+ check_lambda_result<float>(get<0>(_1), float4_(1, 2, 3, 4));
+ check_lambda_result<bool>(get<0>(_1) < 1.f, float4_(1, 2, 3, 4));
+ check_lambda_result<bool>(_1 < 1.f, float(2));
+
+ using boost::compute::lambda::make_pair;
+
+ check_lambda_result<int>(get<0>(make_pair(_1, _2)), int(1), float(1.2f));
+ check_lambda_result<float>(get<1>(make_pair(_1, _2)), int(1), float(1.2f));
+ check_lambda_result<std::pair<int, float> >(make_pair(_1, _2), int(1), float(1.2f));
+
+ using boost::compute::lambda::make_tuple;
+
+ check_lambda_result<boost::tuple<int> >(make_tuple(_1), int(1));
+ check_lambda_result<boost::tuple<int, float> >(make_tuple(_1, _2), int(1), float(1.2f));
+ check_lambda_result<boost::tuple<int, int> >(make_tuple(_1, _1), int(1));
+ check_lambda_result<boost::tuple<int, float> >(make_tuple(_1, _2), int(1), float(1.4f));
+ check_lambda_result<boost::tuple<char, int, float> >(
+ make_tuple(_1, _2, _3), char('a'), int(2), float(3.4f)
+ );
+ check_lambda_result<boost::tuple<int, int, int> >(
+ make_tuple(_1, _1, _1), int(1), float(1.4f)
+ );
+ check_lambda_result<boost::tuple<int, float, int, float, int> >(
+ make_tuple(_1, _2, _1, _2, _1), int(1), float(1.4f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(make_function_from_lamdba)
+{
+ using boost::compute::lambda::_1;
+
+ int data[] = { 2, 4, 6, 8, 10 };
+ compute::vector<int> vector(data, data + 5, queue);
+
+ compute::function<int(int)> f = _1 * 2 + 3;
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(), f, queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, vector, (7, 11, 15, 19, 23));
+}
+
+BOOST_AUTO_TEST_CASE(make_function_from_binary_lamdba)
+{
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::_2;
+ using boost::compute::lambda::abs;
+
+ int data1[] = { 2, 4, 6, 8, 10 };
+ int data2[] = { 10, 8, 6, 4, 2 };
+ compute::vector<int> vec1(data1, data1 + 5, queue);
+ compute::vector<int> vec2(data2, data2 + 5, queue);
+ compute::vector<int> result(5, context);
+
+ compute::function<int(int, int)> f = abs(_1 - _2);
+
+ compute::transform(
+ vec1.begin(), vec1.end(), vec2.begin(), result.begin(), f, queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, result, (8, 4, 0, 4, 8));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_binary_function_with_pointer_modf)
+{
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::_2;
+ using boost::compute::lambda::abs;
+
+ bc::float_ data1[] = { 2.2f, 4.2f, 6.3f, 8.3f, 10.2f };
+ compute::vector<bc::float_> vec1(data1, data1 + 5, queue);
+ compute::vector<bc::float_> vec2(size_t(5), context);
+ compute::vector<bc::float_> result(5, context);
+
+ compute::transform(
+ bc::make_transform_iterator(vec1.begin(), _1 + 0.01f),
+ bc::make_transform_iterator(vec1.end(), _1 + 0.01f),
+ vec2.begin(),
+ result.begin(),
+ bc::lambda::modf(_1, _2),
+ queue
+ );
+ CHECK_RANGE_CLOSE(bc::float_, 5, result, (0.21f, 0.21f, 0.31f, 0.31f, 0.21f), 0.01f);
+ CHECK_RANGE_CLOSE(bc::float_, 5, vec2, (2, 4, 6, 8, 10), 0.01f);
+}
+
+BOOST_AUTO_TEST_CASE(lambda_tenary_function_with_pointer_remquo)
+{
+ if(!has_remquo_func(device))
+ {
+ return;
+ }
+
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::_2;
+ using boost::compute::lambda::get;
+
+ bc::float_ data1[] = { 2.2f, 4.2f, 6.3f, 8.3f, 10.2f };
+ bc::float_ data2[] = { 4.4f, 4.2f, 6.3f, 16.6f, 10.2f };
+ compute::vector<bc::float_> vec1(data1, data1 + 5, queue);
+ compute::vector<bc::float_> vec2(data2, data2 + 5, queue);
+ compute::vector<bc::int_> vec3(size_t(5), context);
+ compute::vector<bc::float_> result(5, context);
+
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(vec1.begin(), vec2.begin(), vec3.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(vec1.end(), vec2.end(), vec3.end())
+ ),
+ result.begin(),
+ bc::lambda::remquo(get<0>(_1), get<1>(_1), get<2>(_1)),
+ queue
+ );
+ CHECK_RANGE_CLOSE(bc::float_, 5, result, (2.2f, 0.0f, 0.0f, 8.3f, 0.0f), 0.01f);
+ CHECK_RANGE_EQUAL(bc::int_, 5, vec3, (0, 1, 1, 0, 1));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_get_vector)
+{
+ using boost::compute::_1;
+ using boost::compute::int2_;
+ using boost::compute::lambda::get;
+
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int2_> vector(4, context);
+
+ compute::copy(
+ reinterpret_cast<int2_ *>(data),
+ reinterpret_cast<int2_ *>(data) + 4,
+ vector.begin(),
+ queue
+ );
+
+ // extract first component of each vector
+ compute::vector<int> first_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ first_component.begin(),
+ get<0>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
+
+ // extract second component of each vector
+ compute::vector<int> second_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ first_component.begin(),
+ get<1>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_component, (2, 4, 6, 8));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_get_pair)
+{
+ using boost::compute::_1;
+ using boost::compute::lambda::get;
+
+ compute::vector<std::pair<int, float> > vector(context);
+ vector.push_back(std::make_pair(1, 1.2f), queue);
+ vector.push_back(std::make_pair(3, 3.4f), queue);
+ vector.push_back(std::make_pair(5, 5.6f), queue);
+ vector.push_back(std::make_pair(7, 7.8f), queue);
+
+ // extract first compoenent of each pair
+ compute::vector<int> first_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ first_component.begin(),
+ get<0>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
+
+ // extract second compoenent of each pair
+ compute::vector<float> second_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ second_component.begin(),
+ get<1>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 4, second_component, (1.2f, 3.4f, 5.6f, 7.8f));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_get_tuple)
+{
+ using boost::compute::_1;
+ using boost::compute::lambda::get;
+
+ compute::vector<boost::tuple<int, char, float> > vector(context);
+
+ vector.push_back(boost::make_tuple(1, 'a', 1.2f), queue);
+ vector.push_back(boost::make_tuple(3, 'b', 3.4f), queue);
+ vector.push_back(boost::make_tuple(5, 'c', 5.6f), queue);
+ vector.push_back(boost::make_tuple(7, 'd', 7.8f), queue);
+
+ // extract first component of each tuple
+ compute::vector<int> first_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ first_component.begin(),
+ get<0>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_component, (1, 3, 5, 7));
+
+ // extract second component of each tuple
+ compute::vector<char> second_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ second_component.begin(),
+ get<1>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(char, 4, second_component, ('a', 'b', 'c', 'd'));
+
+ // extract third component of each tuple
+ compute::vector<float> third_component(4, context);
+ compute::transform(
+ vector.begin(),
+ vector.end(),
+ third_component.begin(),
+ get<2>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 4, third_component, (1.2f, 3.4f, 5.6f, 7.8f));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_get_zip_iterator)
+{
+ using boost::compute::_1;
+ using boost::compute::lambda::get;
+
+ float data[] = { 1.2f, 2.3f, 3.4f, 4.5f, 5.6f, 6.7f, 7.8f, 9.0f };
+ compute::vector<float> input(8, context);
+ compute::copy(data, data + 8, input.begin(), queue);
+
+ compute::vector<float> output(8, context);
+
+ compute::for_each(
+ compute::make_zip_iterator(
+ boost::make_tuple(input.begin(), output.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input.end(), output.end())
+ ),
+ get<1>(_1) = get<0>(_1),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 8, output,
+ (1.2f, 2.3f, 3.4f, 4.5f, 5.6f, 6.7f, 7.8f, 9.0f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(lambda_make_pair)
+{
+ using boost::compute::_1;
+ using boost::compute::_2;
+ using boost::compute::lambda::make_pair;
+
+ int int_data[] = { 1, 3, 5, 7 };
+ float float_data[] = { 1.2f, 2.3f, 3.4f, 4.5f };
+
+ compute::vector<int> int_vector(int_data, int_data + 4, queue);
+ compute::vector<float> float_vector(float_data, float_data + 4, queue);
+ compute::vector<std::pair<int, float> > output_vector(4, context);
+
+ compute::transform(
+ int_vector.begin(),
+ int_vector.end(),
+ float_vector.begin(),
+ output_vector.begin(),
+ make_pair(_1 - 1, 0 - _2),
+ queue
+ );
+
+ std::vector<std::pair<int, float> > host_vector(4);
+ compute::copy_n(output_vector.begin(), 4, host_vector.begin(), queue);
+ BOOST_CHECK(host_vector[0] == std::make_pair(0, -1.2f));
+ BOOST_CHECK(host_vector[1] == std::make_pair(2, -2.3f));
+ BOOST_CHECK(host_vector[2] == std::make_pair(4, -3.4f));
+ BOOST_CHECK(host_vector[3] == std::make_pair(6, -4.5f));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_make_tuple)
+{
+ using boost::compute::_1;
+ using boost::compute::lambda::get;
+ using boost::compute::lambda::make_tuple;
+
+ std::vector<boost::tuple<int, float> > data;
+ data.push_back(boost::make_tuple(2, 1.2f));
+ data.push_back(boost::make_tuple(4, 2.4f));
+ data.push_back(boost::make_tuple(6, 4.6f));
+ data.push_back(boost::make_tuple(8, 6.8f));
+
+ compute::vector<boost::tuple<int, float> > input_vector(4, context);
+ compute::copy(data.begin(), data.end(), input_vector.begin(), queue);
+
+ // reverse the elements in the tuple
+ compute::vector<boost::tuple<float, int> > output_vector(4, context);
+
+ compute::transform(
+ input_vector.begin(),
+ input_vector.end(),
+ output_vector.begin(),
+ make_tuple(get<1>(_1), get<0>(_1)),
+ queue
+ );
+
+ std::vector<boost::tuple<float, int> > host_vector(4);
+ compute::copy_n(output_vector.begin(), 4, host_vector.begin(), queue);
+ BOOST_CHECK_EQUAL(host_vector[0], boost::make_tuple(1.2f, 2));
+ BOOST_CHECK_EQUAL(host_vector[1], boost::make_tuple(2.4f, 4));
+ BOOST_CHECK_EQUAL(host_vector[2], boost::make_tuple(4.6f, 6));
+ BOOST_CHECK_EQUAL(host_vector[3], boost::make_tuple(6.8f, 8));
+
+ // duplicate each element in the tuple
+ compute::vector<boost::tuple<int, int, float, float> > doubled_vector(4, context);
+ compute::transform(
+ input_vector.begin(),
+ input_vector.end(),
+ doubled_vector.begin(),
+ make_tuple(get<0>(_1), get<0>(_1), get<1>(_1), get<1>(_1)),
+ queue
+ );
+
+ std::vector<boost::tuple<int, int, float, float> > doubled_host_vector(4);
+ compute::copy_n(doubled_vector.begin(), 4, doubled_host_vector.begin(), queue);
+ BOOST_CHECK_EQUAL(doubled_host_vector[0], boost::make_tuple(2, 2, 1.2f, 1.2f));
+ BOOST_CHECK_EQUAL(doubled_host_vector[1], boost::make_tuple(4, 4, 2.4f, 2.4f));
+ BOOST_CHECK_EQUAL(doubled_host_vector[2], boost::make_tuple(6, 6, 4.6f, 4.6f));
+ BOOST_CHECK_EQUAL(doubled_host_vector[3], boost::make_tuple(8, 8, 6.8f, 6.8f));
+}
+
+BOOST_AUTO_TEST_CASE(bind_lambda_function)
+{
+ using compute::placeholders::_1;
+ namespace lambda = compute::lambda;
+
+ int data[] = { 1, 2, 3, 4 };
+ compute::vector<int> vector(data, data + 4, queue);
+
+ compute::transform(
+ vector.begin(), vector.end(), vector.begin(),
+ compute::bind(lambda::_1 * lambda::_2, _1, 2),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, vector, (2, 4, 6, 8));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_function_with_uint_args)
+{
+ compute::uint_ host_data[] = { 1, 3, 5, 7, 9 };
+ compute::vector<compute::uint_> device_vector(host_data, host_data + 5, queue);
+
+ using boost::compute::lambda::clamp;
+ using compute::lambda::_1;
+
+ compute::transform(
+ device_vector.begin(), device_vector.end(),
+ device_vector.begin(),
+ clamp(_1, compute::uint_(4), compute::uint_(6)),
+ queue
+ );
+ CHECK_RANGE_EQUAL(compute::uint_, 5, device_vector, (4, 4, 5, 6, 6));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_function_with_short_args)
+{
+ compute::short_ host_data[] = { 1, 3, 5, 7, 9 };
+ compute::vector<compute::short_> device_vector(host_data, host_data + 5, queue);
+
+ using boost::compute::lambda::clamp;
+ using compute::lambda::_1;
+
+ compute::transform(
+ device_vector.begin(), device_vector.end(),
+ device_vector.begin(),
+ clamp(_1, compute::short_(4), compute::short_(6)),
+ queue
+ );
+ CHECK_RANGE_EQUAL(compute::short_, 5, device_vector, (4, 4, 5, 6, 6));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_function_with_uchar_args)
+{
+ compute::uchar_ host_data[] = { 1, 3, 5, 7, 9 };
+ compute::vector<compute::uchar_> device_vector(host_data, host_data + 5, queue);
+
+ using boost::compute::lambda::clamp;
+ using compute::lambda::_1;
+
+ compute::transform(
+ device_vector.begin(), device_vector.end(),
+ device_vector.begin(),
+ clamp(_1, compute::uchar_(4), compute::uchar_(6)),
+ queue
+ );
+ CHECK_RANGE_EQUAL(compute::uchar_, 5, device_vector, (4, 4, 5, 6, 6));
+}
+
+BOOST_AUTO_TEST_CASE(lambda_function_with_char_args)
+{
+ compute::char_ host_data[] = { 1, 3, 5, 7, 9 };
+ compute::vector<compute::char_> device_vector(host_data, host_data + 5, queue);
+
+ using boost::compute::lambda::clamp;
+ using compute::lambda::_1;
+
+ compute::transform(
+ device_vector.begin(), device_vector.end(),
+ device_vector.begin(),
+ clamp(_1, compute::char_(4), compute::char_(6)),
+ queue
+ );
+ CHECK_RANGE_EQUAL(compute::char_, 5, device_vector, (4, 4, 5, 6, 6));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_lexicographical_compare.cpp b/src/boost/libs/compute/test/test_lexicographical_compare.cpp
new file mode 100644
index 00000000..45daa92a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_lexicographical_compare.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Mageswaran.D <mageswaran1989@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 TestLexicographicalCompare
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/container/string.hpp>
+#include <boost/compute/container/basic_string.hpp>
+#include <boost/compute/algorithm/lexicographical_compare.hpp>
+
+#include "context_setup.hpp"
+#include "check_macros.hpp"
+
+BOOST_AUTO_TEST_CASE(lexicographical_compare_string)
+{
+ boost::compute::string a = "abcdefghijk";
+ boost::compute::string b = "abcdefghijk";
+ boost::compute::string c = "abcdefghija";
+ boost::compute::string d = "zabcdefghij";
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(a.begin(),
+ a.end(),
+ b.begin(),
+ b.end()) == false);
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(c.begin(),
+ c.end(),
+ a.begin(),
+ a.end()) == true);
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(c.begin(),
+ c.end(),
+ d.begin(),
+ d.end()) == true);
+}
+
+BOOST_AUTO_TEST_CASE(lexicographical_compare_number)
+{
+ int data1[] = { 1, 2, 3, 4, 5, 6 };
+ int data2[] = { 9, 2, 3, 4, 5, 6 };
+ int data3[] = { 1, 2, 3, 4, 5 };
+ int data4[] = { 9, 2, 3, 4, 5, 100 };
+
+ boost::compute::vector<int> vector1(data1, data1 + 6, queue);
+ boost::compute::vector<int> vector2(data2, data2 + 6, queue);
+ boost::compute::vector<int> vector3(data3, data3 + 5, queue);
+ boost::compute::vector<int> vector4(data4, data4 + 6, queue);
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(vector1.begin(),
+ vector1.end(),
+ vector2.begin(),
+ vector2.end(),
+ queue) == true);
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(vector1.begin(),
+ vector1.end(),
+ vector3.begin(),
+ vector3.end(),
+ queue) == false);
+
+ BOOST_CHECK(boost::compute::lexicographical_compare(vector3.begin(),
+ vector3.end(),
+ vector4.begin(),
+ vector4.end(),
+ queue) == true);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_linear_congruential_engine.cpp b/src/boost/libs/compute/test/test_linear_congruential_engine.cpp
new file mode 100644
index 00000000..25438c7f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_linear_congruential_engine.cpp
@@ -0,0 +1,120 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestLinearCongruentialEngine
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/random/linear_congruential_engine.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(generate_uint)
+{
+ using boost::compute::uint_;
+
+ boost::compute::linear_congruential_engine<uint_> rng(queue);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(1099087573),
+ uint_(2291457337),
+ uint_(4026424941),
+ uint_(420705969),
+ uint_(2250972997),
+ uint_(153107049),
+ uint_(3581708125),
+ uint_(1733142113),
+ uint_(3008982197),
+ uint_(3237988505))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discard_uint)
+{
+ using boost::compute::uint_;
+
+ boost::compute::linear_congruential_engine<uint_> rng(queue);
+
+ boost::compute::vector<uint_> vector(5, context);
+
+ rng.discard(5, queue);
+ rng.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 5, vector,
+ (uint_(153107049),
+ uint_(3581708125),
+ uint_(1733142113),
+ uint_(3008982197),
+ uint_(3237988505))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_ctor)
+{
+ using boost::compute::uint_;
+
+ boost::compute::linear_congruential_engine<uint_> rng(queue);
+ boost::compute::linear_congruential_engine<uint_> rng_copy(rng);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng_copy.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(1099087573),
+ uint_(2291457337),
+ uint_(4026424941),
+ uint_(420705969),
+ uint_(2250972997),
+ uint_(153107049),
+ uint_(3581708125),
+ uint_(1733142113),
+ uint_(3008982197),
+ uint_(3237988505))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(assign_op)
+{
+ using boost::compute::uint_;
+
+ boost::compute::linear_congruential_engine<uint_> rng(queue);
+ boost::compute::linear_congruential_engine<uint_> rng_copy(queue);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng_copy.discard(5, queue);
+ rng_copy = rng;
+ rng_copy.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(1099087573),
+ uint_(2291457337),
+ uint_(4026424941),
+ uint_(420705969),
+ uint_(2250972997),
+ uint_(153107049),
+ uint_(3581708125),
+ uint_(1733142113),
+ uint_(3008982197),
+ uint_(3237988505))
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_literal_conversion.cpp b/src/boost/libs/compute/test/test_literal_conversion.cpp
new file mode 100644
index 00000000..09898d44
--- /dev/null
+++ b/src/boost/libs/compute/test/test_literal_conversion.cpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jason Rhinelander <jason@imaginary.ca>
+//
+// 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 TestLiteralConversion
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/compute/detail/literal.hpp>
+
+BOOST_AUTO_TEST_CASE(literal_conversion_float)
+{
+ std::vector<float> values, roundtrip;
+ values.push_back(1.2345679f);
+ values.push_back(1.2345680f);
+ values.push_back(1.2345681f);
+ for (size_t i = 0; i < values.size(); i++) {
+ std::string literal = boost::compute::detail::make_literal(values[i]);
+ // Check that we got something in the literal, and that at least the first
+ // 6 characters (5 digits) look good
+ BOOST_CHECK_EQUAL(literal.substr(0, 6), "1.2345");
+
+ // libc++ stream extraction fails on a value such as "1.2f" rather than extracting 1.2
+ // and leaving the f; so check the "f", then slice it off for the extraction below:
+ BOOST_CHECK_EQUAL(literal.substr(literal.length()-1), "f");
+
+ std::istringstream iss(literal.substr(0, literal.length()-1));
+ float x;
+ iss >> x;
+ roundtrip.push_back(x);
+ }
+ BOOST_CHECK_EQUAL(values[0], roundtrip[0]);
+ BOOST_CHECK_EQUAL(values[1], roundtrip[1]);
+ BOOST_CHECK_EQUAL(values[2], roundtrip[2]);
+}
+
+BOOST_AUTO_TEST_CASE(literal_conversion_double)
+{
+ std::vector<double> values, roundtrip;
+ values.push_back(1.2345678901234567);
+ values.push_back(1.2345678901234569);
+ values.push_back(1.2345678901234571);
+ for (size_t i = 0; i < values.size(); i++) {
+ std::string literal = boost::compute::detail::make_literal(values[i]);
+ // Check that we got something in the literal, and that at least the first
+ // 11 characters (10 digits) look good
+ BOOST_CHECK_EQUAL(literal.substr(0, 11), "1.234567890");
+
+ // Stuff the literal into a stream then extract it, and make sure we get a numerically
+ // identical result. (Since there is no suffix, we don't have to worry about removing the
+ // suffix like we have to above, for float--but we also check to make sure there is no
+ // (unextracted) suffix).
+ std::istringstream iss(literal);
+ double x;
+ std::string suffix;
+ iss >> x >> suffix;
+ BOOST_CHECK_EQUAL(suffix, "");
+ roundtrip.push_back(x);
+ }
+ BOOST_CHECK_EQUAL(values[0], roundtrip[0]);
+ BOOST_CHECK_EQUAL(values[1], roundtrip[1]);
+ BOOST_CHECK_EQUAL(values[2], roundtrip[2]);
+}
diff --git a/src/boost/libs/compute/test/test_local_buffer.cpp b/src/boost/libs/compute/test/test_local_buffer.cpp
new file mode 100644
index 00000000..69e5389a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_local_buffer.cpp
@@ -0,0 +1,80 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestLocalBuffer
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/core.hpp>
+#include <boost/compute/memory/local_buffer.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(local_buffer_arg)
+{
+ if(device.get_info<CL_DEVICE_LOCAL_MEM_TYPE>() != CL_LOCAL){
+ std::cerr << "skipping local buffer arg test: "
+ << "device does not support local memory" << std::endl;
+ return;
+ }
+
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void foo(__local float *local_buffer,
+ __global float *global_buffer)
+ {
+ const uint gid = get_global_id(0);
+ const uint lid = get_local_id(0);
+
+ local_buffer[lid] = gid;
+
+ global_buffer[gid] = local_buffer[lid];
+ }
+ );
+
+ // create and build program
+ compute::program program =
+ compute::program::build_with_source(source, context);
+
+ // create kernel
+ compute::kernel kernel = program.create_kernel("foo");
+
+ // setup kernel arguments
+ compute::buffer global_buf(context, 128 * sizeof(float));
+ kernel.set_arg(0, compute::local_buffer<float>(32));
+ kernel.set_arg(1, global_buf);
+
+ // some implementations don't correctly report dynamically-set local buffer sizes
+ if(kernel.get_work_group_info<cl_ulong>(device, CL_KERNEL_LOCAL_MEM_SIZE) == 0){
+ std::cerr << "skipping checks for local memory size, device reports "
+ << "zero after setting dynamically-sized local buffer size"
+ << std::endl;
+ return;
+ }
+
+ // check actual memory size
+ BOOST_CHECK_GE(
+ kernel.get_work_group_info<cl_ulong>(device, CL_KERNEL_LOCAL_MEM_SIZE),
+ 32 * sizeof(float)
+ );
+
+ // increase local buffer size and check new actual local memory size
+ kernel.set_arg(0, compute::local_buffer<float>(64));
+
+ BOOST_CHECK_GE(
+ kernel.get_work_group_info<cl_ulong>(device, CL_KERNEL_LOCAL_MEM_SIZE),
+ 64 * sizeof(float)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_malloc.cpp b/src/boost/libs/compute/test/test_malloc.cpp
new file mode 100644
index 00000000..212200d9
--- /dev/null
+++ b/src/boost/libs/compute/test/test_malloc.cpp
@@ -0,0 +1,40 @@
+//---------------------------------------------------------------------------//
+// 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 TestMalloc
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/experimental/malloc.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(malloc_int)
+{
+ bc::experimental::device_ptr<int> ptr = bc::experimental::malloc<int>(5, context);
+
+ int input_data[] = { 2, 5, 8, 3, 6 };
+ bc::copy(input_data, input_data + 5, ptr, queue);
+
+ int output_data[5];
+ bc::copy(ptr, ptr + 5, output_data, queue);
+
+ BOOST_CHECK_EQUAL(output_data[0], 2);
+ BOOST_CHECK_EQUAL(output_data[1], 5);
+ BOOST_CHECK_EQUAL(output_data[2], 8);
+ BOOST_CHECK_EQUAL(output_data[3], 3);
+ BOOST_CHECK_EQUAL(output_data[4], 6);
+
+ bc::experimental::free(ptr);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_mapped_view.cpp b/src/boost/libs/compute/test/test_mapped_view.cpp
new file mode 100644
index 00000000..c862a75e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_mapped_view.cpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestMappedView
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/container/mapped_view.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(fill)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ for(int i = 0; i < 8; i++){
+ BOOST_CHECK_EQUAL(data[i], i+1);
+ }
+
+ compute::mapped_view<int> view(data, 8, context);
+ compute::fill(view.begin(), view.end(), 4, queue);
+
+ view.map(CL_MAP_READ, queue);
+ for(int i = 0; i < 8; i++){
+ BOOST_CHECK_EQUAL(data[i], 4);
+ }
+ view.unmap(queue);
+}
+
+BOOST_AUTO_TEST_CASE(sort)
+{
+ int data[] = { 5, 2, 3, 1, 8, 7, 4, 9 };
+ compute::mapped_view<int> view(data, 8, context);
+
+ compute::sort(view.begin(), view.end(), queue);
+
+ view.map(CL_MAP_READ, queue);
+ BOOST_CHECK_EQUAL(data[0], 1);
+ BOOST_CHECK_EQUAL(data[7], 9);
+ view.unmap(queue);
+}
+
+BOOST_AUTO_TEST_CASE(mapped_view_reduce_doctest)
+{
+//! [reduce]
+// create data array on the host
+int data[] = { 5, 2, 3, 1, 8, 7, 4, 9 };
+boost::compute::mapped_view<int> view(data, 8, context);
+
+// use reduce() to calculate the sum on the device
+int sum = 0;
+boost::compute::reduce(view.begin(), view.end(), &sum, queue);
+//! [reduce]
+
+ BOOST_CHECK_EQUAL(sum, 39);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_merge.cpp b/src/boost/libs/compute/test/test_merge.cpp
new file mode 100644
index 00000000..df3b12dc
--- /dev/null
+++ b/src/boost/libs/compute/test/test_merge.cpp
@@ -0,0 +1,167 @@
+//---------------------------------------------------------------------------//
+// 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 TestMerge
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/types/pair.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/merge.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/lambda.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(simple_merge_int)
+{
+ int data1[] = { 1, 3, 5, 7 };
+ int data2[] = { 2, 4, 6, 8 };
+
+ boost::compute::vector<int> v1(4, context);
+ boost::compute::vector<int> v2(4, context);
+ boost::compute::vector<int> v3(8, context);
+
+ boost::compute::copy_n(data1, 4, v1.begin(), queue);
+ boost::compute::copy_n(data2, 4, v2.begin(), queue);
+ boost::compute::fill(v3.begin(), v3.end(), 0, queue);
+
+ // merge v1 with v2 into v3
+ boost::compute::merge(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, v3, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // merge v2 with v1 into v3
+ boost::compute::merge(
+ v2.begin(), v2.end(),
+ v1.begin(), v1.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, v3, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // merge v1 with v1 into v3
+ boost::compute::merge(
+ v1.begin(), v1.end(),
+ v1.begin(), v1.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, v3, (1, 1, 3, 3, 5, 5, 7, 7));
+
+ // merge v2 with v2 into v3
+ boost::compute::merge(
+ v2.begin(), v2.end(),
+ v2.begin(), v2.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 8, v3, (2, 2, 4, 4, 6, 6, 8, 8));
+
+ // merge v1 with empty range into v3
+ boost::compute::merge(
+ v1.begin(), v1.end(),
+ v1.begin(), v1.begin(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, v3, (1, 3, 5, 7));
+
+ // merge v2 with empty range into v3
+ boost::compute::merge(
+ v1.begin(), v1.begin(),
+ v2.begin(), v2.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, v3, (2, 4, 6, 8));
+}
+
+BOOST_AUTO_TEST_CASE(merge_pairs)
+{
+ std::vector<std::pair<int, float> > data1;
+ std::vector<std::pair<int, float> > data2;
+
+ data1.push_back(std::make_pair(0, 0.1f));
+ data1.push_back(std::make_pair(2, 2.1f));
+ data1.push_back(std::make_pair(4, 4.1f));
+ data1.push_back(std::make_pair(6, 6.1f));
+ data2.push_back(std::make_pair(1, 1.1f));
+ data2.push_back(std::make_pair(3, 3.1f));
+ data2.push_back(std::make_pair(5, 5.1f));
+ data2.push_back(std::make_pair(7, 7.1f));
+
+ std::vector<std::pair<int, float> > data3(data1.size() + data2.size());
+ std::fill(data3.begin(), data3.end(), std::make_pair(-1, -1.f));
+
+ boost::compute::vector<std::pair<int, float> > v1(data1.size(), context);
+ boost::compute::vector<std::pair<int, float> > v2(data2.size(), context);
+ boost::compute::vector<std::pair<int, float> > v3(data3.size(), context);
+
+ boost::compute::copy(data1.begin(), data1.end(), v1.begin(), queue);
+ boost::compute::copy(data2.begin(), data2.end(), v2.begin(), queue);
+
+ using ::boost::compute::lambda::_1;
+ using ::boost::compute::lambda::_2;
+ using ::boost::compute::lambda::get;
+
+ boost::compute::merge(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin(),
+ get<0>(_1) < get<0>(_2),
+ queue
+ );
+
+ boost::compute::copy(v3.begin(), v3.end(), data3.begin(), queue);
+
+ BOOST_CHECK(v3[0] == std::make_pair(0, 0.1f));
+ BOOST_CHECK(v3[1] == std::make_pair(1, 1.1f));
+ BOOST_CHECK(v3[2] == std::make_pair(2, 2.1f));
+ BOOST_CHECK(v3[3] == std::make_pair(3, 3.1f));
+ BOOST_CHECK(v3[4] == std::make_pair(4, 4.1f));
+ BOOST_CHECK(v3[5] == std::make_pair(5, 5.1f));
+ BOOST_CHECK(v3[6] == std::make_pair(6, 6.1f));
+ BOOST_CHECK(v3[7] == std::make_pair(7, 7.1f));
+}
+
+BOOST_AUTO_TEST_CASE(merge_floats)
+{
+ float data1[] = { 1.1f, 2.2f, 3.3f, 4.4f,
+ 5.5f, 6.6f, 7.7f, 8.8f };
+ float data2[] = { 1.0f, 2.0f, 3.9f, 4.9f,
+ 6.8f, 6.9f, 7.0f, 7.1f };
+
+ boost::compute::vector<float> v1(8, context);
+ boost::compute::vector<float> v2(8, context);
+ boost::compute::vector<float> v3(v1.size() + v2.size(), context);
+
+ boost::compute::copy_n(data1, 8, v1.begin(), queue);
+ boost::compute::copy_n(data2, 8, v2.begin(), queue);
+ boost::compute::fill(v3.begin(), v3.end(), 0.f, queue);
+
+ boost::compute::merge(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 16, v3,
+ (1.0f, 1.1f, 2.0f, 2.2f, 3.3f, 3.9f, 4.4f, 4.9f,
+ 5.5f, 6.6f, 6.8f, 6.9f, 7.0f, 7.1f, 7.7f, 8.8f)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_merge_sort_gpu.cpp b/src/boost/libs/compute/test/test_merge_sort_gpu.cpp
new file mode 100644
index 00000000..5b857aca
--- /dev/null
+++ b/src/boost/libs/compute/test/test_merge_sort_gpu.cpp
@@ -0,0 +1,374 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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 TestMergeSortOnGPU
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/detail/merge_sort_on_gpu.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(sort_small_vector_char)
+{
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all merge_sort_on_gpu tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ using boost::compute::char_;
+ ::boost::compute::greater<char_> greater;
+ ::boost::compute::less<char_> less;
+
+ char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
+ boost::compute::vector<char_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ // <
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), less, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), less, queue)
+ );
+ CHECK_RANGE_EQUAL(char_, 8, vector, ('\0', '$', '0', '7', 'B', 'F', 'a', 'c'));
+
+ // >
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), greater, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), greater, queue)
+ );
+ CHECK_RANGE_EQUAL(char_, 8, vector, ('c', 'a', 'F', 'B', '7', '0', '$', '\0'));
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_int)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::int_;
+ ::boost::compute::greater<int_> greater;
+ ::boost::compute::less<int_> less;
+
+ const int_ size = 748;
+ std::vector<int_> data(size);
+ for(int_ i = 0; i < size; i++){
+ data[i] = i%2 ? i : -i;
+ }
+
+ boost::compute::vector<int_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(!boost::compute::is_sorted(vector.begin(), vector.end(), queue));
+
+ // <
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), less, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), less, queue)
+ );
+
+ // >
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), greater, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), greater, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_ulong)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::ulong_;
+ ::boost::compute::greater<ulong_> greater;
+ ::boost::compute::less<ulong_> less;
+
+ const ulong_ size = 260;
+ std::vector<ulong_> data(size);
+ for(ulong_ i = 0; i < size; i++){
+ data[i] = i%2 ? i : i * i;
+ }
+
+ boost::compute::vector<ulong_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(!boost::compute::is_sorted(vector.begin(), vector.end(), queue));
+
+ // <
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), less, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), less, queue)
+ );
+
+ // >
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), greater, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), greater, queue)
+ );
+}
+
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_float)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::float_;
+ ::boost::compute::greater<float_> greater;
+ ::boost::compute::less<float_> less;
+
+ const int size = 513;
+ std::vector<float_> data(size);
+ for(int i = 0; i < size; i++){
+ data[i] = float_(i%2 ? i : -i);
+ }
+
+ boost::compute::vector<float_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(!boost::compute::is_sorted(vector.begin(), vector.end(), queue));
+
+ // <
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), less, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), less, queue)
+ );
+
+ // >
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), greater, queue
+ );
+ queue.finish();
+
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), greater, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_double)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ if(!device.supports_extension("cl_khr_fp64")){
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ using boost::compute::double_;
+ ::boost::compute::greater<double_> greater;
+ ::boost::compute::less<double_> less;
+
+ const int size = 1023;
+ std::vector<double_> data(size);
+ for(int i = 0; i < size; i++){
+ data[i] = double_(i%2 ? i : -i);
+ }
+
+ boost::compute::vector<double_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(!boost::compute::is_sorted(vector.begin(), vector.end(), queue));
+
+ // <
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), less, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), less, queue)
+ );
+
+ // >
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), greater, queue
+ );
+ queue.finish();
+
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), greater, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_int_custom_comparison_func)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::int_;
+ ::boost::compute::greater<int_> greater;
+ ::boost::compute::less<int_> less;
+
+ const int_ size = 1024;
+ std::vector<int_> data(size);
+ for(int_ i = 0; i < size; i++){
+ data[i] = i%2 ? size - i : i - size;
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, abs_sort, (int_ a, int_ b),
+ {
+ return abs(a) < abs(b);
+ });
+
+ boost::compute::vector<int_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(
+ !boost::compute::is_sorted(vector.begin(), vector.end(), abs_sort, queue)
+ );
+
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), abs_sort, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), abs_sort, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_int2)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::int2_;
+ using boost::compute::int_;
+ ::boost::compute::greater<int2_> greater;
+ ::boost::compute::less<int2_> less;
+
+ const int_ size = 1024;
+ std::vector<int2_> data(size);
+ for(int_ i = 0; i < size; i++){
+ data[i] = i%2 ? int2_(i, i) : int2_(i - size, i - size);
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, abs_sort, (int2_ a, int2_ b),
+ {
+ return abs(a.x + a.y) < abs(b.x + b.y);
+ });
+
+ boost::compute::vector<int2_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(
+ !boost::compute::is_sorted(vector.begin(), vector.end(), abs_sort, queue)
+ );
+
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), abs_sort, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), abs_sort, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_mid_vector_long8)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::long8_;
+ using boost::compute::long_;
+ ::boost::compute::greater<long8_> greater;
+ ::boost::compute::less<long8_> less;
+
+ const long_ size = 256;
+ std::vector<long8_> data(size);
+ for(long_ i = 0; i < size; i++){
+ data[i] = i%2 ? long8_(i) : long8_(i * i);
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, comp, (long8_ a, long8_ b),
+ {
+ return a.s0 < b.s3;
+ });
+
+ boost::compute::vector<long8_> vector(data.begin(), data.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(
+ !boost::compute::is_sorted(vector.begin(), vector.end(), comp, queue)
+ );
+
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), comp, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), comp, queue)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_vector_int2)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::int2_;
+
+ int2_ data[] = {
+ int2_(8, 3), int2_(5, 1),
+ int2_(2, 1), int2_(6, 1),
+ int2_(8, 1), int2_(7, 1),
+ int2_(4, 1), int2_(8, 2)
+ };
+
+ BOOST_COMPUTE_FUNCTION(bool, comp, (int2_ a, int2_ b),
+ {
+ return a.x < b.x;
+ });
+
+ boost::compute::vector<int2_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), 8);
+ BOOST_CHECK(
+ !boost::compute::is_sorted(vector.begin(), vector.end(), comp, queue)
+ );
+
+ //
+ boost::compute::detail::merge_sort_on_gpu(
+ vector.begin(), vector.end(), comp, true /*stable*/, queue
+ );
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(), comp, queue)
+ );
+ CHECK_RANGE_EQUAL(
+ int2_, 8, vector,
+ (
+ int2_(2, 1), int2_(4, 1),
+ int2_(5, 1), int2_(6, 1),
+ int2_(7, 1), int2_(8, 3),
+ int2_(8, 1), int2_(8, 2)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_mersenne_twister_engine.cpp b/src/boost/libs/compute/test/test_mersenne_twister_engine.cpp
new file mode 100644
index 00000000..c286c257
--- /dev/null
+++ b/src/boost/libs/compute/test/test_mersenne_twister_engine.cpp
@@ -0,0 +1,120 @@
+//---------------------------------------------------------------------------//
+// 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 TestMersenneTwisterEngine
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/random/mersenne_twister_engine.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(generate_uint)
+{
+ using boost::compute::uint_;
+
+ boost::compute::mt19937 rng(queue);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(3499211612),
+ uint_(581869302),
+ uint_(3890346734),
+ uint_(3586334585),
+ uint_(545404204),
+ uint_(4161255391),
+ uint_(3922919429),
+ uint_(949333985),
+ uint_(2715962298),
+ uint_(1323567403))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(discard_uint)
+{
+ using boost::compute::uint_;
+
+ boost::compute::mt19937 rng(queue);
+
+ boost::compute::vector<uint_> vector(5, context);
+
+ rng.discard(5, queue);
+ rng.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 5, vector,
+ (uint_(4161255391),
+ uint_(3922919429),
+ uint_(949333985),
+ uint_(2715962298),
+ uint_(1323567403))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy_ctor)
+{
+ using boost::compute::uint_;
+
+ boost::compute::mt19937 rng(queue);
+ boost::compute::mt19937 rng_copy(rng);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng_copy.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(3499211612),
+ uint_(581869302),
+ uint_(3890346734),
+ uint_(3586334585),
+ uint_(545404204),
+ uint_(4161255391),
+ uint_(3922919429),
+ uint_(949333985),
+ uint_(2715962298),
+ uint_(1323567403))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(assign_op)
+{
+ using boost::compute::uint_;
+
+ boost::compute::mt19937 rng(queue);
+ boost::compute::mt19937 rng_copy(queue);
+
+ boost::compute::vector<uint_> vector(10, context);
+
+ rng_copy.discard(5, queue);
+ rng_copy = rng;
+ rng_copy.generate(vector.begin(), vector.end(), queue);
+
+ CHECK_RANGE_EQUAL(
+ uint_, 10, vector,
+ (uint_(3499211612),
+ uint_(581869302),
+ uint_(3890346734),
+ uint_(3586334585),
+ uint_(545404204),
+ uint_(4161255391),
+ uint_(3922919429),
+ uint_(949333985),
+ uint_(2715962298),
+ uint_(1323567403))
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_mismatch.cpp b/src/boost/libs/compute/test/test_mismatch.cpp
new file mode 100644
index 00000000..32d900c6
--- /dev/null
+++ b/src/boost/libs/compute/test/test_mismatch.cpp
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------------//
+// 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 TestMismatch
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/mismatch.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(mismatch_int)
+{
+ int data1[] = { 1, 2, 3, 4, 5, 6 };
+ int data2[] = { 1, 2, 3, 7, 5, 6 };
+
+ boost::compute::vector<int> vector1(data1, data1 + 6, queue);
+ boost::compute::vector<int> vector2(data2, data2 + 6, queue);
+
+ typedef boost::compute::vector<int>::iterator iter;
+
+ std::pair<iter, iter> location =
+ boost::compute::mismatch(vector1.begin(), vector1.end(),
+ vector2.begin(), queue);
+ BOOST_CHECK(location.first == vector1.begin() + 3);
+ BOOST_CHECK_EQUAL(int(*location.first), int(4));
+ BOOST_CHECK(location.second == vector2.begin() + 3);
+ BOOST_CHECK_EQUAL(int(*location.second), int(7));
+}
+
+BOOST_AUTO_TEST_CASE(mismatch_different_range_sizes)
+{
+ boost::compute::vector<int> a(10, context);
+ boost::compute::vector<int> b(20, context);
+
+ boost::compute::fill(a.begin(), a.end(), 3, queue);
+ boost::compute::fill(b.begin(), b.end(), 3, queue);
+
+ typedef boost::compute::vector<int>::iterator iter;
+
+ std::pair<iter, iter> location;
+
+ location = boost::compute::mismatch(
+ a.begin(), a.end(), b.begin(), b.end(), queue
+ );
+ BOOST_CHECK(location.first == a.end());
+ BOOST_CHECK(location.second == b.begin() + 10);
+
+ location = boost::compute::mismatch(
+ b.begin(), b.end(), a.begin(), a.end(), queue
+ );
+ BOOST_CHECK(location.first == b.begin() + 10);
+ BOOST_CHECK(location.second == a.end());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_next_permutation.cpp b/src/boost/libs/compute/test/test_next_permutation.cpp
new file mode 100644
index 00000000..b76c3811
--- /dev/null
+++ b/src/boost/libs/compute/test/test_next_permutation.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestNextPermutation
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/next_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(next_permutation_int)
+{
+ int dataset[] = {1, 3, 4, 2, 5};
+ bc::vector<bc::int_> vector(dataset, dataset + 5, queue);
+
+ bool result =
+ bc::next_permutation(vector.begin(), vector.begin() + 5, queue);
+
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 3, 4, 5, 2));
+ BOOST_VERIFY(result == true);
+
+ vector[0] = 10; vector[1] = 9; vector[2] = 6;
+
+ result = bc::next_permutation(vector.begin(), vector.begin() + 5, queue);
+
+ CHECK_RANGE_EQUAL(int, 5, vector, (2, 5, 6, 9, 10));
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(next_permutation_string)
+{
+ char dataset[] = "aaab";
+ bc::vector<bc::char_> vector(dataset, dataset + 4, queue);
+
+ bool result =
+ bc::next_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'a', 'b', 'a'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::next_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'b', 'a', 'a'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::next_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('b', 'a', 'a', 'a'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::next_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'a', 'a', 'b'));
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_no_device_found.cpp b/src/boost/libs/compute/test/test_no_device_found.cpp
new file mode 100644
index 00000000..91a48870
--- /dev/null
+++ b/src/boost/libs/compute/test/test_no_device_found.cpp
@@ -0,0 +1,31 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2015 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 TestNoDeviceFound
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/exception/no_device_found.hpp>
+
+void throw_no_device_found()
+{
+ throw boost::compute::no_device_found();
+}
+
+BOOST_AUTO_TEST_CASE(what)
+{
+ try {
+ throw_no_device_found();
+
+ BOOST_REQUIRE(false); // should not get here
+ }
+ catch(boost::compute::no_device_found& e){
+ BOOST_CHECK_EQUAL(std::string(e.what()), "No OpenCL device found");
+ }
+}
diff --git a/src/boost/libs/compute/test/test_normal_distribution.cpp b/src/boost/libs/compute/test/test_normal_distribution.cpp
new file mode 100644
index 00000000..bb8a93ca
--- /dev/null
+++ b/src/boost/libs/compute/test/test_normal_distribution.cpp
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestNormalDistribution
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/normal_distribution.hpp>
+#include <boost/compute/lambda.hpp>
+
+#include <boost/accumulators/accumulators.hpp>
+#include <boost/accumulators/statistics/mean.hpp>
+#include <boost/accumulators/statistics/stats.hpp>
+#include <boost/accumulators/statistics/variance.hpp>
+
+#include "context_setup.hpp"
+
+template<class Stats, class T>
+boost::accumulators::accumulator_set<T, Stats>
+accumulate_statistics(const boost::compute::vector<T>& vector,
+ boost::compute::command_queue& queue) {
+ // copy vector to the host
+ std::vector<T> host_vector(vector.size());
+ boost::compute::copy(
+ vector.begin(), vector.end(), host_vector.begin(), queue
+ );
+
+ // compute desired statistics and return accumulator object
+ return std::for_each(
+ host_vector.begin(),
+ host_vector.end(),
+ boost::accumulators::accumulator_set<T, Stats>()
+ );
+}
+
+BOOST_AUTO_TEST_CASE(normal_distribution_doctest)
+{
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<float> vec(10, context);
+
+//! [generate]
+// initialize the default random engine
+boost::compute::default_random_engine engine(queue);
+
+// setup the normal distribution to produce floats centered at 5
+boost::compute::normal_distribution<float> distribution(5.0f, 1.0f);
+
+// generate the random values and store them to 'vec'
+distribution.generate(vec.begin(), vec.end(), engine, queue);
+//! [generate]
+}
+
+BOOST_AUTO_TEST_CASE(normal_distribution_statistics)
+{
+ // generate normally distributed random numbers
+ const size_t n = 10000;
+ boost::compute::vector<float> vec(n, context);
+ boost::compute::default_random_engine engine(queue);
+ boost::compute::normal_distribution<float> distribution(10.0f, 2.0f);
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ // compute mean and standard deviation
+ using namespace boost::accumulators;
+ accumulator_set<float, stats<tag::variance> > acc =
+ accumulate_statistics<stats<tag::variance> >(vec, queue);
+
+ // check mean and standard deviation are what we expect
+ BOOST_CHECK_CLOSE(mean(acc), 10.f, 0.5f);
+ BOOST_CHECK_CLOSE(std::sqrt(variance(acc)), 2.f, 0.5f);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_nth_element.cpp b/src/boost/libs/compute/test/test_nth_element.cpp
new file mode 100644
index 00000000..ac072732
--- /dev/null
+++ b/src/boost/libs/compute/test/test_nth_element.cpp
@@ -0,0 +1,113 @@
+//---------------------------------------------------------------------------//
+// 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 TestNthElement
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/is_partitioned.hpp>
+#include <boost/compute/algorithm/nth_element.hpp>
+#include <boost/compute/algorithm/partition_point.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(nth_element_int)
+{
+ int data[] = { 9, 15, 1, 4, 9, 9, 4, 15, 12, 1 };
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::nth_element(
+ vector.begin(), vector.begin() + 5, vector.end(), queue
+ );
+
+ BOOST_CHECK_EQUAL(vector[5], 9);
+ BOOST_VERIFY(boost::compute::is_partitioned(
+ vector.begin(), vector.end(), boost::compute::_1 <= 9, queue
+ ));
+ BOOST_VERIFY(boost::compute::partition_point(
+ vector.begin(), vector.end(), boost::compute::_1 <= 9, queue
+ ) > vector.begin() + 5);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::nth_element(
+ vector.begin(), vector.end(), vector.end(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 10, vector, (9, 15, 1, 4, 9, 9, 4, 15, 12, 1));
+}
+
+BOOST_AUTO_TEST_CASE(nth_element_median)
+{
+ int data[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
+ boost::compute::vector<int> v(9, context);
+ boost::compute::copy_n(data, 9, v.begin(), queue);
+
+ boost::compute::nth_element(v.begin(), v.begin() + 4, v.end(), queue);
+
+ BOOST_CHECK_EQUAL(v[4], 5);
+ BOOST_VERIFY(boost::compute::is_partitioned(
+ v.begin(), v.end(), boost::compute::_1 <= 5, queue
+ ));
+ BOOST_VERIFY(boost::compute::partition_point(
+ v.begin(), v.end(), boost::compute::_1 <= 5, queue
+ ) > v.begin() + 4);
+}
+
+BOOST_AUTO_TEST_CASE(nth_element_second_largest)
+{
+ int data[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
+ boost::compute::vector<int> v(9, context);
+ boost::compute::copy_n(data, 9, v.begin(), queue);
+
+ boost::compute::nth_element(v.begin(), v.begin() + 1, v.end(), queue);
+
+ BOOST_CHECK_EQUAL(v[1], 3);
+ BOOST_VERIFY(boost::compute::is_partitioned(
+ v.begin(), v.end(), boost::compute::_1 <= 3, queue
+ ));
+ BOOST_VERIFY(boost::compute::partition_point(
+ v.begin(), v.end(), boost::compute::_1 <= 3, queue
+ ) > v.begin() + 1);
+}
+
+BOOST_AUTO_TEST_CASE(nth_element_comparator)
+{
+ int data[] = { 9, 15, 1, 4, 9, 9, 4, 15, 12, 1 };
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::less<int> less_than;
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::nth_element(
+ vector.begin(), vector.begin() + 5, vector.end(), less_than, queue
+ );
+ BOOST_CHECK_EQUAL(vector[5], 9);
+ BOOST_VERIFY(boost::compute::is_partitioned(
+ vector.begin(), vector.end(), boost::compute::_1 <= 9, queue
+ ));
+ BOOST_VERIFY(boost::compute::partition_point(
+ vector.begin(), vector.end(), boost::compute::_1 <= 9, queue
+ ) > vector.begin() + 5);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::nth_element(
+ vector.begin(), vector.end(), vector.end(), less_than, queue
+ );
+ CHECK_RANGE_EQUAL(int, 10, vector, (9, 15, 1, 4, 9, 9, 4, 15, 12, 1));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_opencl_error.cpp b/src/boost/libs/compute/test/test_opencl_error.cpp
new file mode 100644
index 00000000..6735b44a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_opencl_error.cpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestOpenCLError
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/exception/opencl_error.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(error_to_string)
+{
+ using boost::compute::opencl_error;
+
+ BOOST_CHECK_EQUAL(opencl_error::to_string(CL_SUCCESS), "Success");
+ BOOST_CHECK_EQUAL(opencl_error::to_string(CL_INVALID_VALUE), "Invalid Value");
+ BOOST_CHECK_EQUAL(opencl_error::to_string(-123456), "Unknown OpenCL Error (-123456)");
+}
+
+BOOST_AUTO_TEST_CASE(error_code)
+{
+ boost::compute::opencl_error e(CL_INVALID_DEVICE);
+ BOOST_CHECK_EQUAL(e.error_code(), CL_INVALID_DEVICE);
+ BOOST_CHECK_EQUAL(e.error_string(), "Invalid Device");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_pair.cpp b/src/boost/libs/compute/test/test_pair.cpp
new file mode 100644
index 00000000..055ed920
--- /dev/null
+++ b/src/boost/libs/compute/test/test_pair.cpp
@@ -0,0 +1,194 @@
+//---------------------------------------------------------------------------//
+// 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 TestPair
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/get.hpp>
+#include <boost/compute/functional/field.hpp>
+#include <boost/compute/types/pair.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(vector_pair_int_float)
+{
+ boost::compute::vector<std::pair<int, float> > vector(context);
+ vector.push_back(std::make_pair(1, 1.1f), queue);
+ vector.push_back(std::make_pair(2, 2.2f), queue);
+ vector.push_back(std::make_pair(3, 3.3f), queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.size(), size_t(3));
+ BOOST_CHECK(vector[0] == std::make_pair(1, 1.1f));
+ BOOST_CHECK(vector[1] == std::make_pair(2, 2.2f));
+ BOOST_CHECK(vector[2] == std::make_pair(3, 3.3f));
+}
+
+BOOST_AUTO_TEST_CASE(copy_pair_vector)
+{
+ boost::compute::vector<std::pair<int, float> > input(context);
+ input.push_back(std::make_pair(1, 2.0f), queue);
+ input.push_back(std::make_pair(3, 4.0f), queue);
+ input.push_back(std::make_pair(5, 6.0f), queue);
+ input.push_back(std::make_pair(7, 8.0f), queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(input.size(), size_t(4));
+
+ boost::compute::vector<std::pair<int, float> > output(4, context);
+ boost::compute::copy(input.begin(), input.end(), output.begin(), queue);
+ queue.finish();
+ BOOST_CHECK(output[0] == std::make_pair(1, 2.0f));
+ BOOST_CHECK(output[1] == std::make_pair(3, 4.0f));
+ BOOST_CHECK(output[2] == std::make_pair(5, 6.0f));
+ BOOST_CHECK(output[3] == std::make_pair(7, 8.0f));
+}
+
+BOOST_AUTO_TEST_CASE(fill_pair_vector)
+{
+ if(bug_in_struct_assignment(device)){
+ std::cerr << "skipping fill_pair_vector test" << std::endl;
+ return;
+ }
+
+ boost::compute::vector<std::pair<int, float> > vector(5, context);
+ boost::compute::fill(vector.begin(), vector.end(), std::make_pair(4, 2.0f), queue);
+ queue.finish();
+ BOOST_CHECK(vector[0] == std::make_pair(4, 2.0f));
+ BOOST_CHECK(vector[1] == std::make_pair(4, 2.0f));
+ BOOST_CHECK(vector[2] == std::make_pair(4, 2.0f));
+ BOOST_CHECK(vector[3] == std::make_pair(4, 2.0f));
+ BOOST_CHECK(vector[4] == std::make_pair(4, 2.0f));
+}
+
+BOOST_AUTO_TEST_CASE(fill_char_pair_vector)
+{
+ if(bug_in_struct_assignment(device)){
+ std::cerr << "skipping fill_char_pair_vector test" << std::endl;
+ return;
+ }
+
+ std::pair<char, unsigned char> value('c', static_cast<unsigned char>(127));
+ boost::compute::vector<std::pair<char, unsigned char> > vector(5, context);
+ boost::compute::fill(vector.begin(), vector.end(), value, queue);
+ queue.finish();
+ BOOST_CHECK(vector[0] == value);
+ BOOST_CHECK(vector[1] == value);
+ BOOST_CHECK(vector[2] == value);
+ BOOST_CHECK(vector[3] == value);
+ BOOST_CHECK(vector[4] == value);
+}
+
+BOOST_AUTO_TEST_CASE(transform_pair_get)
+{
+ boost::compute::vector<std::pair<int, float> > input(context);
+ input.push_back(std::make_pair(1, 2.0f), queue);
+ input.push_back(std::make_pair(3, 4.0f), queue);
+ input.push_back(std::make_pair(5, 6.0f), queue);
+ input.push_back(std::make_pair(7, 8.0f), queue);
+ queue.finish();
+
+ boost::compute::vector<int> first_output(4, context);
+ boost::compute::transform(
+ input.begin(),
+ input.end(),
+ first_output.begin(),
+ ::boost::compute::get<0>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_output, (1, 3, 5, 7));
+
+ boost::compute::vector<float> second_output(4, context);
+ boost::compute::transform(
+ input.begin(),
+ input.end(),
+ second_output.begin(),
+ ::boost::compute::get<1>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 4, second_output, (2.0f, 4.0f, 6.0f, 8.0f));
+}
+
+BOOST_AUTO_TEST_CASE(transform_pair_field)
+{
+ boost::compute::vector<std::pair<int, float> > input(context);
+ input.push_back(std::make_pair(1, 2.0f), queue);
+ input.push_back(std::make_pair(3, 4.0f), queue);
+ input.push_back(std::make_pair(5, 6.0f), queue);
+ input.push_back(std::make_pair(7, 8.0f), queue);
+
+ boost::compute::vector<int> first_output(4, context);
+ boost::compute::transform(
+ input.begin(),
+ input.end(),
+ first_output.begin(),
+ boost::compute::field<int>("first"),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 4, first_output, (1, 3, 5, 7));
+
+ boost::compute::vector<float> second_output(4, context);
+ boost::compute::transform(
+ input.begin(),
+ input.end(),
+ second_output.begin(),
+ boost::compute::field<float>("second"),
+ queue
+ );
+ CHECK_RANGE_EQUAL(float, 4, second_output, (2.0f, 4.0f, 6.0f, 8.0f));
+}
+
+BOOST_AUTO_TEST_CASE(find_vector_pair)
+{
+ boost::compute::vector<std::pair<int, float> > vector(context);
+ vector.push_back(std::make_pair(1, 1.1f), queue);
+ vector.push_back(std::make_pair(2, 2.2f), queue);
+ vector.push_back(std::make_pair(3, 3.3f), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(3));
+
+ BOOST_CHECK(
+ boost::compute::find(
+ boost::compute::make_transform_iterator(
+ vector.begin(),
+ boost::compute::get<0>()
+ ),
+ boost::compute::make_transform_iterator(
+ vector.end(),
+ boost::compute::get<0>()
+ ),
+ int(2),
+ queue
+ ).base() == vector.begin() + 1
+ );
+
+ BOOST_CHECK(
+ boost::compute::find(
+ boost::compute::make_transform_iterator(
+ vector.begin(),
+ boost::compute::get<1>()
+ ),
+ boost::compute::make_transform_iterator(
+ vector.end(),
+ boost::compute::get<1>()
+ ),
+ float(3.3f),
+ queue
+ ).base() == vector.begin() + 2
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_partial_sum.cpp b/src/boost/libs/compute/test/test_partial_sum.cpp
new file mode 100644
index 00000000..f8d82922
--- /dev/null
+++ b/src/boost/libs/compute/test/test_partial_sum.cpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// 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 TestPartialSum
+#include <boost/test/unit_test.hpp>
+
+#include <vector>
+#include <numeric>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/partial_sum.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(partial_sum_int)
+{
+ int data[] = { 1, 2, 5, 3, 9, 1, 4, 2 };
+ bc::vector<int> a(8, context);
+ bc::copy(data, data + 8, a.begin(), queue);
+
+ bc::vector<int> b(a.size(), context);
+ bc::vector<int>::iterator iter =
+ bc::partial_sum(a.begin(), a.end(), b.begin(), queue);
+ BOOST_CHECK(iter == b.end());
+ CHECK_RANGE_EQUAL(int, 8, b, (1, 3, 8, 11, 20, 21, 25, 27));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_partition.cpp b/src/boost/libs/compute/test/test_partition.cpp
new file mode 100644
index 00000000..b6faac8d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_partition.cpp
@@ -0,0 +1,82 @@
+//---------------------------------------------------------------------------//
+// 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 TestPartition
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/algorithm/partition_copy.hpp>
+#include <boost/compute/algorithm/is_partitioned.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(partition_float_vector)
+{
+ bc::vector<float> vector(context);
+ vector.push_back(1.0f, queue);
+ vector.push_back(2.0f, queue);
+ vector.push_back(-1.0f, queue);
+ vector.push_back(-2.0f, queue);
+ vector.push_back(3.0f, queue);
+ vector.push_back(4.0f, queue);
+ vector.push_back(-3.0f, queue);
+ vector.push_back(-4.0f, queue);
+
+ // verify is_partitioned()
+ BOOST_VERIFY(bc::is_partitioned(vector.begin(),
+ vector.end(),
+ bc::signbit_<float>(),
+ queue) == false);
+
+ // partition by signbit
+ bc::vector<float>::iterator iter = bc::partition(vector.begin(),
+ vector.end(),
+ bc::signbit_<float>(),
+ queue);
+ queue.finish();
+ BOOST_VERIFY(iter == vector.begin() + 4);
+ BOOST_CHECK_LT(vector[0], 0.0f);
+ BOOST_CHECK_LT(vector[1], 0.0f);
+ BOOST_CHECK_LT(vector[2], 0.0f);
+ BOOST_CHECK_LT(vector[3], 0.0f);
+ BOOST_CHECK_GT(vector[4], 0.0f);
+ BOOST_CHECK_GT(vector[5], 0.0f);
+ BOOST_CHECK_GT(vector[6], 0.0f);
+ BOOST_CHECK_GT(vector[7], 0.0f);
+
+ // verify is_partitioned()
+ BOOST_VERIFY(bc::is_partitioned(vector.begin(),
+ vector.end(),
+ bc::signbit_<float>(),
+ queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(partition_small_vector)
+{
+ bc::vector<float> vector(context);
+ bc::partition(vector.begin(), vector.end(), bc::signbit_<float>(), queue);
+
+ vector.push_back(1.0f, queue);
+ bc::partition(vector.begin(), vector.end(), bc::signbit_<float>(), queue);
+ CHECK_RANGE_EQUAL(float, 1, vector, (1.0f));
+
+ vector.push_back(-1.0f, queue);
+ bc::partition(vector.begin(), vector.end(), bc::signbit_<float>(), queue);
+ CHECK_RANGE_EQUAL(float, 2, vector, (-1.0f, 1.0f));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_partition_point.cpp b/src/boost/libs/compute/test/test_partition_point.cpp
new file mode 100644
index 00000000..5cee7e9f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_partition_point.cpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestPartitionPoint
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/partition_point.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(partition_point_int)
+{
+ int dataset[] = {1, 1, 5, 2, 4, -2, 0, -1, 0, -1};
+ bc::vector<bc::int_> vector(dataset, dataset + 10, queue);
+
+ bc::vector<bc::int_>::iterator iter =
+ bc::partition_point(vector.begin(), vector.begin() + 10,
+ bc::_1 > 0, queue);
+
+ BOOST_VERIFY(iter == vector.begin()+5);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_permutation_iterator.cpp b/src/boost/libs/compute/test/test_permutation_iterator.cpp
new file mode 100644
index 00000000..ee6488c3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_permutation_iterator.cpp
@@ -0,0 +1,110 @@
+//---------------------------------------------------------------------------//
+// 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 TestPermutationIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/permutation_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ using boost::compute::float4_;
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::permutation_iterator<
+ boost::compute::buffer_iterator<float>,
+ boost::compute::buffer_iterator<int>
+ >::value_type,
+ float
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::permutation_iterator<
+ boost::compute::buffer_iterator<float4_>,
+ boost::compute::buffer_iterator<short>
+ >::value_type,
+ float4_
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(base_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::permutation_iterator<
+ boost::compute::buffer_iterator<int>,
+ boost::compute::buffer_iterator<int>
+ >::base_type,
+ boost::compute::buffer_iterator<int>
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ int input_data[] = { 3, 4, 2, 1, 5 };
+ boost::compute::vector<int> input(input_data, input_data + 5, queue);
+
+ int map_data[] = { 3, 2, 0, 1, 4 };
+ boost::compute::vector<int> map(map_data, map_data + 5, queue);
+
+ boost::compute::vector<int> output(5, context);
+ boost::compute::copy(
+ boost::compute::make_permutation_iterator(input.begin(), map.begin()),
+ boost::compute::make_permutation_iterator(input.end(), map.end()),
+ output.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 2, 3, 4, 5));
+}
+
+BOOST_AUTO_TEST_CASE(reverse_range_doctest)
+{
+ int values_data[] = { 10, 20, 30, 40 };
+ int indices_data[] = { 3, 2, 1, 0 };
+
+ boost::compute::vector<int> values(values_data, values_data + 4, queue);
+ boost::compute::vector<int> indices(indices_data, indices_data + 4, queue);
+
+ boost::compute::vector<int> result(4, context);
+
+//! [reverse_range]
+// values = { 10, 20, 30, 40 }
+// indices = { 3, 2, 1, 0 }
+
+boost::compute::copy(
+ boost::compute::make_permutation_iterator(values.begin(), indices.begin()),
+ boost::compute::make_permutation_iterator(values.end(), indices.end()),
+ result.begin(),
+ queue
+);
+
+// result == { 40, 30, 20, 10 }
+//! [reverse_range]
+
+ CHECK_RANGE_EQUAL(int, 4, result, (40, 30, 20, 10));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_pinned_allocator.cpp b/src/boost/libs/compute/test/test_pinned_allocator.cpp
new file mode 100644
index 00000000..ca34c034
--- /dev/null
+++ b/src/boost/libs/compute/test/test_pinned_allocator.cpp
@@ -0,0 +1,27 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestPinnedAllocator
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/allocator/pinned_allocator.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(vector_with_pinned_allocator)
+{
+ compute::vector<int, compute::pinned_allocator<int> > vector(context);
+ vector.push_back(12, queue);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_pipe.cpp b/src/boost/libs/compute/test/test_pipe.cpp
new file mode 100644
index 00000000..25e61c8d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_pipe.cpp
@@ -0,0 +1,36 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestPipe
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/core.hpp>
+#include <boost/compute/pipe.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(empty)
+{
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+BOOST_AUTO_TEST_CASE(create_pipe)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ compute::pipe pipe(context, 16 * sizeof(float), 128);
+ BOOST_CHECK_EQUAL(pipe.get_info<CL_PIPE_PACKET_SIZE>(), 64);
+ BOOST_CHECK_EQUAL(pipe.get_info<CL_PIPE_MAX_PACKETS>(), 128);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_platform.cpp b/src/boost/libs/compute/test/test_platform.cpp
new file mode 100644
index 00000000..76cfaecb
--- /dev/null
+++ b/src/boost/libs/compute/test/test_platform.cpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestPlatform
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/platform.hpp>
+#include <boost/compute/system.hpp>
+
+BOOST_AUTO_TEST_CASE(platform_id)
+{
+ boost::compute::platform platform =
+ boost::compute::system::platforms().front();
+
+ boost::compute::platform platform_copy(platform.id());
+
+ BOOST_CHECK(platform == platform_copy);
+ BOOST_CHECK(platform.id() == platform_copy.id());
+}
+
+BOOST_AUTO_TEST_CASE(platform_supports_extension)
+{
+ boost::compute::platform platform =
+ boost::compute::system::platforms().front();
+
+ std::string extensions = platform.get_info<CL_PLATFORM_EXTENSIONS>();
+ if(extensions.empty()){
+ std::cerr << "platform doesn't support any extensions" << std::endl;
+ return;
+ }
+
+ size_t space = extensions.find(' ');
+ std::string first_extension = extensions.substr(0, space);
+ BOOST_CHECK(platform.supports_extension(first_extension) == true);
+ BOOST_CHECK(platform.supports_extension("invalid_extension_name") == false);
+}
diff --git a/src/boost/libs/compute/test/test_prev_permutation.cpp b/src/boost/libs/compute/test/test_prev_permutation.cpp
new file mode 100644
index 00000000..b6edf4cf
--- /dev/null
+++ b/src/boost/libs/compute/test/test_prev_permutation.cpp
@@ -0,0 +1,71 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestPrevPermutation
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/prev_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(prev_permutation_int)
+{
+ int dataset[] = {1, 3, 4, 2, 5};
+ bc::vector<bc::int_> vector(dataset, dataset + 5, queue);
+
+ bool result =
+ bc::prev_permutation(vector.begin(), vector.begin() + 5, queue);
+
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 3, 2, 5, 4));
+ BOOST_VERIFY(result == true);
+
+ vector[1] = 1; vector[4] = 6;
+
+ result = bc::prev_permutation(vector.begin(), vector.begin() + 5, queue);
+
+ CHECK_RANGE_EQUAL(int, 5, vector, (6, 5, 2, 1, 1));
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_CASE(prev_permutation_string)
+{
+ char dataset[] = "baaa";
+ bc::vector<bc::char_> vector(dataset, dataset + 4, queue);
+
+ bool result =
+ bc::prev_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'b', 'a', 'a'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::prev_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'a', 'b', 'a'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::prev_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('a', 'a', 'a', 'b'));
+ BOOST_VERIFY(result == true);
+
+ result = bc::prev_permutation(vector.begin(), vector.begin() + 4, queue);
+
+ CHECK_RANGE_EQUAL(char, 4, vector, ('b', 'a', 'a', 'a'));
+ BOOST_VERIFY(result == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_program.cpp b/src/boost/libs/compute/test/test_program.cpp
new file mode 100644
index 00000000..7172c5e2
--- /dev/null
+++ b/src/boost/libs/compute/test/test_program.cpp
@@ -0,0 +1,401 @@
+//---------------------------------------------------------------------------//
+// 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 TestProgram
+#include <boost/test/unit_test.hpp>
+
+// disable the automatic kernel compilation debug messages. this allows the
+// test for program to check that compilation error exceptions are properly
+// thrown when invalid kernel code is passed to program::build().
+#undef BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
+
+#include <boost/compute/exception/program_build_failure.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include "quirks.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+const char source[] =
+ "__kernel void foo(__global float *x, const uint n) { }\n"
+ "__kernel void bar(__global int *x, __global int *y) { }\n";
+
+
+BOOST_AUTO_TEST_CASE(get_program_info)
+{
+ // create program
+ boost::compute::program program =
+ boost::compute::program::create_with_source(source, context);
+
+ // build program
+ program.build();
+
+ // check program info
+#ifndef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ BOOST_CHECK(program.source().empty() == false);
+#endif
+ BOOST_CHECK(program.get_context() == context);
+}
+
+BOOST_AUTO_TEST_CASE(program_source)
+{
+ // create program from source
+ boost::compute::program program =
+ boost::compute::program::create_with_source(source, context);
+
+ BOOST_CHECK_EQUAL(std::string(source), program.source());
+}
+
+BOOST_AUTO_TEST_CASE(program_multiple_sources)
+{
+ std::vector<std::string> sources;
+ sources.push_back("__kernel void foo(__global int* x) { }\n");
+ sources.push_back("__kernel void bar(__global float* y) { }\n");
+
+ // create program from sources
+ boost::compute::program program =
+ boost::compute::program::create_with_source(sources, context);
+ program.build();
+
+ boost::compute::kernel foo = program.create_kernel("foo");
+ boost::compute::kernel bar = program.create_kernel("bar");
+}
+
+BOOST_AUTO_TEST_CASE(program_source_no_file)
+{
+ // create program from a non-existant source file
+ // and verifies it throws.
+ BOOST_CHECK_THROW(boost::compute::program program =
+ boost::compute::program::create_with_source_file
+ (std::string(), context),
+ std::ios_base::failure);
+}
+
+BOOST_AUTO_TEST_CASE(create_kernel)
+{
+ boost::compute::program program =
+ boost::compute::program::create_with_source(source, context);
+ program.build();
+
+ boost::compute::kernel foo = program.create_kernel("foo");
+ boost::compute::kernel bar = program.create_kernel("bar");
+
+ // try to create a kernel that doesn't exist
+ BOOST_CHECK_THROW(program.create_kernel("baz"), boost::compute::opencl_error);
+}
+
+BOOST_AUTO_TEST_CASE(create_with_binary)
+{
+ // create program from source
+ boost::compute::program source_program =
+ boost::compute::program::create_with_source(source, context);
+ source_program.build();
+
+ // create kernels in source program
+ boost::compute::kernel source_foo_kernel = source_program.create_kernel("foo");
+ boost::compute::kernel source_bar_kernel = source_program.create_kernel("bar");
+
+ // check source kernels
+ BOOST_CHECK_EQUAL(source_foo_kernel.name(), std::string("foo"));
+ BOOST_CHECK_EQUAL(source_bar_kernel.name(), std::string("bar"));
+
+ // get binary
+ std::vector<unsigned char> binary = source_program.binary();
+
+ // create program from binary
+ boost::compute::program binary_program =
+ boost::compute::program::create_with_binary(binary, context);
+ binary_program.build();
+
+ // create kernels in binary program
+ boost::compute::kernel binary_foo_kernel = binary_program.create_kernel("foo");
+ boost::compute::kernel binary_bar_kernel = binary_program.create_kernel("bar");
+
+ // check binary kernels
+ BOOST_CHECK_EQUAL(binary_foo_kernel.name(), std::string("foo"));
+ BOOST_CHECK_EQUAL(binary_bar_kernel.name(), std::string("bar"));
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(create_with_il)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ size_t device_address_space_size = device.address_bits();
+ std::string file_path(BOOST_COMPUTE_TEST_DATA_PATH);
+ if(device_address_space_size == 64)
+ {
+ file_path += "/program.spirv64";
+ }
+ else
+ {
+ file_path += "/program.spirv32";
+ }
+
+ // create program from il
+ boost::compute::program il_program;
+ BOOST_CHECK_NO_THROW(
+ il_program = boost::compute::program::create_with_il_file(
+ file_path, context
+ )
+ );
+ BOOST_CHECK_NO_THROW(il_program.build());
+
+ // create kernel (to check if program was loaded correctly)
+ BOOST_CHECK_NO_THROW(il_program.create_kernel("foobar"));
+}
+
+BOOST_AUTO_TEST_CASE(get_program_il_binary)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ size_t device_address_space_size = device.address_bits();
+ std::string file_path(BOOST_COMPUTE_TEST_DATA_PATH);
+ if(device_address_space_size == 64)
+ {
+ file_path += "/program.spirv64";
+ }
+ else
+ {
+ file_path += "/program.spirv32";
+ }
+
+ // create program from il
+ boost::compute::program il_program;
+ BOOST_CHECK_NO_THROW(
+ il_program = boost::compute::program::create_with_il_file(
+ file_path, context
+ )
+ );
+ BOOST_CHECK_NO_THROW(il_program.build());
+
+ std::vector<unsigned char> il_binary;
+ BOOST_CHECK_NO_THROW(il_binary = il_program.il_binary());
+
+ // create program from loaded il binary
+ BOOST_CHECK_NO_THROW(
+ il_program = boost::compute::program::create_with_il(il_binary, context)
+ );
+ BOOST_CHECK_NO_THROW(il_program.build());
+
+ // create kernel (to check if program was loaded correctly)
+ BOOST_CHECK_NO_THROW(il_program.create_kernel("foobar"));
+}
+
+BOOST_AUTO_TEST_CASE(get_program_il_binary_empty)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ boost::compute::program program;
+ BOOST_CHECK_NO_THROW(
+ program = boost::compute::program::create_with_source(source, context)
+ );
+ BOOST_CHECK_NO_THROW(program.build());
+
+ std::vector<unsigned char> il_binary;
+ il_binary = program.il_binary();
+ BOOST_CHECK(il_binary.empty());
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_1
+
+BOOST_AUTO_TEST_CASE(create_with_source_doctest)
+{
+//! [create_with_source]
+std::string source = "__kernel void foo(__global int *data) { }";
+
+boost::compute::program foo_program =
+ boost::compute::program::create_with_source(source, context);
+//! [create_with_source]
+
+ foo_program.build();
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_2
+BOOST_AUTO_TEST_CASE(compile_and_link)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(!supports_compile_program(device) || !supports_link_program(device)) {
+ return;
+ }
+
+ // create the library program
+ const char library_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // for some reason the apple opencl compilers complains if a prototype
+ // for the square() function is not available, so we add it here
+ T square(T);
+
+ // generic square function definition
+ T square(T x) { return x * x; }
+ );
+
+ compute::program library_program =
+ compute::program::create_with_source(library_source, context);
+
+ library_program.compile("-DT=int");
+
+ // create the kernel program
+ const char kernel_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // forward declare square function
+ extern int square(int);
+
+ // square kernel definition
+ __kernel void square_kernel(__global int *x)
+ {
+ x[0] = square(x[0]);
+ }
+ );
+
+ compute::program square_program =
+ compute::program::create_with_source(kernel_source, context);
+
+ square_program.compile();
+
+ // link the programs
+ std::vector<compute::program> programs;
+ programs.push_back(library_program);
+ programs.push_back(square_program);
+
+ compute::program linked_program =
+ compute::program::link(programs, context);
+
+ // create the square kernel
+ compute::kernel square_kernel =
+ linked_program.create_kernel("square_kernel");
+ BOOST_CHECK_EQUAL(square_kernel.name(), "square_kernel");
+}
+
+BOOST_AUTO_TEST_CASE(compile_and_link_with_headers)
+{
+ REQUIRES_OPENCL_VERSION(1,2);
+
+ if(!supports_compile_program(device) || !supports_link_program(device)) {
+ return;
+ }
+
+ // create the header programs
+ const char square_header_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ T square(T x) { return x * x; }
+ );
+ const char div2_header_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ T div2(T x) { return x / 2; }
+ );
+
+ compute::program square_header_program =
+ compute::program::create_with_source(square_header_source, context);
+ compute::program div2_header_program =
+ compute::program::create_with_source(div2_header_source, context);
+
+ // create the kernel program
+ const char kernel_source[] =
+ "#include \"square.h\"\n"
+ "#include \"div2.h\"\n"
+ "__kernel void squareby2_kernel(__global int *x)"
+ "{"
+ " x[0] = div2(square(x[0]));"
+ "}";
+
+ compute::program square_program =
+ compute::program::create_with_source(kernel_source, context);
+
+ std::vector<std::pair<std::string, compute::program> > header_programs;
+ header_programs.push_back(std::make_pair("square.h", square_header_program));
+ header_programs.push_back(std::make_pair("div2.h", div2_header_program));
+
+ square_program.compile("-DT=int", header_programs);
+
+ // link program
+ std::vector<compute::program> programs;
+ programs.push_back(square_program);
+
+ compute::program linked_program =
+ compute::program::link(programs, context);
+
+ // create the square kernel
+ compute::kernel square_kernel =
+ linked_program.create_kernel("squareby2_kernel");
+ BOOST_CHECK_EQUAL(square_kernel.name(), "squareby2_kernel");
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_2
+
+BOOST_AUTO_TEST_CASE(build_log)
+{
+ const char invalid_source[] =
+ "__kernel void foo(__global int *input) { !@#$%^&*() }";
+
+ compute::program invalid_program =
+ compute::program::create_with_source(invalid_source, context);
+
+ try {
+ invalid_program.build();
+
+ // should not get here
+ BOOST_CHECK(false);
+ }
+ catch(compute::opencl_error&){
+ std::string log = invalid_program.build_log();
+ BOOST_CHECK(!log.empty());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(program_build_exception)
+{
+ const char invalid_source[] =
+ "__kernel void foo(__global int *input) { !@#$%^&*() }";
+
+ compute::program invalid_program =
+ compute::program::create_with_source(invalid_source, context);
+
+ BOOST_CHECK_THROW(invalid_program.build(),
+ compute::program_build_failure);
+
+ try {
+ // POCL bug: https://github.com/pocl/pocl/issues/577
+ if(pocl_bug_issue_577(device))
+ {
+ invalid_program =
+ compute::program::create_with_source(invalid_source, context);
+ }
+ invalid_program.build();
+
+ // should not get here
+ BOOST_CHECK(false);
+ }
+ catch(compute::program_build_failure& e){
+ BOOST_CHECK(e.build_log() == invalid_program.build_log());
+ }
+ catch(...)
+ {
+ // should not get here
+ BOOST_CHECK(false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(build_with_source_exception)
+{
+ const char invalid_source[] =
+ "__kernel void foo(__global int *input) { !@#$%^&*() }";
+
+ BOOST_CHECK_THROW(compute::program::build_with_source(invalid_source, context),
+ compute::program_build_failure);
+}
+
+BOOST_AUTO_TEST_CASE(build_with_source_file_exception)
+{
+ std::string file_path(BOOST_COMPUTE_TEST_DATA_PATH "/invalid_program.cl");
+ BOOST_CHECK_THROW(compute::program::build_with_source_file(file_path, context),
+ compute::program_build_failure);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_program_cache.cpp b/src/boost/libs/compute/test/test_program_cache.cpp
new file mode 100644
index 00000000..446e9a87
--- /dev/null
+++ b/src/boost/libs/compute/test/test_program_cache.cpp
@@ -0,0 +1,99 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestProgramCache
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(setup)
+{
+ // get default context
+ compute::context ctx = context;
+
+ // get program cache
+ boost::shared_ptr<compute::program_cache> cache =
+ compute::program_cache::get_global_cache(ctx);
+
+ // try to load a null string
+ BOOST_CHECK(cache->get(std::string()) == boost::none);
+
+ // try to load a non-existant program
+ BOOST_CHECK(cache->get("nonexistant") == boost::none);
+
+ // create and store a program
+ const char p1_source[] =
+ "__kernel void add(__global int *a, int x)\n"
+ "{\n"
+ " a[get_global_id(0)] += x;\n"
+ "}\n";
+ compute::program p1 =
+ compute::program::create_with_source(p1_source, ctx);
+ p1.build();
+ cache->insert("p1", p1);
+
+ // try to load the program
+ BOOST_CHECK(cache->get("p1") == p1);
+
+ // create a copy of the context
+ compute::context ctx_copy = ctx;
+
+ // check that they both have the same cl_context
+ BOOST_CHECK(ctx_copy.get() == ctx.get());
+
+ // check that the cache is the same
+ boost::shared_ptr<compute::program_cache> cache_copy =
+ compute::program_cache::get_global_cache(ctx_copy);
+ BOOST_CHECK(cache_copy == cache);
+
+ // try to load the program again
+ BOOST_CHECK(cache_copy->get("p1") == p1);
+}
+
+BOOST_AUTO_TEST_CASE(evict)
+{
+ // create cache with capacity of four and insert four programs
+ compute::program_cache cache(4);
+ cache.insert("a", compute::program());
+ cache.insert("b", compute::program());
+ cache.insert("c", compute::program());
+ cache.insert("d", compute::program());
+
+ // check that all four programs still reside in the cache
+ BOOST_CHECK(cache.get("a") != boost::none);
+ BOOST_CHECK(cache.get("b") != boost::none);
+ BOOST_CHECK(cache.get("c") != boost::none);
+ BOOST_CHECK(cache.get("d") != boost::none);
+
+ // insert fifth program which should evict the oldest ("a")
+ cache.insert("e", compute::program());
+
+ // check that "a" has been evicted and that "e" is now present
+ BOOST_CHECK(cache.get("a") == boost::none);
+ BOOST_CHECK(cache.get("b") != boost::none);
+ BOOST_CHECK(cache.get("c") != boost::none);
+ BOOST_CHECK(cache.get("d") != boost::none);
+ BOOST_CHECK(cache.get("e") != boost::none);
+
+ // clear cache and ensure no program objects are found
+ cache.clear();
+ BOOST_CHECK(cache.get("a") == boost::none);
+ BOOST_CHECK(cache.get("b") == boost::none);
+ BOOST_CHECK(cache.get("c") == boost::none);
+ BOOST_CHECK(cache.get("d") == boost::none);
+ BOOST_CHECK(cache.get("e") == boost::none);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_radix_sort.cpp b/src/boost/libs/compute/test/test_radix_sort.cpp
new file mode 100644
index 00000000..d43deae2
--- /dev/null
+++ b/src/boost/libs/compute/test/test_radix_sort.cpp
@@ -0,0 +1,543 @@
+//---------------------------------------------------------------------------//
+// 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 TestRadixSort
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/detail/radix_sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+const bool descending = false;
+
+BOOST_AUTO_TEST_CASE(sort_char_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all radix_sort tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ using boost::compute::char_;
+
+ char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
+ boost::compute::vector<char_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(char_, 8, vector, ('\0', '$', '0', '7', 'B', 'F', 'a', 'c'));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uchar_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::uchar_;
+
+ uchar_ data[] = { 0x12, 0x00, 0xFF, 0xB4, 0x80, 0x32, 0x64, 0xA2 };
+ boost::compute::vector<uchar_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uchar_, 8, vector, (0x00, 0x12, 0x32, 0x64, 0x80, 0xA2, 0xB4, 0xFF));
+}
+
+BOOST_AUTO_TEST_CASE(sort_short_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::short_;
+
+ short_ data[] = { -4, 152, -94, 963, 31002, -456, 0, -2113 };
+ boost::compute::vector<short_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(short_, 8, vector, (-2113, -456, -94, -4, 0, 152, 963, 31002));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ushort_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::ushort_;
+
+ ushort_ data[] = { 4, 152, 94, 963, 63202, 34560, 0, 2113 };
+ boost::compute::vector<ushort_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ushort_, 8, vector, (0, 4, 94, 152, 963, 2113, 34560, 63202));
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(int, 8, vector, (-5000, -456, -4, 0, 152, 963, 1112, 75321));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uint_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::uint_;
+
+ uint_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<uint_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uint_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_long_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::long_;
+
+ long_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<long_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(long_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ulong_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::ulong_;
+
+ ulong_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<ulong_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ulong_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ float data[] = { -6023.0f, 152.5f, -63.0f, 1234567.0f, 11.2f,
+ -5000.1f, 0.0f, 14.0f, -8.25f, -0.0f };
+ boost::compute::vector<float> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (-6023.0f, -5000.1f, -63.0f, -8.25f, -0.0f, 0.0f, 11.2f, 14.0f, 152.5f, 1234567.0f)
+ );
+
+ // copy data, sort, and check again (to check program caching)
+ boost::compute::copy(data, data + 10, vector.begin(), queue);
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (-6023.0f, -5000.1f, -63.0f, -8.25f, -0.0f, 0.0f, 11.2f, 14.0f, 152.5f, 1234567.0f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_double_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ if(!device.supports_extension("cl_khr_fp64")){
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ double data[] = { -6023.0, 152.5, -63.0, 1234567.0, 11.2,
+ -5000.1, 0.0, 14.0, -8.25, -0.0 };
+ boost::compute::vector<double> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::detail::radix_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ double, 10, vector,
+ (-6023.0, -5000.1, -63.0, -8.25, -0.0, 0.0, 11.2, 14.0, 152.5, 1234567.0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_char_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::char_;
+
+ char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
+ boost::compute::vector<char_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<char_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<char_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ char_, 8, vector,
+ ('c', 'a', 'F', 'B', '7', '0', '$', '\0')
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_uchar_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::uchar_;
+
+ uchar_ data[] = { 0x12, 0x00, 0xFF, 0xB4, 0x80, 0x32, 0x64, 0xA2 };
+ boost::compute::vector<uchar_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<uchar_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<uchar_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ uchar_, 8, vector,
+ (0xFF, 0xB4, 0xA2, 0x80, 0x64, 0x32, 0x12, 0x00)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_short_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::short_;
+
+ short_ data[] = { -4, 152, -94, 963, 31002, -456, 0, -2113 };
+ boost::compute::vector<short_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<short_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<short_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ short_, 8, vector,
+ (31002, 963, 152, 0, -4, -94, -456, -2113)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_ushort_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::ushort_;
+
+ ushort_ data[] = { 4, 152, 94, 963, 63202, 34560, 0, 2113 };
+ boost::compute::vector<ushort_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<ushort_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<ushort_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ ushort_, 8, vector,
+ (63202, 34560, 2113, 963, 152, 94, 4, 0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::int_;
+
+ int_ data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ boost::compute::vector<int_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<int_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<int_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ int_, 8, vector,
+ (75321, 1112, 963, 152, 0, -4, -456, -5000)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_uint_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::uint_;
+
+ uint_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<uint_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<uint_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<uint_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ uint_, 8, vector,
+ (4000000, 123456, 102030, 9852, 1988, 562, 500, 0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_long_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::long_;
+
+ long_ data[] = { -500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<long_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<long_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<long_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ long_, 8, vector,
+ (4000000, 123456, 102030, 9852, 1988, 562, 0, -500)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_ulong_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ using boost::compute::ulong_;
+
+ ulong_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<ulong_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<ulong_>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<ulong_>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ ulong_, 8, vector,
+ (4000000, 123456, 102030, 9852, 1988, 562, 500, 0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ float data[] = {
+ -6023.0f, 152.5f, -63.0f, 1234567.0f, 11.2f,
+ -5000.1f, 0.0f, 14.0f, -8.25f, -0.0f
+ };
+
+ boost::compute::vector<float> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<float>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<float>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (1234567.0f, 152.5f, 14.0f, 11.2f, 0.0f, -0.0f, -8.25f, -63.0f, -5000.1f, -6023.0f)
+ );
+
+ // copy data, sort, and check again (to check program caching)
+ boost::compute::copy(data, data + 10, vector.begin(), queue);
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<float>(), queue
+ ));
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (1234567.0f, 152.5f, 14.0f, 11.2f, 0.0f, -0.0f, -8.25f, -63.0f, -5000.1f, -6023.0f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_double_vector_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ if(!device.supports_extension("cl_khr_fp64")){
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ double data[] = {
+ -6023.0, 152.5, -63.0, 1234567.0, 11.2, -5000.1, 0.0, 14.0, -8.25, -0.0
+ };
+
+ boost::compute::vector<double> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+
+ BOOST_CHECK(!boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<double>(), queue
+ ));
+ boost::compute::detail::radix_sort(
+ vector.begin(), vector.end(), descending, queue
+ );
+ BOOST_CHECK(boost::compute::is_sorted(
+ vector.begin(), vector.end(), boost::compute::greater<double>(), queue
+ ));
+
+ CHECK_RANGE_EQUAL(
+ double, 10, vector,
+ (1234567.0, 152.5, 14.0, 11.2, 0.0, -0.0, -8.25, -63.0, -5000.1, -6023.0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_partial_vector)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ int data[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+ boost::compute::vector<int> vec(data, data + 10, queue);
+
+ boost::compute::detail::radix_sort(vec.begin() + 2, vec.end() - 2, queue);
+ CHECK_RANGE_EQUAL(int, 10, vec, (9, 8, 2, 3, 4, 5, 6, 7, 1, 0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_radix_sort_by_key.cpp b/src/boost/libs/compute/test/test_radix_sort_by_key.cpp
new file mode 100644
index 00000000..cc86d4ba
--- /dev/null
+++ b/src/boost/libs/compute/test/test_radix_sort_by_key.cpp
@@ -0,0 +1,311 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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 TestRadixSortByKey
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/detail/radix_sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+const bool descending = false;
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_int)
+{
+ if(is_apple_cpu_device(device)) {
+ std::cerr
+ << "skipping all radix_sort_by_key tests due to Apple platform"
+ << " behavior when local memory is used on a CPU device"
+ << std::endl;
+ return;
+ }
+
+ compute::int_ keys_data[] = { 10, 9, 2, 7, 6, -1, 4, 2, 2, 10 };
+ compute::int_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::int_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, keys,
+ (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
+ // ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, values,
+ // (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
+ ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
+ );
+}
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_int_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::int_ keys_data[] = { 10, 9, 2, 7, 6, -1, 4, 2, 2, 10 };
+ compute::int_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::int_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(
+ !compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::int_>(), queue
+ )
+ );
+ compute::detail::radix_sort_by_key(
+ keys.begin(), keys.end(), values.begin(), descending, queue
+ );
+ BOOST_CHECK(
+ compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::int_>(), queue
+ )
+ );
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, keys,
+ (10, 10, 9, 7, 6, 4, 2, 2, 2, -1) // keys
+ // ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, values,
+ // (10, 10, 9, 7, 6, 4, 2, 2, 2, -1) // keys
+ ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) // values
+ );
+}
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_uint_by_uint)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::uint_ keys_data[] = { 10, 9, 2, 7, 6, 1, 4, 2, 2, 10 };
+ compute::uint_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::uint_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, keys,
+ (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
+ // (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, values,
+ // (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
+ (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
+ );
+}
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_uint_by_uint_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::uint_ keys_data[] = { 10, 9, 2, 7, 6, 1, 4, 2, 2, 10 };
+ compute::uint_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::uint_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(
+ !compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::uint_>(), queue
+ )
+ );
+ compute::detail::radix_sort_by_key(
+ keys.begin(), keys.end(), values.begin(), descending, queue
+ );
+ BOOST_CHECK(
+ compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::uint_>(), queue
+ )
+ );
+
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, keys,
+ (10, 10, 9, 7, 6, 4, 2, 2, 2, 1) // keys
+ // ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, values,
+ // (10, 10, 9, 7, 6, 4, 2, 2, 2, 1) // keys
+ ( 1, 10, 2, 4, 5, 7, 3, 8, 9, 6) // values
+ );
+}
+
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_float)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::float_ keys_data[] = { 10., 5.5, 10., 7., 5.5};
+ compute::int_ values_data[] = { 1, 200, -10, 2, 4 };
+
+ compute::vector<compute::float_> keys(keys_data, keys_data + 5, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 5, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::float_, 5, keys,
+ (5.5, 5.5, 7., 10., 10.) // keys
+ // (200, 4, 2, 1, -10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 5, values,
+ // (5.5, 5.5, 7., 10., 10.) keys
+ (200, 4, 2, 1, -10) // values
+ );
+}
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_int_by_float_desc)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::float_ keys_data[] = { 10., 5.5, 10., 7., 5.5};
+ compute::int_ values_data[] = { 1, 200, -10, 2, 4 };
+
+ compute::vector<compute::float_> keys(keys_data, keys_data + 5, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 5, queue);
+
+ BOOST_CHECK(
+ !compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::float_>(), queue
+ )
+ );
+ compute::detail::radix_sort_by_key(
+ keys.begin(), keys.end(), values.begin(), descending, queue
+ );
+ BOOST_CHECK(
+ compute::is_sorted(
+ keys.begin(), keys.end(), compute::greater<compute::float_>(), queue
+ )
+ );
+
+ CHECK_RANGE_EQUAL(
+ compute::float_, 5, keys,
+ (10., 10., 7., 5.5, 5.5) // keys
+ // ( 1, -10, 2, 200, 4) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 5, values,
+ // (10., 10., 7., 5.5, 5.5) // keys
+ ( 1, -10, 2, 200, 4) // values
+ );
+}
+
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_char_by_int)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::int_ keys_data[] = { 6, 1, 1, 3, 4, 7, 5, 1 };
+ compute::char_ values_data[] = { 'g', 'c', 'b', 'd', 'e', 'h', 'f', 'a' };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 8, queue);
+ compute::vector<compute::char_> values(values_data, values_data + 8, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 8, keys,
+ (1, 1, 1, 3, 4, 5, 6, 7)
+ );
+ CHECK_RANGE_EQUAL(
+ compute::char_, 8, values,
+ ('c', 'b', 'a', 'd', 'e', 'f', 'g', 'h')
+ );
+}
+
+// radix_sort_by_key should be stable
+BOOST_AUTO_TEST_CASE(stable_radix_sort_int2_by_int)
+{
+ if(is_apple_cpu_device(device)) {
+ return;
+ }
+
+ compute::int_ keys_data[] = { 6, 1, 1, 3, 4, 7, 5, 1 };
+ compute::int2_ values_data[] = {
+ compute::int2_(1, 1), // 6
+ compute::int2_(1, 2), // 1
+ compute::int2_(1, 3), // 1
+ compute::int2_(1, 4), // 3
+ compute::int2_(1, 5), // 4
+ compute::int2_(1, 6), // 7
+ compute::int2_(1, 7), // 5
+ compute::int2_(1, 8) // 1
+ };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 8, queue);
+ compute::vector<compute::int2_> values(values_data, values_data + 8, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::detail::radix_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 8, keys,
+ (1, 1, 1, 3, 4, 5, 6, 7)
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int2_, 8, values,
+ (
+ compute::int2_(1, 2),
+ compute::int2_(1, 3),
+ compute::int2_(1, 8),
+ compute::int2_(1, 4),
+ compute::int2_(1, 5),
+ compute::int2_(1, 7),
+ compute::int2_(1, 1),
+ compute::int2_(1, 6)
+ )
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_random_fill.cpp b/src/boost/libs/compute/test/test_random_fill.cpp
new file mode 100644
index 00000000..8d890e7d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_random_fill.cpp
@@ -0,0 +1,76 @@
+//---------------------------------------------------------------------------//
+// 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 TestRandomFill
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/detail/random_fill.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/lambda.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(random_fill_float)
+{
+ using compute::lambda::_1;
+
+ compute::vector<float> vector(10, context);
+
+ // fill with values between 0 and 1
+ compute::detail::random_fill(
+ vector.begin(),
+ vector.end(),
+ 0.0f,
+ 1.0f,
+ queue
+ );
+
+ BOOST_CHECK_EQUAL(
+ compute::count_if(
+ vector.begin(), vector.end(), _1 < 0.0f || _1 > 1.0f, queue
+ ),
+ size_t(0)
+ );
+
+ // fill with values between 5 and 10
+ compute::detail::random_fill(
+ vector.begin(),
+ vector.end(),
+ 5.0f,
+ 10.0f,
+ queue
+ );
+
+ BOOST_CHECK_EQUAL(
+ compute::count_if(
+ vector.begin(), vector.end(), _1 < 5.0f || _1 > 10.0f, queue
+ ),
+ size_t(0)
+ );
+
+ // fill with values between -25 and 25
+ compute::detail::random_fill(
+ vector.begin(), vector.end(), -25.0f, 25.0f, queue
+ );
+
+ BOOST_CHECK_EQUAL(
+ compute::count_if(
+ vector.begin(), vector.end(), _1 < -25.0f || _1 > 25.0f, queue
+ ),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_random_shuffle.cpp b/src/boost/libs/compute/test/test_random_shuffle.cpp
new file mode 100644
index 00000000..69885aba
--- /dev/null
+++ b/src/boost/libs/compute/test/test_random_shuffle.cpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// 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 TestRandomShuffle
+#include <boost/test/unit_test.hpp>
+
+#include <set>
+#include <iterator>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/random_shuffle.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(shuffle_int_vector)
+{
+ bc::vector<int> vector(context);
+ vector.push_back(1, queue);
+ vector.push_back(9, queue);
+ vector.push_back(19, queue);
+ vector.push_back(29, queue);
+ queue.finish();
+
+ std::set<int> original_values;
+ for(size_t i = 0; i < vector.size(); i++){
+ original_values.insert(vector[i]);
+ }
+ BOOST_CHECK_EQUAL(original_values.size(), size_t(4));
+
+ bc::random_shuffle(vector.begin(), vector.end(), queue);
+
+ std::set<int> shuffled_values;
+ bc::copy(
+ vector.begin(),
+ vector.end(),
+ std::inserter(shuffled_values, shuffled_values.begin()),
+ queue
+ );
+ BOOST_CHECK_EQUAL(shuffled_values.size(), size_t(4));
+ BOOST_VERIFY(original_values == shuffled_values);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_reduce.cpp b/src/boost/libs/compute/test/test_reduce.cpp
new file mode 100644
index 00000000..c3855061
--- /dev/null
+++ b/src/boost/libs/compute/test/test_reduce.cpp
@@ -0,0 +1,298 @@
+//---------------------------------------------------------------------------//
+// 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 TestReduce
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/types/complex.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(reduce_int)
+{
+ int data[] = { 1, 5, 9, 13, 17 };
+ compute::vector<int> vector(data, data + 5, queue);
+ int sum;
+ compute::reduce(vector.begin(), vector.end(), &sum, compute::plus<int>(), queue);
+ BOOST_CHECK_EQUAL(sum, 45);
+
+ int product;
+ compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<int>(), queue);
+ BOOST_CHECK_EQUAL(product, 9945);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_empty_vector)
+{
+ compute::vector<short> vector(context);
+
+ short sum = 0;
+ compute::reduce(vector.begin(), vector.end(), &sum, queue);
+ BOOST_CHECK_EQUAL(sum, short(0));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_doctest)
+{
+ int data[] = { 1, 2, 3, 4 };
+ boost::compute::vector<int> vec(data, data + 4, queue);
+
+//! [sum_int]
+int sum = 0;
+boost::compute::reduce(vec.begin(), vec.end(), &sum, queue);
+//! [sum_int]
+
+ BOOST_CHECK_EQUAL(sum, 10);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_twos)
+{
+ using compute::uint_;
+
+ compute::vector<uint_> vector(8, context);
+ compute::fill(vector.begin(), vector.end(), uint_(2), queue);
+
+ uint_ sum;
+ compute::reduce(vector.begin(), vector.end(), &sum, compute::plus<uint_>(), queue);
+ BOOST_CHECK_EQUAL(sum, uint_(16));
+
+ uint_ product;
+ compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<uint_>(), queue);
+ BOOST_CHECK_EQUAL(product, uint_(256));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_on_device)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> input(data, data + 8, queue);
+ compute::vector<int> result(2, context);
+ compute::reduce(input.begin(), input.begin() + 4, result.begin(), queue);
+ compute::reduce(input.begin() + 4, input.end(), result.end() - 1, queue);
+ CHECK_RANGE_EQUAL(int, 2, result, (10, 26));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_int_min_max)
+{
+ int data[] = { 11, 5, 92, 13, 42 };
+ compute::vector<int> vector(data, data + 5, queue);
+ int min_value;
+ compute::reduce(
+ vector.begin(),
+ vector.end(),
+ &min_value,
+ compute::min<int>(),
+ queue
+ );
+ BOOST_CHECK_EQUAL(min_value, 5);
+
+ int max_value;
+ compute::reduce(
+ vector.begin(),
+ vector.end(),
+ &max_value,
+ compute::max<int>(),
+ queue
+ );
+ BOOST_CHECK_EQUAL(max_value, 92);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_int2)
+{
+ std::vector<compute::int2_> data;
+ for(int i = 0; i < 6; i++){
+ compute::int2_ value;
+ value[0] = i + 1;
+ value[1] = 2 * i + 1;
+ data.push_back(value);
+ }
+
+ compute::vector<compute::int2_> vector(data.begin(), data.end(), queue);
+
+ compute::int2_ sum;
+ compute::reduce(
+ vector.begin(),
+ vector.end(),
+ &sum,
+ queue
+ );
+ BOOST_CHECK_EQUAL(sum, compute::int2_(21, 36));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_pinned_vector)
+{
+ int data[] = { 2, 5, 8, 11, 15 };
+ std::vector<int> vector(data, data + 5);
+
+ compute::buffer buffer(context,
+ vector.size() * sizeof(int),
+ compute::buffer::read_only | compute::buffer::use_host_ptr,
+ &vector[0]);
+
+ int sum;
+ compute::reduce(
+ compute::make_buffer_iterator<int>(buffer, 0),
+ compute::make_buffer_iterator<int>(buffer, 5),
+ &sum,
+ compute::plus<int>()
+ );
+ BOOST_CHECK_EQUAL(sum, 41);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_constant_iterator)
+{
+ int result;
+ compute::reduce(
+ compute::make_constant_iterator(1, 0),
+ compute::make_constant_iterator(1, 5),
+ &result,
+ queue
+ );
+ BOOST_CHECK_EQUAL(result, 5);
+
+ compute::reduce(
+ compute::make_constant_iterator(3, 0),
+ compute::make_constant_iterator(3, 5),
+ &result,
+ queue
+ );
+ BOOST_CHECK_EQUAL(result, 15);
+
+ compute::reduce(
+ compute::make_constant_iterator(2, 0),
+ compute::make_constant_iterator(2, 5),
+ &result,
+ compute::multiplies<int>(),
+ queue
+ );
+ BOOST_CHECK_EQUAL(result, 32);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_counting_iterator)
+{
+ int result;
+ compute::reduce(
+ compute::make_counting_iterator(1),
+ compute::make_counting_iterator(10),
+ &result,
+ queue
+ );
+ BOOST_CHECK_EQUAL(result, 45);
+
+ compute::reduce(
+ compute::make_counting_iterator(1),
+ compute::make_counting_iterator(5),
+ &result,
+ compute::multiplies<int>(),
+ queue
+ );
+ BOOST_CHECK_EQUAL(result, 24);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_transform_iterator)
+{
+ using ::boost::compute::_1;
+
+ int data[] = { 1, 3, 5, 7, 9 };
+ compute::vector<int> vector(data, data + 5, queue);
+
+ int sum;
+ compute::reduce(
+ compute::make_transform_iterator(vector.begin(), _1 + 1),
+ compute::make_transform_iterator(vector.end(), _1 + 1),
+ &sum,
+ queue
+ );
+ BOOST_CHECK_EQUAL(sum, 30);
+
+ compute::reduce(
+ compute::make_transform_iterator(vector.begin(), _1 > 4),
+ compute::make_transform_iterator(vector.end(), _1 > 4),
+ &sum,
+ compute::plus<int>(),
+ queue
+ );
+ BOOST_CHECK_EQUAL(sum, 3);
+
+ compute::reduce(
+ compute::make_transform_iterator(vector.begin(), _1 * _1),
+ compute::make_transform_iterator(vector.end(), _1 * _1),
+ &sum,
+ queue
+ );
+ BOOST_CHECK_EQUAL(sum, 165);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_complex)
+{
+ std::vector<std::complex<float> > data;
+ data.push_back(std::complex<float>(1, 2));
+ data.push_back(std::complex<float>(2, 4));
+ data.push_back(std::complex<float>(3, 6));
+ data.push_back(std::complex<float>(4, 8));
+
+ compute::vector<std::complex<float> > vector(data.size(), context);
+ compute::copy(data.begin(), data.end(), vector.begin(), queue);
+
+ std::complex<float> result;
+ compute::reduce(
+ vector.begin(), vector.end(), &result, queue
+ );
+ BOOST_CHECK(result == std::complex<float>(10, 20));
+
+ compute::reduce(
+ vector.begin(), vector.end(), &result, compute::plus<std::complex<float> >(), queue
+ );
+ BOOST_CHECK(result == std::complex<float>(10, 20));
+
+ compute::reduce(
+ vector.begin(), vector.end(), &result, compute::multiplies<std::complex<float> >(), queue
+ );
+ BOOST_CHECK(result == std::complex<float>(-168, -576));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_uchar_to_float)
+{
+ compute::vector<compute::uchar_> data(context);
+ data.push_back(250, queue);
+ data.push_back(250, queue);
+ float sum = 0;
+ compute::reduce(data.begin(), data.end(), &sum, compute::plus<float>(), queue);
+ BOOST_CHECK_EQUAL(sum, 500);
+}
+
+// Test case for https://github.com/boostorg/compute/issues/746
+BOOST_AUTO_TEST_CASE(buffer_reference_count_test)
+{
+ using compute::uint_;
+
+ compute::vector<uint_> vector(8, context);
+ const compute::buffer& b = vector.get_buffer();
+ uint_ rc1 = b.get_info<CL_MEM_REFERENCE_COUNT>();
+ {
+ compute::fill(vector.begin(), vector.end(), uint_(2), queue);
+
+ uint_ product;
+ compute::reduce(vector.begin(), vector.end(), &product, compute::multiplies<uint_>(), queue);
+ BOOST_CHECK_EQUAL(product, uint_(256));
+ }
+ uint_ rc2 = b.get_info<CL_MEM_REFERENCE_COUNT>();
+ BOOST_CHECK_EQUAL(rc1, rc2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_reduce_by_key.cpp b/src/boost/libs/compute/test/test_reduce_by_key.cpp
new file mode 100644
index 00000000..df34250f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_reduce_by_key.cpp
@@ -0,0 +1,210 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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 TestReduceByKey
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/algorithm/reduce_by_key.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int)
+{
+//! [reduce_by_key_int]
+// setup keys and values
+int keys[] = { 0, 2, -3, -3, -3, -3, -3, 4 };
+int data[] = { 1, 1, 1, 1, 1, 2, 5, 1 };
+
+boost::compute::vector<int> keys_input(keys, keys + 8, queue);
+boost::compute::vector<int> values_input(data, data + 8, queue);
+
+boost::compute::vector<int> keys_output(8, context);
+boost::compute::vector<int> values_output(8, context);
+// reduce by key
+boost::compute::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+// keys_output = { 0, 2, -3, 4 }
+// values_output = { 1, 1, 10, 1 }
+//! [reduce_by_key_int]
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, -3, 4));
+ CHECK_RANGE_EQUAL(int, 4, values_output, (1, 1, 10, 1));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_long_vector)
+{
+ size_t size = 1024;
+ bc::vector<int> keys_input(size, int(0), queue);
+ bc::vector<int> values_input(size, int(1), queue);
+
+ bc::vector<int> keys_output(size, context);
+ bc::vector<int> values_output(size, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 1, keys_output, (0));
+ CHECK_RANGE_EQUAL(int, 1, values_output, (static_cast<int>(size)));
+
+ keys_input[137] = 1;
+ keys_input[677] = 1;
+ keys_input[1001] = 1;
+ bc::inclusive_scan(keys_input.begin(), keys_input.end(), keys_input.begin(), queue);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 1, 2, 3));
+ CHECK_RANGE_EQUAL(int, 4, values_output, (137, 540, 324, 23));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_empty_vector)
+{
+ bc::vector<int> keys_input(context);
+ bc::vector<int> values_input(context);
+
+ bc::vector<int> keys_output(context);
+ bc::vector<int> values_output(context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ BOOST_CHECK(keys_output.empty());
+ BOOST_CHECK(values_output.empty());
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_one_key_value)
+{
+ int keys[] = { 22 };
+ int data[] = { -9 };
+
+ bc::vector<int> keys_input(keys, keys + 1, queue);
+ bc::vector<int> values_input(data, data + 1, queue);
+
+ bc::vector<int> keys_output(1, context);
+ bc::vector<int> values_output(1, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 1, keys_output, (22));
+ CHECK_RANGE_EQUAL(int, 1, values_output, (-9));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_min_max)
+{
+ int keys[] = { 0, 2, 2, 3, 3, 3, 3, 3, 4 };
+ int data[] = { 1, 2, 1, -3, 1, 4, 2, 5, 77 };
+
+ bc::vector<int> keys_input(keys, keys + 9, queue);
+ bc::vector<int> values_input(data, data + 9, queue);
+
+ bc::vector<int> keys_output(9, context);
+ bc::vector<int> values_output(9, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), bc::min<int>(),
+ bc::equal_to<int>(), queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+ CHECK_RANGE_EQUAL(int, 4, values_output, (1, 1, -3, 77));
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), bc::max<int>(),
+ bc::equal_to<int>(), queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+ CHECK_RANGE_EQUAL(int, 4, values_output, (1, 2, 5, 77));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_float_max)
+{
+ int keys[] = { 0, 2, 2, 3, 3, 3, 3, 3, 4 };
+ float data[] = { 1.0, 2.0, -1.5, -3.0, 1.0, -0.24, 2, 5, 77.1 };
+
+ bc::vector<int> keys_input(keys, keys + 9, queue);
+ bc::vector<float> values_input(data, data + 9, queue);
+
+ bc::vector<int> keys_output(9, context);
+ bc::vector<float> values_output(9, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), bc::max<float>(),
+ queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+ BOOST_CHECK_CLOSE(float(values_output[0]), 1.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(values_output[1]), 2.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(values_output[2]), 5.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(values_output[3]), 77.1f, 1e-4f);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int2)
+{
+ using bc::int2_;
+
+ int keys[] = { 0, 2, 3, 3, 3, 3, 4, 4 };
+ int2_ data[] = {
+ int2_(0, 1), int2_(-3, 2), int2_(0, 1), int2_(0, 1),
+ int2_(-3, 0), int2_(0, 0), int2_(-3, 2), int2_(-7, -2)
+ };
+
+ bc::vector<int> keys_input(keys, keys + 8, queue);
+ bc::vector<int2_> values_input(data, data + 8, queue);
+
+ bc::vector<int> keys_output(8, context);
+ bc::vector<int2_> values_output(8, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+ CHECK_RANGE_EQUAL(int2_, 4, values_output,
+ (int2_(0, 1), int2_(-3, 2), int2_(-3, 2), int2_(-10, 0)));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int2_long_vector)
+{
+ using bc::int2_;
+
+ size_t size = 1024;
+ bc::vector<int> keys_input(size, int(0), queue);
+ bc::vector<int2_> values_input(size, int2_(1, -1), queue);
+
+ bc::vector<int> keys_output(size, context);
+ bc::vector<int2_> values_output(size, context);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 1, keys_output, (0));
+ CHECK_RANGE_EQUAL(int2_, 1, values_output, (int2_(int(size), -int(size))));
+
+ keys_input[137] = 1;
+ keys_input[677] = 1;
+ keys_input[1001] = 1;
+ bc::inclusive_scan(keys_input.begin(), keys_input.end(), keys_input.begin(), queue);
+
+ bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+ keys_output.begin(), values_output.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 1, 2, 3));
+ CHECK_RANGE_EQUAL(int2_, 4, values_output,
+ (int2_(137, -137), int2_(540, -540), int2_(324, -324), int2_(23, -23)));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_remove.cpp b/src/boost/libs/compute/test/test_remove.cpp
new file mode 100644
index 00000000..5cb980bd
--- /dev/null
+++ b/src/boost/libs/compute/test/test_remove.cpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// 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 TestRemove
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/remove.hpp>
+#include <boost/compute/algorithm/remove_if.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(remove_int)
+{
+ int data[] = { 1, 2, 1, 3, 2, 4, 3, 4, 5 };
+ bc::vector<int> vector(data, data + 9, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(9));
+
+ // remove 2's
+ bc::vector<int>::const_iterator iter =
+ bc::remove(vector.begin(), vector.end(), 2, queue);
+ BOOST_VERIFY(iter == vector.begin() + 7);
+ CHECK_RANGE_EQUAL(int, 7, vector, (1, 1, 3, 4, 3, 4, 5));
+
+ // remove 4's
+ iter = bc::remove(vector.begin(), vector.begin() + 7, 4, queue);
+ BOOST_VERIFY(iter == vector.begin() + 5);
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 1, 3, 3, 5));
+
+ // remove 1's
+ iter = bc::remove(vector.begin(), vector.begin() + 5, 1, queue);
+ BOOST_VERIFY(iter == vector.begin() + 3);
+ CHECK_RANGE_EQUAL(int, 3, vector, (3, 3, 5));
+
+ // remove 5's
+ iter = bc::remove(vector.begin(), vector.begin() + 3, 5, queue);
+ BOOST_VERIFY(iter == vector.begin() + 2);
+ CHECK_RANGE_EQUAL(int, 2, vector, (3, 3));
+
+ // remove 3's
+ iter = bc::remove(vector.begin(), vector.begin() + 2, 3, queue);
+ BOOST_VERIFY(iter == vector.begin());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_replace.cpp b/src/boost/libs/compute/test/test_replace.cpp
new file mode 100644
index 00000000..6ce5ffd6
--- /dev/null
+++ b/src/boost/libs/compute/test/test_replace.cpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// 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 TestReplace
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/replace.hpp>
+#include <boost/compute/algorithm/replace_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(replace_int)
+{
+ bc::vector<int> vector(5, context);
+ bc::iota(vector.begin(), vector.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (0, 1, 2, 3, 4));
+
+ bc::replace(vector.begin(), vector.end(), 2, 6, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (0, 1, 6, 3, 4));
+}
+
+BOOST_AUTO_TEST_CASE(replace_copy_int)
+{
+ bc::vector<int> a(5, context);
+ bc::iota(a.begin(), a.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 5, a, (0, 1, 2, 3, 4));
+
+ bc::vector<int> b(5, context);
+ bc::vector<int>::iterator iter =
+ bc::replace_copy(a.begin(), a.end(), b.begin(), 3, 9, queue);
+ BOOST_CHECK(iter == b.end());
+ CHECK_RANGE_EQUAL(int, 5, b, (0, 1, 2, 9, 4));
+
+ // ensure 'a' was not modified
+ CHECK_RANGE_EQUAL(int, 5, a, (0, 1, 2, 3, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_result_of.cpp b/src/boost/libs/compute/test/test_result_of.cpp
new file mode 100644
index 00000000..e964c4de
--- /dev/null
+++ b/src/boost/libs/compute/test/test_result_of.cpp
@@ -0,0 +1,40 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestResultOf
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/functional/operator.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+BOOST_AUTO_TEST_CASE(result_of_function)
+{
+ using boost::compute::function;
+ using boost::compute::result_of;
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<result_of<function<int()>()>::type, int>::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(result_of_operators)
+{
+ using boost::compute::plus;
+ using boost::compute::minus;
+ using boost::compute::result_of;
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<result_of<plus<int>(int, int)>::type, int>::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<result_of<minus<int>(int, int)>::type, int>::value
+ ));
+}
diff --git a/src/boost/libs/compute/test/test_reverse.cpp b/src/boost/libs/compute/test/test_reverse.cpp
new file mode 100644
index 00000000..03ffe639
--- /dev/null
+++ b/src/boost/libs/compute/test/test_reverse.cpp
@@ -0,0 +1,93 @@
+//---------------------------------------------------------------------------//
+// 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 TestReverse
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/algorithm/reverse_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(reverse_int)
+{
+ bc::vector<int> vector(5, context);
+ bc::iota(vector.begin(), vector.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (0, 1, 2, 3, 4));
+
+ bc::reverse(vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (4, 3, 2, 1, 0));
+
+ bc::reverse(vector.begin() + 1, vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (4, 0, 1, 2, 3));
+
+ bc::reverse(vector.begin() + 1, vector.end() - 1, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (4, 2, 1, 0, 3));
+
+ bc::reverse(vector.begin(), vector.end() - 2, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 4, 0, 3));
+
+ vector.resize(6, queue);
+ bc::iota(vector.begin(), vector.end(), 10, queue);
+ CHECK_RANGE_EQUAL(int, 6, vector, (10, 11, 12, 13, 14, 15));
+
+ bc::reverse(vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 6, vector, (15, 14, 13, 12, 11, 10));
+
+ bc::reverse(vector.begin() + 3, vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 6, vector, (15, 14, 13, 10, 11, 12));
+
+ bc::reverse(vector.begin() + 1, vector.end() - 2, queue);
+ CHECK_RANGE_EQUAL(int, 6, vector, (15, 10, 13, 14, 11, 12));
+}
+
+BOOST_AUTO_TEST_CASE(reverse_copy_int)
+{
+ bc::vector<int> a(5, context);
+ bc::iota(a.begin(), a.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 5, a, (0, 1, 2, 3, 4));
+
+ bc::vector<int> b(5, context);
+ bc::vector<int>::iterator iter =
+ bc::reverse_copy(a.begin(), a.end(), b.begin(), queue);
+ BOOST_CHECK(iter == b.end());
+ CHECK_RANGE_EQUAL(int, 5, b, (4, 3, 2, 1, 0));
+
+ iter = bc::reverse_copy(b.begin() + 1, b.end(), a.begin() + 1, queue);
+ BOOST_CHECK(iter == a.end());
+ CHECK_RANGE_EQUAL(int, 5, a, (0, 0, 1, 2, 3));
+
+ iter = bc::reverse_copy(a.begin(), a.end() - 1, b.begin(), queue);
+ BOOST_CHECK(iter == (b.end() - 1));
+ CHECK_RANGE_EQUAL(int, 5, b, (2, 1, 0, 0, 0));
+}
+
+BOOST_AUTO_TEST_CASE(reverse_copy_counting_iterator)
+{
+ bc::vector<int> vector(5, context);
+ bc::reverse_copy(
+ bc::make_counting_iterator(1),
+ bc::make_counting_iterator(6),
+ vector.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, vector, (5, 4, 3, 2, 1));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_rotate.cpp b/src/boost/libs/compute/test/test_rotate.cpp
new file mode 100644
index 00000000..cedec5d0
--- /dev/null
+++ b/src/boost/libs/compute/test/test_rotate.cpp
@@ -0,0 +1,69 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestRotate
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/rotate.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(rotate_trivial)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate(vector.begin(), vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (1, 4, 2, 6, 3, 2, 5, 3, 4, 6));
+
+ boost::compute::rotate(vector.begin(), vector.end(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (1, 4, 2, 6, 3, 2, 5, 3, 4, 6));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_1)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate(vector.begin(), vector.begin()+1, vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (4, 2, 6, 3, 2, 5, 3, 4, 6, 1));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_4)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate(vector.begin(), vector.begin()+4, vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (3, 2, 5, 3, 4, 6, 1, 4, 2, 6));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_9)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate(vector.begin(), vector.begin()+9, vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (6, 1, 4, 2, 6, 3, 2, 5, 3, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_rotate_copy.cpp b/src/boost/libs/compute/test/test_rotate_copy.cpp
new file mode 100644
index 00000000..14f67d7f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_rotate_copy.cpp
@@ -0,0 +1,73 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestRotateCopy
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/rotate_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(rotate_copy_trivial)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+ boost::compute::vector<int> result(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate_copy(vector.begin(), vector.begin(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 10, result, (1, 4, 2, 6, 3, 2, 5, 3, 4, 6));
+
+ boost::compute::rotate_copy(vector.begin(), vector.end(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 10, result, (1, 4, 2, 6, 3, 2, 5, 3, 4, 6));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_copy_1)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+ boost::compute::vector<int> result(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate_copy(vector.begin(), vector.begin()+1, vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 10, result, (4, 2, 6, 3, 2, 5, 3, 4, 6, 1));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_copy_4)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+ boost::compute::vector<int> result(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate_copy(vector.begin(), vector.begin()+4, vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 10, result, (3, 2, 5, 3, 4, 6, 1, 4, 2, 6));
+}
+
+BOOST_AUTO_TEST_CASE(rotate_copy_9)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 5, 3, 4, 6};
+ boost::compute::vector<int> vector(10, context);
+ boost::compute::vector<int> result(10, context);
+
+ boost::compute::copy_n(data, 10, vector.begin(), queue);
+
+ boost::compute::rotate_copy(vector.begin(), vector.begin()+9, vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 10, result, (6, 1, 4, 2, 6, 3, 2, 5, 3, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_scan.cpp b/src/boost/libs/compute/test/test_scan.cpp
new file mode 100644
index 00000000..1504ea06
--- /dev/null
+++ b/src/boost/libs/compute/test/test_scan.cpp
@@ -0,0 +1,490 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+// Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
+// parameters for copy algorithm without any undesirable consequences (like
+// saving modified values of those parameters).
+#ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
+ #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
+#endif
+
+#define BOOST_TEST_MODULE TestScan
+#include <boost/test/unit_test.hpp>
+
+#include <numeric>
+#include <functional>
+#include <vector>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_int)
+{
+ using boost::compute::uint_;
+ using boost::compute::int_;
+
+ int_ data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ bc::vector<int_> vector(data, data + 12, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(12));
+
+ bc::vector<int_> result(12, context);
+ BOOST_CHECK_EQUAL(result.size(), size_t(12));
+
+ // inclusive scan
+ bc::inclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
+
+ // in-place inclusive scan
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
+
+ // scan_on_cpu
+
+ bc::copy(data, data + 12, vector.begin(), queue);
+
+ // make sure parallel scan_on_cpu is used, no serial_scan
+ std::string cache_key =
+ "__boost_scan_cpu_4";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_scan_threshold", 0);
+ // force parallel scan_on_cpu
+ parameters->set(cache_key, "serial_scan_threshold", 0);
+
+ // inclusive scan
+ bc::inclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
+
+ // in-place inclusive scan
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
+
+ // restore
+ parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_int)
+{
+ using boost::compute::uint_;
+ using boost::compute::int_;
+
+ int_ data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ bc::vector<int_> vector(data, data + 12, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(12));
+
+ bc::vector<int_> result(size_t(12), int_(0), queue);
+ BOOST_CHECK_EQUAL(result.size(), size_t(12));
+
+ // exclusive scan
+ bc::exclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, result, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // in-place exclusive scan
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // scan_on_cpu
+ bc::copy(data, data + 12, vector.begin(), queue);
+
+ // make sure parallel scan_on_cpu is used, no serial_scan
+ std::string cache_key =
+ "__boost_scan_cpu_4";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_scan_threshold", 0);
+ // force parallel scan_on_cpu
+ parameters->set(cache_key, "serial_scan_threshold", 0);
+
+ // exclusive scan
+ bc::exclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, result, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // in-place exclusive scan
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 12, vector, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // restore
+ parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_int2)
+{
+ using boost::compute::int_;
+ using boost::compute::uint_;
+ using boost::compute::int2_;
+
+ int_ data[] = { 1, 2,
+ 3, 4,
+ 5, 6,
+ 7, 8,
+ 9, 0 };
+
+ boost::compute::vector<int2_> input(reinterpret_cast<int2_*>(data),
+ reinterpret_cast<int2_*>(data) + 5,
+ queue);
+ BOOST_CHECK_EQUAL(input.size(), size_t(5));
+
+ boost::compute::vector<int2_> output(5, context);
+ boost::compute::inclusive_scan(input.begin(), input.end(), output.begin(),
+ queue);
+ CHECK_RANGE_EQUAL(
+ int2_, 5, output,
+ (int2_(1, 2), int2_(4, 6), int2_(9, 12), int2_(16, 20), int2_(25, 20))
+ );
+
+ // scan_on_cpu
+
+ // make sure parallel scan_on_cpu is used, no serial_scan
+ std::string cache_key =
+ "__boost_scan_cpu_8";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_scan_threshold", 0);
+ // force parallel scan_on_cpu
+ parameters->set(cache_key, "serial_scan_threshold", 0);
+
+ boost::compute::inclusive_scan(input.begin(), input.end(), output.begin(),
+ queue);
+ CHECK_RANGE_EQUAL(
+ int2_, 5, output,
+ (int2_(1, 2), int2_(4, 6), int2_(9, 12), int2_(16, 20), int2_(25, 20))
+ );
+
+ // restore
+ parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_counting_iterator)
+{
+ using boost::compute::int_;
+ using boost::compute::uint_;
+
+ bc::vector<int_> result(10, context);
+ bc::inclusive_scan(bc::make_counting_iterator(1),
+ bc::make_counting_iterator(11),
+ result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 10, result, (1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // scan_on_cpu
+
+ // make sure parallel scan_on_cpu is used, no serial_scan
+ std::string cache_key =
+ "__boost_scan_cpu_4";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_scan_threshold", 0);
+ // force parallel scan_on_cpu
+ parameters->set(cache_key, "serial_scan_threshold", 0);
+
+ bc::inclusive_scan(bc::make_counting_iterator(1),
+ bc::make_counting_iterator(11),
+ result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 10, result, (1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
+
+ // restore
+ parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_counting_iterator)
+{
+ using boost::compute::int_;
+ using boost::compute::uint_;
+
+ bc::vector<int_> result(10, context);
+ bc::exclusive_scan(bc::make_counting_iterator(1),
+ bc::make_counting_iterator(11),
+ result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 10, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45));
+
+ // scan_on_cpu
+
+ // make sure parallel scan_on_cpu is used, no serial_scan
+ std::string cache_key =
+ "__boost_scan_cpu_4";
+ boost::shared_ptr<bc::detail::parameter_cache> parameters =
+ bc::detail::parameter_cache::get_global_cache(device);
+
+ // save
+ uint_ map_copy_threshold =
+ parameters->get(cache_key, "serial_scan_threshold", 0);
+ // force parallel scan_on_cpu
+ parameters->set(cache_key, "serial_scan_threshold", 0);
+
+ bc::exclusive_scan(bc::make_counting_iterator(1),
+ bc::make_counting_iterator(11),
+ result.begin(), queue);
+ CHECK_RANGE_EQUAL(int_, 10, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45));
+
+ // restore
+ parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_transform_iterator)
+{
+ float data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
+ bc::vector<float> input(data, data + 5, queue);
+ bc::vector<float> output(5, context);
+
+ // normal inclusive scan of the input
+ bc::inclusive_scan(input.begin(), input.end(), output.begin(), queue);
+ queue.finish();
+ BOOST_CHECK_CLOSE(float(output[0]), 1.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[1]), 3.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[2]), 6.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[3]), 10.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[4]), 15.0f, 1e-4f);
+
+ // inclusive scan of squares of the input
+ using ::boost::compute::_1;
+
+ bc::inclusive_scan(bc::make_transform_iterator(input.begin(), pown(_1, 2)),
+ bc::make_transform_iterator(input.end(), pown(_1, 2)),
+ output.begin(), queue);
+ queue.finish();
+ BOOST_CHECK_CLOSE(float(output[0]), 1.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[1]), 5.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[2]), 14.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[3]), 30.0f, 1e-4f);
+ BOOST_CHECK_CLOSE(float(output[4]), 55.0f, 1e-4f);
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_doctest)
+{
+//! [inclusive_scan_int]
+// setup input
+int data[] = { 1, 2, 3, 4 };
+boost::compute::vector<int> input(data, data + 4, queue);
+
+// setup output
+boost::compute::vector<int> output(4, context);
+
+// scan values
+boost::compute::inclusive_scan(
+ input.begin(), input.end(), output.begin(), queue
+);
+
+// output = [ 1, 3, 6, 10 ]
+//! [inclusive_scan_int]
+
+ CHECK_RANGE_EQUAL(int, 4, output, (1, 3, 6, 10));
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_doctest)
+{
+//! [exclusive_scan_int]
+// setup input
+int data[] = { 1, 2, 3, 4 };
+boost::compute::vector<int> input(data, data + 4, queue);
+
+// setup output
+boost::compute::vector<int> output(4, context);
+
+// scan values
+boost::compute::exclusive_scan(
+ input.begin(), input.end(), output.begin(), queue
+);
+
+// output = [ 0, 1, 3, 6 ]
+//! [exclusive_scan_int]
+
+ CHECK_RANGE_EQUAL(int, 4, output, (0, 1, 3, 6));
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_int_multiplies)
+{
+//! [inclusive_scan_int_multiplies]
+// setup input
+int data[] = { 1, 2, 1, 2, 3 };
+boost::compute::vector<int> input(data, data + 5, queue);
+
+// setup output
+boost::compute::vector<int> output(5, context);
+
+// inclusive scan with multiplication
+boost::compute::inclusive_scan(
+ input.begin(), input.end(), output.begin(),
+ boost::compute::multiplies<int>(), queue
+);
+
+// output = [1, 2, 2, 4, 12]
+//! [inclusive_scan_int_multiplies]
+
+ BOOST_CHECK_EQUAL(input.size(), size_t(5));
+ BOOST_CHECK_EQUAL(output.size(), size_t(5));
+
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 2, 2, 4, 12));
+
+ // in-place inclusive scan
+ CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 1, 2, 3));
+ boost::compute::inclusive_scan(input.begin(), input.end(), input.begin(),
+ boost::compute::multiplies<int>(), queue);
+ CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 2, 4, 12));
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_int_multiplies)
+{
+//! [exclusive_scan_int_multiplies]
+// setup input
+int data[] = { 1, 2, 1, 2, 3 };
+boost::compute::vector<int> input(data, data + 5, queue);
+
+// setup output
+boost::compute::vector<int> output(5, context);
+
+// exclusive_scan with multiplication
+// initial value equals 10
+boost::compute::exclusive_scan(
+ input.begin(), input.end(), output.begin(),
+ int(10), boost::compute::multiplies<int>(), queue
+);
+
+// output = [10, 10, 20, 20, 40]
+//! [exclusive_scan_int_multiplies]
+
+ BOOST_CHECK_EQUAL(input.size(), size_t(5));
+ BOOST_CHECK_EQUAL(output.size(), size_t(5));
+
+ CHECK_RANGE_EQUAL(int, 5, output, (10, 10, 20, 20, 40));
+
+ // in-place exclusive scan
+ CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 1, 2, 3));
+ bc::exclusive_scan(input.begin(), input.end(), input.begin(),
+ int(10), bc::multiplies<int>(), queue);
+ CHECK_RANGE_EQUAL(int, 5, input, (10, 10, 20, 20, 40));
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_int_multiplies_long_vector)
+{
+ size_t size = 1000;
+ bc::vector<int> device_vector(size, int(2), queue);
+ BOOST_CHECK_EQUAL(device_vector.size(), size);
+ bc::inclusive_scan(device_vector.begin(), device_vector.end(),
+ device_vector.begin(), bc::multiplies<int>(), queue);
+
+ std::vector<int> host_vector(size, 2);
+ BOOST_CHECK_EQUAL(host_vector.size(), size);
+ bc::copy(device_vector.begin(), device_vector.end(),
+ host_vector.begin(), queue);
+
+ std::vector<int> test(size, 2);
+ BOOST_CHECK_EQUAL(test.size(), size);
+ std::partial_sum(test.begin(), test.end(),
+ test.begin(), std::multiplies<int>());
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(host_vector.begin(), host_vector.end(),
+ test.begin(), test.end());
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_int_multiplies_long_vector)
+{
+ size_t size = 1000;
+ bc::vector<int> device_vector(size, int(2), queue);
+ BOOST_CHECK_EQUAL(device_vector.size(), size);
+ bc::exclusive_scan(device_vector.begin(), device_vector.end(),
+ device_vector.begin(), int(10), bc::multiplies<int>(),
+ queue);
+
+ std::vector<int> host_vector(size, 2);
+ BOOST_CHECK_EQUAL(host_vector.size(), size);
+ bc::copy(device_vector.begin(), device_vector.end(),
+ host_vector.begin(), queue);
+
+ std::vector<int> test(size, 2);
+ BOOST_CHECK_EQUAL(test.size(), size);
+ test[0] = 10;
+ std::partial_sum(test.begin(), test.end(),
+ test.begin(), std::multiplies<int>());
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(host_vector.begin(), host_vector.end(),
+ test.begin(), test.end());
+}
+
+BOOST_AUTO_TEST_CASE(inclusive_scan_int_custom_function)
+{
+ BOOST_COMPUTE_FUNCTION(int, multi, (int x, int y),
+ {
+ return x * y * 2;
+ });
+
+ int data[] = { 1, 2, 1, 2, 3 };
+ bc::vector<int> vector(data, data + 5, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(5));
+
+ bc::vector<int> result(5, context);
+ BOOST_CHECK_EQUAL(result.size(), size_t(5));
+
+ // inclusive scan
+ bc::inclusive_scan(vector.begin(), vector.end(), result.begin(),
+ multi, queue);
+ CHECK_RANGE_EQUAL(int, 5, result, (1, 4, 8, 32, 192));
+
+ // in-place inclusive scan
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 1, 2, 3));
+ bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(),
+ multi, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 4, 8, 32, 192));
+}
+
+BOOST_AUTO_TEST_CASE(exclusive_scan_int_custom_function)
+{
+ BOOST_COMPUTE_FUNCTION(int, multi, (int x, int y),
+ {
+ return x * y * 2;
+ });
+
+ int data[] = { 1, 2, 1, 2, 3 };
+ bc::vector<int> vector(data, data + 5, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(5));
+
+ bc::vector<int> result(5, context);
+ BOOST_CHECK_EQUAL(result.size(), size_t(5));
+
+ // exclusive_scan
+ bc::exclusive_scan(vector.begin(), vector.end(), result.begin(),
+ int(1), multi, queue);
+ CHECK_RANGE_EQUAL(int, 5, result, (1, 2, 8, 16, 64));
+
+ // in-place exclusive scan
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 1, 2, 3));
+ bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(),
+ int(1), multi, queue);
+ CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 8, 16, 64));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_scatter.cpp b/src/boost/libs/compute/test/test_scatter.cpp
new file mode 100644
index 00000000..00c74b22
--- /dev/null
+++ b/src/boost/libs/compute/test/test_scatter.cpp
@@ -0,0 +1,57 @@
+//---------------------------------------------------------------------------//
+// 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 TestScatter
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/scatter.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_buffer_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(scatter_int)
+{
+ int input_data[] = { 1, 2, 3, 4, 5 };
+ bc::vector<int> input(input_data, input_data + 5, queue);
+
+ int map_data[] = { 0, 4, 1, 3, 2 };
+ bc::vector<int> map(map_data, map_data + 5, queue);
+
+ bc::vector<int> output(5, context);
+ bc::scatter(input.begin(), input.end(), map.begin(), output.begin(), queue);
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 4, 2));
+}
+
+BOOST_AUTO_TEST_CASE(scatter_constant_indices)
+{
+ int input_data[] = { 1, 2, 3, 4, 5 };
+ bc::vector<int> input(input_data, input_data + 5, queue);
+
+ int map_data[] = { 0, 4, 1, 3, 2 };
+ bc::buffer map_buffer(context,
+ 5 * sizeof(int),
+ bc::buffer::read_only | bc::buffer::use_host_ptr,
+ map_data);
+
+ bc::vector<int> output(5, context);
+ bc::scatter(input.begin(),
+ input.end(),
+ bc::make_constant_buffer_iterator<int>(map_buffer, 0),
+ output.begin(),
+ queue);
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 4, 2));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_scatter_if.cpp b/src/boost/libs/compute/test/test_scatter_if.cpp
new file mode 100644
index 00000000..1233f8c8
--- /dev/null
+++ b/src/boost/libs/compute/test/test_scatter_if.cpp
@@ -0,0 +1,141 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Pola <jakub.pola@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 TestScatterIf
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/scatter_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_buffer_iterator.hpp>
+#include <boost/compute/iterator/counting_iterator.hpp>
+#include <boost/compute/functional.hpp>
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(scatter_if_int)
+{
+ int input_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ bc::vector<int> input(input_data, input_data + 10, queue);
+
+ int map_data[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+
+ bc::vector<int> map(map_data, map_data + 10, queue);
+
+ int stencil_data[] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
+
+ bc::vector<bc::uint_> stencil(stencil_data, stencil_data + 10, queue);
+
+ bc::vector<int> output(input.size(), -1, queue);
+
+ bc::scatter_if(input.begin(), input.end(),
+ map.begin(), stencil.begin(),
+ output.begin(),
+ queue);
+
+ CHECK_RANGE_EQUAL(int, 10, output, (9, -1, 7, -1, 5, -1, 3, -1, 1, -1) );
+}
+
+BOOST_AUTO_TEST_CASE(scatter_if_constant_indices)
+{
+ int input_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ bc::vector<int> input(input_data, input_data + 10, queue);
+
+ int map_data[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+ bc::buffer map_buffer(context,
+ 10 * sizeof(int),
+ bc::buffer::read_only | bc::buffer::use_host_ptr,
+ map_data);
+
+ int stencil_data[] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
+ bc::buffer stencil_buffer(context,
+ 10 * sizeof(bc::uint_),
+ bc::buffer::read_only | bc::buffer::use_host_ptr,
+ stencil_data);
+
+ bc::vector<int> output(input.size(), -1, queue);
+
+ bc::scatter_if(input.begin(),
+ input.end(),
+ bc::make_constant_buffer_iterator<int>(map_buffer, 0),
+ bc::make_constant_buffer_iterator<int>(stencil_buffer, 0),
+ output.begin(),
+ queue);
+
+ CHECK_RANGE_EQUAL(int, 10, output, (9, -1, 7, -1, 5, -1, 3, -1, 1, -1) );
+}
+
+
+BOOST_AUTO_TEST_CASE(scatter_if_function)
+{
+ int input_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ bc::vector<int> input(input_data, input_data + 10, queue);
+
+ int map_data[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+ bc::vector<int> map(map_data, map_data + 10, queue);
+
+ int stencil_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ bc::vector<bc::uint_> stencil(stencil_data, stencil_data + 10, queue);
+
+ bc::vector<int> output(input.size(), -1, queue);
+
+ BOOST_COMPUTE_FUNCTION(int, gt_than_5, (int x),
+ {
+ if (x > 5)
+ return true;
+ else
+ return false;
+ });
+
+ bc::scatter_if(input.begin(),
+ input.end(),
+ map.begin(),
+ stencil.begin(),
+ output.begin(),
+ gt_than_5,
+ queue);
+
+ CHECK_RANGE_EQUAL(int, 10, output, (9, 8, 7, 6, -1, -1, -1, -1, -1, -1) );
+}
+
+
+BOOST_AUTO_TEST_CASE(scatter_if_counting_iterator)
+{
+ int input_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ bc::vector<int> input(input_data, input_data + 10, queue);
+
+ int map_data[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+ bc::vector<int> map(map_data, map_data + 10, queue);
+
+ bc::vector<int> output(input.size(), -1, queue);
+
+ BOOST_COMPUTE_FUNCTION(int, gt_than_5, (int x),
+ {
+ if (x > 5)
+ return true;
+ else
+ return false;
+ });
+
+ bc::scatter_if(input.begin(),
+ input.end(),
+ map.begin(),
+ bc::make_counting_iterator<int>(0),
+ output.begin(),
+ gt_than_5,
+ queue);
+
+ CHECK_RANGE_EQUAL(int, 10, output, (9, 8, 7, 6, -1, -1, -1, -1, -1, -1) );
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_search.cpp b/src/boost/libs/compute/test/test_search.cpp
new file mode 100644
index 00000000..51943625
--- /dev/null
+++ b/src/boost/libs/compute/test/test_search.cpp
@@ -0,0 +1,72 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSearch
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/search.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(search_int)
+{
+ int data[] = {1, 4, 2, 6, 3, 2, 6, 3, 4, 6, 6};
+ bc::vector<bc::int_> vectort(data, data + 11, queue);
+
+ int datap[] = {2, 6};
+ bc::vector<bc::int_> vectorp(datap, datap + 2, queue);
+
+ bc::vector<bc::int_>::iterator iter =
+ bc::search(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 2);
+
+ vectorp[1] = 9;
+
+ iter =
+ bc::search(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 11);
+
+ vectorp[0] = 6;
+ vectorp[1] = 6;
+
+ iter =
+ bc::search(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 9);
+}
+
+BOOST_AUTO_TEST_CASE(search_string)
+{
+ char text[] = "sdabababacabskjabacab";
+ bc::vector<bc::char_> vectort(text, text + 21, queue);
+
+ char pattern[] = "aba";
+ bc::vector<bc::char_> vectorp(pattern, pattern + 3, queue);
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::search(vectort.begin(), vectort.end(),
+ vectorp.begin(), vectorp.end(), queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_search_n.cpp b/src/boost/libs/compute/test/test_search_n.cpp
new file mode 100644
index 00000000..c8b5af07
--- /dev/null
+++ b/src/boost/libs/compute/test/test_search_n.cpp
@@ -0,0 +1,56 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSearchN
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/search_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(search_int)
+{
+ int data[] = {1, 2, 2, 2, 3, 2, 2, 2, 4, 6, 6};
+ bc::vector<bc::int_> vectort(data, data + 11, queue);
+
+ bc::vector<bc::int_>::iterator iter =
+ bc::search_n(vectort.begin(), vectort.end(), 3, 2, queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 1);
+
+ iter =
+ bc::search_n(vectort.begin(), vectort.end(), 5, 2, queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 11);
+
+ iter =
+ bc::search_n(vectort.begin(), vectort.end(), 2, 6, queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 9);
+}
+
+BOOST_AUTO_TEST_CASE(search_string)
+{
+ char text[] = "asaaababaaca";
+ bc::vector<bc::char_> vectort(text, text + 12, queue);
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::search_n(vectort.begin(), vectort.end(), 2, 'a', queue);
+
+ BOOST_CHECK(iter == vectort.begin() + 2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_set_difference.cpp b/src/boost/libs/compute/test/test_set_difference.cpp
new file mode 100644
index 00000000..d6ecb0a3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_set_difference.cpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSetDifference
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/set_difference.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(set_difference_int)
+{
+ int dataset1[] = {1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 10};
+ bc::vector<bc::int_> set1(dataset1, dataset1 + 12, queue);
+
+ int dataset2[] = {0, 2, 2, 4, 5, 6, 8, 8, 9, 9, 9, 13};
+ bc::vector<bc::int_> set2(dataset2, dataset2 + 12, queue);
+
+ bc::vector<bc::uint_>result(7, queue.get_context());
+
+ bc::vector<bc::uint_>::iterator iter =
+ bc::set_difference(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 12,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 7, result, (1, 1, 2, 2, 3, 3, 10));
+ BOOST_VERIFY(iter == result.begin()+7);
+}
+
+BOOST_AUTO_TEST_CASE(set_difference_string)
+{
+ char string1[] = "abcccdddeeff";
+ bc::vector<bc::char_> set1(string1, string1 + 12, queue);
+
+ char string2[] = "bccdfgh";
+ bc::vector<bc::char_> set2(string2, string2 + 7, queue);
+
+ bc::vector<bc::char_>result(7, queue.get_context());
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::set_difference(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 7,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(char, 7, result, ('a', 'c', 'd', 'd', 'e', 'e', 'f'));
+ BOOST_VERIFY(iter == result.begin()+7);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_set_intersection.cpp b/src/boost/libs/compute/test/test_set_intersection.cpp
new file mode 100644
index 00000000..b33007b7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_set_intersection.cpp
@@ -0,0 +1,62 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSetIntersection
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/set_intersection.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(set_intersection_int)
+{
+ int dataset1[] = {1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 10};
+ bc::vector<bc::int_> set1(dataset1, dataset1 + 12, queue);
+
+ int dataset2[] = {0, 2, 2, 4, 5, 6, 8, 8, 9, 9, 9, 13};
+ bc::vector<bc::int_> set2(dataset2, dataset2 + 12, queue);
+
+ bc::vector<bc::uint_>result(10, queue.get_context());
+
+ bc::vector<bc::uint_>::iterator iter =
+ bc::set_intersection(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 12,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 5, result, (2, 2, 4, 5, 6));
+ BOOST_VERIFY(iter == result.begin()+5);
+}
+
+BOOST_AUTO_TEST_CASE(set_intersection_string)
+{
+ char string1[] = "abcccdddeeff";
+ bc::vector<bc::char_> set1(string1, string1 + 12, queue);
+
+ char string2[] = "bccdfgh";
+ bc::vector<bc::char_> set2(string2, string2 + 7, queue);
+
+ bc::vector<bc::char_>result(5, queue.get_context());
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::set_intersection(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 7,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(char, 5, result, ('b', 'c', 'c', 'd', 'f'));
+ BOOST_VERIFY(iter == result.begin()+5);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_set_symmetric_difference.cpp b/src/boost/libs/compute/test/test_set_symmetric_difference.cpp
new file mode 100644
index 00000000..f90a34b2
--- /dev/null
+++ b/src/boost/libs/compute/test/test_set_symmetric_difference.cpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSetSymmetricDifference
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/set_symmetric_difference.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(set_symmetric_difference_int)
+{
+ int dataset1[] = {1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 10};
+ bc::vector<bc::int_> set1(dataset1, dataset1 + 12, queue);
+
+ int dataset2[] = {0, 2, 2, 4, 5, 6, 8, 8, 9, 9, 9, 13};
+ bc::vector<bc::int_> set2(dataset2, dataset2 + 12, queue);
+
+ bc::vector<bc::uint_>result(14, queue.get_context());
+
+ bc::vector<bc::uint_>::iterator iter =
+ bc::set_symmetric_difference(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 12,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 14, result, (0, 1, 1, 2, 2, 3, 3, 8,
+ 8, 9, 9, 9, 10, 13));
+ BOOST_VERIFY(iter == result.begin()+14);
+}
+
+BOOST_AUTO_TEST_CASE(set_symmetric_difference_string)
+{
+ char string1[] = "abcccdddeeff";
+ bc::vector<bc::char_> set1(string1, string1 + 12, queue);
+
+ char string2[] = "bccdfgh";
+ bc::vector<bc::char_> set2(string2, string2 + 7, queue);
+
+ bc::vector<bc::char_>result(9, queue.get_context());
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::set_symmetric_difference(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 7,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(char, 9, result, ('a', 'c', 'd', 'd', 'e', 'e', 'f', 'g', 'h'));
+ BOOST_VERIFY(iter == result.begin()+9);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_set_union.cpp b/src/boost/libs/compute/test/test_set_union.cpp
new file mode 100644
index 00000000..f3c6dedb
--- /dev/null
+++ b/src/boost/libs/compute/test/test_set_union.cpp
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestSetUnion
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/set_union.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(set_union_int)
+{
+ int dataset1[] = {1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 10};
+ bc::vector<bc::int_> set1(dataset1, dataset1 + 12, queue);
+
+ int dataset2[] = {0, 2, 2, 4, 5, 6, 8, 8, 9, 9, 9, 13};
+ bc::vector<bc::int_> set2(dataset2, dataset2 + 12, queue);
+
+ bc::vector<bc::uint_>result(19, queue.get_context());
+
+ bc::vector<bc::uint_>::iterator iter =
+ bc::set_union(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 12,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 19, result, (0, 1, 1, 2, 2, 2, 2, 3, 3, 4,
+ 5, 6, 8, 8, 9, 9, 9, 10, 13));
+ BOOST_VERIFY(iter == result.begin()+19);
+}
+
+BOOST_AUTO_TEST_CASE(set_union_string)
+{
+ char string1[] = "abcccdddeeff";
+ bc::vector<bc::char_> set1(string1, string1 + 12, queue);
+
+ char string2[] = "bccdfgh";
+ bc::vector<bc::char_> set2(string2, string2 + 7, queue);
+
+ bc::vector<bc::char_>result(14, queue.get_context());
+
+ bc::vector<bc::char_>::iterator iter =
+ bc::set_union(set1.begin(), set1.begin() + 12,
+ set2.begin(), set2.begin() + 7,
+ result.begin(), queue);
+
+ CHECK_RANGE_EQUAL(char, 14, result, ('a', 'b', 'c', 'c', 'c', 'd', 'd', 'd',
+ 'e', 'e', 'f', 'f', 'g', 'h'));
+ BOOST_VERIFY(iter == result.begin()+14);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_sort.cpp b/src/boost/libs/compute/test/test_sort.cpp
new file mode 100644
index 00000000..3b3a76f7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_sort.cpp
@@ -0,0 +1,367 @@
+//---------------------------------------------------------------------------//
+// 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 TestSort
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/struct.hpp>
+
+struct Particle
+{
+ Particle(): x(0.f), y(0.f) { }
+ Particle(float _x, float _y): x(_x), y(_y) { }
+
+ float x;
+ float y;
+};
+
+// adapt struct for OpenCL
+BOOST_COMPUTE_ADAPT_STRUCT(Particle, Particle, (x, y))
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+// test trivial sorting of zero and one element vectors
+BOOST_AUTO_TEST_CASE(sort_int_0_and_1)
+{
+ boost::compute::vector<int> vec(context);
+ BOOST_CHECK_EQUAL(vec.size(), size_t(0));
+ BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
+ boost::compute::sort(vec.begin(), vec.end(), queue);
+
+ vec.push_back(11, queue);
+ BOOST_CHECK_EQUAL(vec.size(), size_t(1));
+ BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
+ boost::compute::sort(vec.begin(), vec.end(), queue);
+}
+
+// test sorting of two element int vectors
+BOOST_AUTO_TEST_CASE(sort_int_2)
+{
+ int data[] = { 4, 2 };
+ boost::compute::vector<int> vec(data, data + 2, queue);
+
+ // check that vec is unsorted
+ BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == false);
+
+ // sort vec
+ boost::compute::sort(vec.begin(), vec.end(), queue);
+
+ // check that vec is sorted
+ BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
+
+ // sort already sorted vec and ensure it is still sorted
+ boost::compute::sort(vec.begin(), vec.end());
+ BOOST_CHECK(boost::compute::is_sorted(vec.begin(), vec.end(), queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_3)
+{
+ float data[] = { 2.3f, 0.1f, 1.2f };
+ boost::compute::vector<float> vec(data, data + 3, queue);
+ boost::compute::sort(vec.begin(), vec.end(), queue);
+ CHECK_RANGE_EQUAL(float, 3, vec, (0.1f, 1.2f, 2.3f));
+}
+
+BOOST_AUTO_TEST_CASE(sort_char_vector)
+{
+ using boost::compute::char_;
+
+ char_ data[] = { 'c', 'a', '0', '7', 'B', 'F', '\0', '$' };
+ boost::compute::vector<char_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(char_, 8, vector, ('\0', '$', '0', '7', 'B', 'F', 'a', 'c'));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uchar_vector)
+{
+ using boost::compute::uchar_;
+
+ uchar_ data[] = { 0x12, 0x00, 0xFF, 0xB4, 0x80, 0x32, 0x64, 0xA2 };
+ boost::compute::vector<uchar_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uchar_, 8, vector, (0x00, 0x12, 0x32, 0x64, 0x80, 0xA2, 0xB4, 0xFF));
+}
+
+BOOST_AUTO_TEST_CASE(sort_short_vector)
+{
+ using boost::compute::short_;
+
+ short_ data[] = { -4, 152, -94, 963, 31002, -456, 0, -2113 };
+ boost::compute::vector<short_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(short_, 8, vector, (-2113, -456, -94, -4, 0, 152, 963, 31002));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ushort_vector)
+{
+ using boost::compute::ushort_;
+
+ ushort_ data[] = { 4, 152, 94, 963, 63202, 34560, 0, 2113 };
+ boost::compute::vector<ushort_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ushort_, 8, vector, (0, 4, 94, 152, 963, 2113, 34560, 63202));
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_vector)
+{
+ int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(int, 8, vector, (-5000, -456, -4, 0, 152, 963, 1112, 75321));
+}
+
+BOOST_AUTO_TEST_CASE(sort_uint_vector)
+{
+ using boost::compute::uint_;
+
+ uint_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<uint_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(uint_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_long_vector)
+{
+ using boost::compute::long_;
+
+ long_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<long_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(long_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_ulong_vector)
+{
+ using boost::compute::ulong_;
+
+ ulong_ data[] = { 500, 1988, 123456, 562, 0, 4000000, 9852, 102030 };
+ boost::compute::vector<ulong_> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(ulong_, 8, vector, (0, 500, 562, 1988, 9852, 102030, 123456, 4000000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_float_vector)
+{
+ float data[] = { -6023.0f, 152.5f, -63.0f, 1234567.0f, 11.2f,
+ -5000.1f, 0.0f, 14.0f, -8.25f, -0.0f };
+ boost::compute::vector<float> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ float, 10, vector,
+ (-6023.0f, -5000.1f, -63.0f, -8.25f, -0.0f, 0.0f, 11.2f, 14.0f, 152.5f, 1234567.0f)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(sort_double_vector)
+{
+ if(!device.supports_extension("cl_khr_fp64")){
+ std::cout << "skipping test: device does not support double" << std::endl;
+ return;
+ }
+
+ double data[] = { -6023.0, 152.5, -63.0, 1234567.0, 11.2,
+ -5000.1, 0.0, 14.0, -8.25, -0.0 };
+ boost::compute::vector<double> vector(data, data + 10, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(10));
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(boost::compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(
+ double, 10, vector,
+ (-6023.0, -5000.1, -63.0, -8.25, -0.0, 0.0, 11.2, 14.0, 152.5, 1234567.0)
+ );
+
+}
+
+BOOST_AUTO_TEST_CASE(reverse_sort_int_vector)
+{
+ int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ boost::compute::vector<int> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+
+ boost::compute::sort(vector.begin(), vector.end(),
+ boost::compute::greater<int>(), queue);
+ CHECK_RANGE_EQUAL(int, 8, vector, (75321, 1112, 963, 152, 0, -4, -456, -5000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_vectors_by_length)
+{
+ using boost::compute::float2_;
+ using boost::compute::lambda::_1;
+ using boost::compute::lambda::_2;
+
+ float data[] = { 1.0f, 0.2f,
+ 1.3f, 1.0f,
+ 6.7f, 0.0f,
+ 5.2f, 3.4f,
+ 1.4f, 1.4f };
+
+ // create vector on device containing vectors
+ boost::compute::vector<float2_> vector(
+ reinterpret_cast<float2_ *>(data),
+ reinterpret_cast<float2_ *>(data) + 5,
+ queue
+ );
+
+ // sort vectors by length
+ boost::compute::sort(
+ vector.begin(),
+ vector.end(),
+ length(_1) < length(_2),
+ queue
+ );
+
+ // copy sorted values back to host
+ boost::compute::copy(
+ vector.begin(),
+ vector.end(),
+ reinterpret_cast<float2_ *>(data),
+ queue
+ );
+
+ // check values
+ BOOST_CHECK_EQUAL(data[0], 1.0f);
+ BOOST_CHECK_EQUAL(data[1], 0.2f);
+ BOOST_CHECK_EQUAL(data[2], 1.3f);
+ BOOST_CHECK_EQUAL(data[3], 1.0f);
+ BOOST_CHECK_EQUAL(data[4], 1.4f);
+ BOOST_CHECK_EQUAL(data[5], 1.4f);
+ BOOST_CHECK_EQUAL(data[6], 5.2f);
+ BOOST_CHECK_EQUAL(data[7], 3.4f);
+ BOOST_CHECK_EQUAL(data[8], 6.7f);
+ BOOST_CHECK_EQUAL(data[9], 0.0f);
+}
+
+BOOST_AUTO_TEST_CASE(sort_host_vector)
+{
+ int data[] = { 5, 2, 3, 6, 7, 4, 0, 1 };
+ std::vector<int> vector(data, data + 8);
+ boost::compute::sort(vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(int, 8, vector, (0, 1, 2, 3, 4, 5, 6, 7));
+}
+
+BOOST_AUTO_TEST_CASE(sort_custom_struct)
+{
+ // function to compare particles by their x-coordinate
+ BOOST_COMPUTE_FUNCTION(bool, sort_by_x, (Particle a, Particle b),
+ {
+ return a.x < b.x;
+ });
+
+ std::vector<Particle> particles;
+ particles.push_back(Particle(0.1f, 0.f));
+ particles.push_back(Particle(-0.4f, 0.f));
+ particles.push_back(Particle(10.0f, 0.f));
+ particles.push_back(Particle(0.001f, 0.f));
+
+ boost::compute::vector<Particle> vector(4, context);
+ boost::compute::copy(particles.begin(), particles.end(), vector.begin(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(4));
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(),
+ sort_by_x, queue) == false
+ );
+
+ boost::compute::sort(vector.begin(), vector.end(), sort_by_x, queue);
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(),
+ sort_by_x, queue) == true
+ );
+ boost::compute::copy(vector.begin(), vector.end(), particles.begin(), queue);
+ BOOST_CHECK_CLOSE(particles[0].x, -0.4f, 0.1);
+ BOOST_CHECK_CLOSE(particles[1].x, 0.001f, 0.1);
+ BOOST_CHECK_CLOSE(particles[2].x, 0.1f, 0.1);
+ BOOST_CHECK_CLOSE(particles[3].x, 10.0f, 0.1);
+}
+
+BOOST_AUTO_TEST_CASE(sort_int2)
+{
+ using bc::int2_;
+
+ BOOST_COMPUTE_FUNCTION(bool, sort_int2, (int2_ a, int2_ b),
+ {
+ return a.x < b.x;
+ });
+
+ const size_t size = 100;
+ std::vector<int2_> host(size, int2_(0, 0));
+ host[0] = int2_(100.f, 0.f);
+ host[size/4] = int2_(20.f, 0.f);
+ host[(size*3)/4] = int2_(9.f, 0.f);
+ host[size-3] = int2_(-10.0f, 0.f);
+ host[size/2+1] = int2_(-10.0f, -1.f);
+
+ boost::compute::vector<int2_> vector(size, context);
+ boost::compute::copy(host.begin(), host.end(), vector.begin(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size);
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(),
+ sort_int2, queue) == false
+ );
+
+ boost::compute::sort(vector.begin(), vector.end(), sort_int2, queue);
+ BOOST_CHECK(
+ boost::compute::is_sorted(vector.begin(), vector.end(),
+ sort_int2, queue) == true
+ );
+ boost::compute::copy(vector.begin(), vector.end(), host.begin(), queue);
+ BOOST_CHECK_CLOSE(host[0][0], -10.f, 0.1);
+ BOOST_CHECK_CLOSE(host[1][0], -10.f, 0.1);
+ BOOST_CHECK_CLOSE(host[(size - 3)][0], 9.f, 0.1);
+ BOOST_CHECK_CLOSE(host[(size - 2)][0], 20.f, 0.1);
+ BOOST_CHECK_CLOSE(host[(size - 1)][0], 100.f, 0.1);
+ BOOST_CHECK_NE(host[0], host[1]);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_sort_by_key.cpp b/src/boost/libs/compute/test/test_sort_by_key.cpp
new file mode 100644
index 00000000..978d81d3
--- /dev/null
+++ b/src/boost/libs/compute/test/test_sort_by_key.cpp
@@ -0,0 +1,207 @@
+//---------------------------------------------------------------------------//
+// 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 TestSortByKey
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/sort_by_key.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/struct.hpp>
+
+struct custom_struct
+{
+ boost::compute::int_ x;
+ boost::compute::int_ y;
+ boost::compute::float2_ zw;
+};
+
+BOOST_COMPUTE_ADAPT_STRUCT(custom_struct, custom_struct, (x, y, zw))
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+// test trivial sorting of zero element vectors
+BOOST_AUTO_TEST_CASE(sort_int_0)
+{
+ compute::vector<int> keys(context);
+ compute::vector<int> values(context);
+ BOOST_CHECK_EQUAL(keys.size(), size_t(0));
+ BOOST_CHECK_EQUAL(values.size(), size_t(0));
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end()) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end()) == true);
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+}
+
+// test trivial sorting of one element vectors
+BOOST_AUTO_TEST_CASE(sort_int_1)
+{
+ int keys_data[] = { 11 };
+ int values_data[] = { 100 };
+
+ compute::vector<int> keys(keys_data, keys_data + 1, queue);
+ compute::vector<int> values(values_data, values_data + 1, queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+}
+
+// test trivial sorting of two element vectors
+BOOST_AUTO_TEST_CASE(sort_int_2)
+{
+ int keys_data[] = { 4, 2 };
+ int values_data[] = { 42, 24 };
+
+ compute::vector<int> keys(keys_data, keys_data + 2, queue);
+ compute::vector<int> values(values_data, values_data + 2, queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == false);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(sort_char_by_int)
+{
+ int keys_data[] = { 6, 2, 1, 3, 4, 7, 5, 0 };
+ compute::char_ values_data[] = { 'g', 'c', 'b', 'd', 'e', 'h', 'f', 'a' };
+
+ compute::vector<int> keys(keys_data, keys_data + 8, queue);
+ compute::vector<compute::char_> values(values_data, values_data + 8, queue);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ CHECK_RANGE_EQUAL(int, 8, keys, (0, 1, 2, 3, 4, 5, 6, 7));
+ CHECK_RANGE_EQUAL(compute::char_, 8, values, ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'));
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_and_float)
+{
+ int n = 1024;
+ std::vector<int> host_keys(n);
+ std::vector<float> host_values(n);
+ for(int i = 0; i < n; i++){
+ host_keys[i] = n - i;
+ host_values[i] = (n - i) / 2.f;
+ }
+
+ compute::vector<int> keys(host_keys.begin(), host_keys.end(), queue);
+ compute::vector<float> values(host_values.begin(), host_values.end(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == false);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_and_float_custom_comparison_func)
+{
+ using boost::compute::int_;
+ using boost::compute::float_;
+
+ int n = 1024;
+ std::vector<int_> host_keys(n);
+ std::vector<float_> host_values(n);
+ for(int i = 0; i < n; i++){
+ host_keys[i] = n - i;
+ host_values[i] = (n - i) / 2.f;
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, sort_int, (int_ a, int_ b),
+ {
+ return a < b;
+ });
+
+ compute::vector<int_> keys(host_keys.begin(), host_keys.end(), queue);
+ compute::vector<float_> values(host_values.begin(), host_values.end(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), sort_int, queue) == false);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == false);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), sort_int, queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), sort_int, queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(sort_int_and_float2)
+{
+ using boost::compute::int_;
+ using boost::compute::float2_;
+
+ int n = 1024;
+ std::vector<int_> host_keys(n);
+ std::vector<float2_> host_values(n);
+ for(int i = 0; i < n; i++){
+ host_keys[i] = n - i;
+ host_values[i] = float2_((n - i) / 2.f);
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, sort_float2, (float2_ a, float2_ b),
+ {
+ return a.x < b.x;
+ });
+
+ compute::vector<int_> keys(host_keys.begin(), host_keys.end(), queue);
+ compute::vector<float2_> values(host_values.begin(), host_values.end(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), sort_float2, queue) == false);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), sort_float2, queue) == true);
+}
+
+BOOST_AUTO_TEST_CASE(sort_custom_struct_by_int)
+{
+ using boost::compute::int_;
+ using boost::compute::float2_;
+
+ int_ n = 1024;
+ std::vector<int_> host_keys(n);
+ std::vector<custom_struct> host_values(n);
+ for(int_ i = 0; i < n; i++){
+ host_keys[i] = n - i;
+ host_values[i].x = n - i;
+ host_values[i].y = n - i;
+ host_values[i].zw = float2_((n - i) / 0.5f);
+ }
+
+ BOOST_COMPUTE_FUNCTION(bool, sort_custom_struct, (custom_struct a, custom_struct b),
+ {
+ return a.x < b.x;
+ });
+
+ compute::vector<int_> keys(host_keys.begin(), host_keys.end(), queue);
+ compute::vector<custom_struct> values(host_values.begin(), host_values.end(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == false);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), sort_custom_struct, queue) == false);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue) == true);
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), sort_custom_struct, queue) == true);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_sort_by_transform.cpp b/src/boost/libs/compute/test/test_sort_by_transform.cpp
new file mode 100644
index 00000000..25076060
--- /dev/null
+++ b/src/boost/libs/compute/test/test_sort_by_transform.cpp
@@ -0,0 +1,110 @@
+//---------------------------------------------------------------------------//
+// 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 TestSortByTransform
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/experimental/sort_by_transform.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(sort_int_by_abs)
+{
+ int data[] = { 1, -2, 4, -3, 0, 5, -8, -9 };
+ compute::vector<int> vector(data, data + 8, queue);
+
+ compute::experimental::sort_by_transform(
+ vector.begin(),
+ vector.end(),
+ compute::abs<int>(),
+ compute::less<int>(),
+ queue
+ );
+
+ CHECK_RANGE_EQUAL(int, 8, vector, (0, 1, -2, -3, 4, 5, -8, -9));
+}
+
+BOOST_AUTO_TEST_CASE(sort_vectors_by_length)
+{
+ using compute::float4_;
+
+ float data[] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 1.0f, 0.0f,
+ 3.0f, 2.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.0f
+ };
+
+ compute::vector<float4_> vector(4, context);
+ compute::copy_n(
+ reinterpret_cast<float4_ *>(data), 4, vector.begin(), queue
+ );
+
+ compute::experimental::sort_by_transform(
+ vector.begin(),
+ vector.end(),
+ compute::length<float4_>(),
+ compute::less<float>(),
+ queue
+ );
+
+ std::vector<float4_> host_vector(4);
+ compute::copy(
+ vector.begin(), vector.end(), host_vector.begin(), queue
+ );
+ BOOST_CHECK_EQUAL(host_vector[0], float4_(0.0f, 0.0f, 0.5f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[1], float4_(1.0f, 0.0f, 0.0f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[2], float4_(0.0f, 1.0f, 1.0f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[3], float4_(3.0f, 2.0f, 1.0f, 0.0f));
+}
+
+BOOST_AUTO_TEST_CASE(sort_vectors_by_component)
+{
+ using compute::float4_;
+
+ float data[] = {
+ 1.0f, 2.0f, 3.0f, 0.0f,
+ 9.0f, 8.0f, 7.0f, 0.0f,
+ 4.0f, 5.0f, 6.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f
+ };
+
+ compute::vector<float4_> vector(4, context);
+ compute::copy_n(
+ reinterpret_cast<float4_ *>(data), 4, vector.begin(), queue
+ );
+
+ // sort by y-component
+ compute::experimental::sort_by_transform(
+ vector.begin(),
+ vector.end(),
+ compute::get<1>(),
+ compute::less<float>(),
+ queue
+ );
+
+ std::vector<float4_> host_vector(4);
+ compute::copy(
+ vector.begin(), vector.end(), host_vector.begin(), queue
+ );
+ BOOST_CHECK_EQUAL(host_vector[0], float4_(0.0f, 0.0f, 0.0f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[1], float4_(1.0f, 2.0f, 3.0f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[2], float4_(4.0f, 5.0f, 6.0f, 0.0f));
+ BOOST_CHECK_EQUAL(host_vector[3], float4_(9.0f, 8.0f, 7.0f, 0.0f));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_stable_partition.cpp b/src/boost/libs/compute/test/test_stable_partition.cpp
new file mode 100644
index 00000000..08f1fc23
--- /dev/null
+++ b/src/boost/libs/compute/test/test_stable_partition.cpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestStablePartition
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/stable_partition.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(partition_int)
+{
+ int dataset[] = {1, 1, -2, 0, 5, -1, 2, 4, 0, -1};
+ bc::vector<bc::int_> vector(dataset, dataset + 10, queue);
+
+ bc::vector<bc::int_>::iterator iter =
+ bc::stable_partition(vector.begin(), vector.begin() + 10,
+ bc::_1 > 0, queue);
+
+ CHECK_RANGE_EQUAL(int, 10, vector, (1, 1, 5, 2, 4, -2, 0, -1, 0, -1));
+ BOOST_VERIFY(iter == vector.begin()+5);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_stable_sort.cpp b/src/boost/libs/compute/test/test_stable_sort.cpp
new file mode 100644
index 00000000..d0c573c7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_stable_sort.cpp
@@ -0,0 +1,92 @@
+//---------------------------------------------------------------------------//
+// 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 TestStableSort
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/stable_sort.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(sort_int_vector)
+{
+ int data[] = { -4, 152, -5000, 963, 75321, -456, 0, 1112 };
+ compute::vector<int> vector(data, data + 8, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(8));
+ BOOST_CHECK(compute::is_sorted(vector.begin(), vector.end(), queue) == false);
+
+ compute::stable_sort(vector.begin(), vector.end(), queue);
+ BOOST_CHECK(compute::is_sorted(vector.begin(), vector.end(), queue) == true);
+ CHECK_RANGE_EQUAL(int, 8, vector, (-5000, -456, -4, 0, 152, 963, 1112, 75321));
+
+ // sort reversed
+ compute::stable_sort(vector.begin(), vector.end(), compute::greater<int>(), queue);
+ CHECK_RANGE_EQUAL(int, 8, vector, (75321, 1112, 963, 152, 0, -4, -456, -5000));
+}
+
+BOOST_AUTO_TEST_CASE(sort_int2)
+{
+ using compute::int2_;
+
+ // device vector of int2's
+ compute::vector<int2_> vec(context);
+ vec.push_back(int2_(2, 1), queue);
+ vec.push_back(int2_(2, 2), queue);
+ vec.push_back(int2_(1, 2), queue);
+ vec.push_back(int2_(1, 1), queue);
+
+ // function comparing the first component of each int2
+ BOOST_COMPUTE_FUNCTION(bool, compare_first, (int2_ a, int2_ b),
+ {
+ return a.x < b.x;
+ });
+
+ // ensure vector is not sorted
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), compare_first, queue) == false);
+
+ // sort elements based on their first component
+ compute::stable_sort(vec.begin(), vec.end(), compare_first, queue);
+
+ // ensure vector is now sorted
+ BOOST_CHECK(compute::is_sorted(vec.begin(), vec.end(), compare_first, queue) == true);
+
+ // check sorted vector order
+ std::vector<int2_> result(vec.size());
+ compute::copy(vec.begin(), vec.end(), result.begin(), queue);
+ BOOST_CHECK_EQUAL(result[0], int2_(1, 2));
+ BOOST_CHECK_EQUAL(result[1], int2_(1, 1));
+ BOOST_CHECK_EQUAL(result[2], int2_(2, 1));
+ BOOST_CHECK_EQUAL(result[3], int2_(2, 2));
+
+ // function comparing the second component of each int2
+ BOOST_COMPUTE_FUNCTION(bool, compare_second, (int2_ a, int2_ b),
+ {
+ return a.y < b.y;
+ });
+
+ // sort elements based on their second component
+ compute::stable_sort(vec.begin(), vec.end(), compare_second, queue);
+
+ // check sorted vector order
+ compute::copy(vec.begin(), vec.end(), result.begin(), queue);
+ BOOST_CHECK_EQUAL(result[0], int2_(1, 1));
+ BOOST_CHECK_EQUAL(result[1], int2_(2, 1));
+ BOOST_CHECK_EQUAL(result[2], int2_(1, 2));
+ BOOST_CHECK_EQUAL(result[3], int2_(2, 2));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_stable_sort_by_key.cpp b/src/boost/libs/compute/test/test_stable_sort_by_key.cpp
new file mode 100644
index 00000000..0ed7b6a9
--- /dev/null
+++ b/src/boost/libs/compute/test/test_stable_sort_by_key.cpp
@@ -0,0 +1,206 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2016 Jakub Szuppe <j.szuppe@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 TestStableSortByKey
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/stable_sort_by_key.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(empty_int_by_int)
+{
+ compute::vector<compute::int_> keys(size_t(0), compute::int_(0), queue);
+ compute::vector<compute::int_> values(size_t(0), compute::int_(0), queue);
+
+ BOOST_CHECK_EQUAL(keys.size(), size_t(0));
+ BOOST_CHECK_EQUAL(values.size(), size_t(0));
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue));
+
+ compute::stable_sort_by_key(
+ keys.begin(), keys.end(), values.begin(), queue
+ );
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end()));
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end()));
+}
+
+BOOST_AUTO_TEST_CASE(one_element_int_by_int)
+{
+ compute::int_ keys_data[] = { 1 };
+ compute::int_ values_data[] = { 2 };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 1, queue);
+ compute::vector<compute::int_> values(values_data, values_data + 1, queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue));
+
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+ BOOST_CHECK(compute::is_sorted(values.begin(), values.end(), queue));
+}
+
+BOOST_AUTO_TEST_CASE(two_elements_int_by_int)
+{
+ compute::int_ keys_data[] = { 1, -1 };
+ compute::int_ values_data[] = { -10, 1 };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 2, queue);
+ compute::vector<compute::int_> values(values_data, values_data + 2, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_int_by_int)
+{
+ compute::int_ keys_data[] = { 10, 9, 2, 7, 6, -1, 4, 2, 2, 10 };
+ compute::int_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::int_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, keys,
+ (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
+ // ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 10, values,
+ // (-1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
+ ( 6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
+ );
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_uint_by_uint)
+{
+ compute::uint_ keys_data[] = { 10, 9, 2, 7, 6, 1, 4, 2, 2, 10 };
+ compute::uint_ values_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ compute::vector<compute::uint_> keys(keys_data, keys_data + 10, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 10, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, keys,
+ (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) // keys
+ // (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::uint_, 10, values,
+ // (1, 2, 2, 2, 4, 6, 7, 9, 10, 10) keys
+ (6, 3, 8, 9, 7, 5, 4, 2, 1, 10) // values
+ );
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_int_by_float)
+{
+ compute::float_ keys_data[] = { 10., 5.5, 10., 7., 5.5};
+ compute::int_ values_data[] = { 1, 200, -10, 2, 4 };
+
+ compute::vector<compute::float_> keys(keys_data, keys_data + 5, queue);
+ compute::vector<compute::uint_> values(values_data, values_data + 5, queue);
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), queue));
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), queue));
+
+ CHECK_RANGE_EQUAL(
+ compute::float_, 5, keys,
+ (5.5, 5.5, 7., 10., 10.) // keys
+ // (200, 4, 2, 1, -10) values
+ );
+ CHECK_RANGE_EQUAL(
+ compute::int_, 5, values,
+ // (5.5, 5.5, 7., 10., 10.) keys
+ (200, 4, 2, 1, -10) // values
+ );
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_char_by_int)
+{
+ compute::int_ keys_data[] = { 6, 1, 1, 3, 4, 7, 5, 1 };
+ compute::char_ values_data[] = { 'g', 'c', 'b', 'd', 'e', 'h', 'f', 'a' };
+
+ compute::vector<compute::int_> keys(keys_data, keys_data + 8, queue);
+ compute::vector<compute::char_> values(values_data, values_data + 8, queue);
+
+ compute::sort_by_key(keys.begin(), keys.end(), values.begin(), queue);
+
+ CHECK_RANGE_EQUAL(
+ compute::int_, 8, keys,
+ (1, 1, 1, 3, 4, 5, 6, 7)
+ );
+ CHECK_RANGE_EQUAL(
+ compute::char_, 8, values,
+ ('c', 'b', 'a', 'd', 'e', 'f', 'g', 'h')
+ );
+}
+
+BOOST_AUTO_TEST_CASE(stable_sort_mid_uint_by_uint)
+{
+ using boost::compute::int_;
+
+ const int_ size = 128;
+ std::vector<int_> keys_data(size);
+ std::vector<int_> values_data(size);
+ for(int_ i = 0; i < size; i++){
+ keys_data[i] = -i;
+ values_data[i] = -i;
+ }
+
+ keys_data[size/2] = -256;
+ keys_data[size - 2] = -256;
+ keys_data[size - 1] = -256;
+ values_data[size/2] = 3;
+ values_data[size - 2] = 1;
+ values_data[size - 1] = 2;
+
+ compute::vector<int_> keys(keys_data.begin(), keys_data.end(), queue);
+ compute::vector<int_> values(values_data.begin(), values_data.end(), queue);
+
+ // less function for float
+ BOOST_COMPUTE_FUNCTION(bool, comp, (int_ a, int_ b),
+ {
+ return a < b;
+ });
+
+ BOOST_CHECK(!compute::is_sorted(keys.begin(), keys.end(), comp, queue));
+ compute::stable_sort_by_key(keys.begin(), keys.end(), values.begin(), comp, queue);
+ BOOST_CHECK(compute::is_sorted(keys.begin(), keys.end(), comp, queue));
+
+ BOOST_CHECK(keys.begin().read(queue) == -256);
+ BOOST_CHECK((keys.begin() + 1).read(queue) == -256);
+ BOOST_CHECK((keys.begin() + 2).read(queue) == -256);
+
+ BOOST_CHECK(values.begin().read(queue) == 3);
+ BOOST_CHECK((values.begin() + 1).read(queue) == 1);
+ BOOST_CHECK((values.begin() + 2).read(queue) == 2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_stack.cpp b/src/boost/libs/compute/test/test_stack.cpp
new file mode 100644
index 00000000..fffedcc2
--- /dev/null
+++ b/src/boost/libs/compute/test/test_stack.cpp
@@ -0,0 +1,50 @@
+//---------------------------------------------------------------------------//
+// 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 TestStack
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/container/stack.hpp>
+
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ bc::stack<int> stack;
+ BOOST_CHECK_EQUAL(stack.size(), size_t(0));
+
+ stack.push(1);
+ stack.push(2);
+ stack.push(3);
+ BOOST_CHECK_EQUAL(stack.size(), size_t(3));
+}
+
+BOOST_AUTO_TEST_CASE(push_and_pop)
+{
+ bc::stack<int> stack;
+ stack.push(1);
+ stack.push(2);
+ stack.push(3);
+
+ BOOST_CHECK_EQUAL(stack.top(), 3);
+ BOOST_CHECK_EQUAL(stack.size(), size_t(3));
+ stack.pop();
+ BOOST_CHECK_EQUAL(stack.top(), 2);
+ BOOST_CHECK_EQUAL(stack.size(), size_t(2));
+ stack.pop();
+ BOOST_CHECK_EQUAL(stack.top(), 1);
+ BOOST_CHECK_EQUAL(stack.size(), size_t(1));
+ stack.pop();
+ BOOST_CHECK_EQUAL(stack.size(), size_t(0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_strided_iterator.cpp b/src/boost/libs/compute/test/test_strided_iterator.cpp
new file mode 100644
index 00000000..e05e8b2e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_strided_iterator.cpp
@@ -0,0 +1,194 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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 TestStridedIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/strided_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::strided_iterator<
+ boost::compute::buffer_iterator<int>
+ >::value_type,
+ int
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::strided_iterator<
+ boost::compute::buffer_iterator<float>
+ >::value_type,
+ float
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(base_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::strided_iterator<
+ boost::compute::buffer_iterator<int>
+ >::base_type,
+ boost::compute::buffer_iterator<int>
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(distance)
+{
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::vector<int> vec(data, data + 8, queue);
+
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_strided_iterator(vec.begin(), 1),
+ boost::compute::make_strided_iterator(vec.end(), 1)
+ ),
+ std::ptrdiff_t(8)
+ );
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_strided_iterator(vec.begin(), 2),
+ boost::compute::make_strided_iterator(vec.end(), 2)
+ ),
+ std::ptrdiff_t(4)
+ );
+
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_strided_iterator(vec.begin(), 3),
+ boost::compute::make_strided_iterator(vec.begin()+6, 3)
+ ),
+ std::ptrdiff_t(2)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ boost::compute::int_ data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::vector<boost::compute::int_> vec(data, data + 8, queue);
+
+ boost::compute::vector<boost::compute::int_> result(4, context);
+
+ // copy every other element to result
+ boost::compute::copy(
+ boost::compute::make_strided_iterator(vec.begin(), 2),
+ boost::compute::make_strided_iterator(vec.end(), 2),
+ result.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(boost::compute::int_, 4, result, (1, 3, 5, 7));
+
+ // copy every 3rd element to result
+ boost::compute::copy(
+ boost::compute::make_strided_iterator(vec.begin(), 3),
+ boost::compute::make_strided_iterator(vec.begin()+9, 3),
+ result.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(boost::compute::int_, 3, result, (1, 4, 7));
+}
+
+BOOST_AUTO_TEST_CASE(make_strided_iterator_end)
+{
+ boost::compute::int_ data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ boost::compute::vector<boost::compute::int_> vec(data, data + 8, queue);
+
+ // stride equals 3
+ typedef boost::compute::vector<boost::compute::int_>::iterator IterType;
+ boost::compute::strided_iterator<IterType> end =
+ boost::compute::make_strided_iterator_end(vec.begin(),
+ vec.end(),
+ 3);
+
+ // end should be vec.begin() + 9 which is one step after last element
+ // accessible through strided_iterator, i.e. vec.begin()+6
+ BOOST_CHECK(boost::compute::make_strided_iterator(vec.begin()+9, 3) ==
+ end);
+
+ // stride equals 2
+ end = boost::compute::make_strided_iterator_end(vec.begin(),
+ vec.end(),
+ 2);
+ // end should be vec.end(), because vector size is divisible by 2
+ BOOST_CHECK(boost::compute::make_strided_iterator(vec.end(), 2) == end);
+
+ // stride equals 1000
+ end = boost::compute::make_strided_iterator_end(vec.begin(),
+ vec.end(),
+ 1000);
+ // end should be vec.begin() + 1000, because stride > vector size
+ BOOST_CHECK(boost::compute::make_strided_iterator(vec.begin()+1000, 1000) ==
+ end);
+
+
+ // test boost::compute::make_strided_iterator_end with copy(..)
+
+ boost::compute::vector<boost::compute::int_> result(4, context);
+
+ // copy every other element to result
+ boost::compute::copy(
+ boost::compute::make_strided_iterator(vec.begin()+1, 2),
+ boost::compute::make_strided_iterator_end(vec.begin()+1, vec.end(), 2),
+ result.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(boost::compute::int_, 4, result, (2, 4, 6, 8));
+}
+
+BOOST_AUTO_TEST_CASE(iterator_tag)
+{
+ typedef bc::buffer_iterator<bc::float_> i_type;
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ std::iterator_traits<
+ i_type
+ >::iterator_category,
+ std::iterator_traits<
+ bc::strided_iterator<i_type>
+ >::iterator_category
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(std_distance)
+{
+ bc::vector<bc::float_> vec(
+ size_t(300),
+ bc::float_(1.1f),
+ queue
+ );
+
+ bc::strided_iterator<bc::buffer_iterator<bc::float_> > begin(vec.begin(), 1);
+ bc::strided_iterator<bc::buffer_iterator<bc::float_> > end(vec.end(), 1);
+
+ BOOST_CHECK_EQUAL(std::distance(begin, end), 300);
+ BOOST_CHECK_EQUAL(std::distance(end, begin), -300);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_string.cpp b/src/boost/libs/compute/test/test_string.cpp
new file mode 100644
index 00000000..4406df7f
--- /dev/null
+++ b/src/boost/libs/compute/test/test_string.cpp
@@ -0,0 +1,89 @@
+//---------------------------------------------------------------------------//
+// 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 TestString
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/container/string.hpp>
+#include <boost/compute/container/basic_string.hpp>
+#include <boost/test/output_test_stream.hpp>
+
+#include "context_setup.hpp"
+#include "check_macros.hpp"
+
+using boost::test_tools::output_test_stream;
+
+BOOST_AUTO_TEST_CASE(empty)
+{
+ boost::compute::string str;
+ BOOST_VERIFY(str.empty());
+}
+
+BOOST_AUTO_TEST_CASE(swap)
+{
+ // boost::compute::string currently uses only default_queue, default_context,
+ // default_device so this overrides queue variable set in
+ // BOOST_FIXTURE_TEST_SUITE(compute_test, Context) in context_setup.hpp
+ // in case it is not the default_queue
+ boost::compute::command_queue& queue =
+ boost::compute::system::default_queue();
+
+ boost::compute::string str1 = "compute";
+ boost::compute::string str2 = "boost";
+ BOOST_VERIFY(!str2.empty());
+ BOOST_VERIFY(!str2.empty());
+ str1.swap(str2);
+ // this macro uses queue variable and it must be default_queue
+ CHECK_STRING_EQUAL(str1, "boost");
+ CHECK_STRING_EQUAL(str2, "compute");
+ str1.clear();
+ str1.swap(str2);
+ CHECK_STRING_EQUAL(str1, "compute");
+ CHECK_STRING_EQUAL(str2, "");
+ str2.swap(str1);
+ CHECK_STRING_EQUAL(str1, "");
+ CHECK_STRING_EQUAL(str2, "compute");
+ str1.swap(str1);
+ CHECK_STRING_EQUAL(str1, "");
+}
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ boost::compute::string str = "string";
+ BOOST_VERIFY(!str.empty());
+ BOOST_CHECK_EQUAL(str.size(), size_t(6));
+ BOOST_CHECK_EQUAL(str.length(), size_t(6));
+}
+
+BOOST_AUTO_TEST_CASE(find_doctest)
+{
+//! [string_find]
+boost::compute::string str = "boost::compute::string";
+int pos = str.find("::");
+//! [string_find]
+ boost::compute::string pattern = "string";
+ BOOST_VERIFY(!str.empty());
+ BOOST_CHECK_EQUAL(str.find('o'), 1);
+ BOOST_CHECK_NE(str.find('o'), 2);
+ BOOST_CHECK_EQUAL(str.find(pattern), 16);
+ BOOST_CHECK_EQUAL(pos, 5);
+ BOOST_CHECK_EQUAL(str.find("@#$"), size_t(-1));
+}
+
+BOOST_AUTO_TEST_CASE(outStream)
+{
+ output_test_stream output;
+ boost::compute::string str = "string";
+ output<<str;
+ BOOST_CHECK(output.is_equal("string"));
+ BOOST_VERIFY(!output.is_equal("!@$%"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_struct.cpp b/src/boost/libs/compute/test/test_struct.cpp
new file mode 100644
index 00000000..d7a7b650
--- /dev/null
+++ b/src/boost/libs/compute/test/test_struct.cpp
@@ -0,0 +1,165 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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.
+//---------------------------------------------------------------------------//
+
+#include <boost/compute/config.hpp>
+
+#define BOOST_TEST_MODULE TestStruct
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/field.hpp>
+#include <boost/compute/types/struct.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/type_traits/type_definition.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// example code defining an atom class
+namespace chemistry {
+
+struct Atom
+{
+ Atom(float _x, float _y, float _z, int _number)
+ : x(_x), y(_y), z(_z), number(_number)
+ {
+ }
+
+ float x;
+ float y;
+ float z;
+ int number;
+};
+
+} // end chemistry namespace
+
+// adapt the chemistry::Atom class
+BOOST_COMPUTE_ADAPT_STRUCT(chemistry::Atom, Atom, (x, y, z, number))
+
+struct StructWithArray {
+ int value;
+ int array[3];
+};
+
+BOOST_COMPUTE_ADAPT_STRUCT(StructWithArray, StructWithArray, (value, array))
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(atom_type_name)
+{
+ BOOST_CHECK(std::strcmp(compute::type_name<chemistry::Atom>(), "Atom") == 0);
+}
+
+BOOST_AUTO_TEST_CASE(atom_struct)
+{
+ std::vector<chemistry::Atom> atoms;
+ atoms.push_back(chemistry::Atom(1.f, 0.f, 0.f, 1));
+ atoms.push_back(chemistry::Atom(0.f, 1.f, 0.f, 1));
+ atoms.push_back(chemistry::Atom(0.f, 0.f, 0.f, 8));
+
+ compute::vector<chemistry::Atom> vec(atoms.size(), context);
+ compute::copy(atoms.begin(), atoms.end(), vec.begin(), queue);
+
+ // find the oxygen atom
+ BOOST_COMPUTE_FUNCTION(bool, is_oxygen, (chemistry::Atom atom),
+ {
+ return atom.number == 8;
+ });
+
+ compute::vector<chemistry::Atom>::iterator iter =
+ compute::find_if(vec.begin(), vec.end(), is_oxygen, queue);
+ BOOST_CHECK(iter == vec.begin() + 2);
+
+ // copy the atomic numbers to another vector
+ compute::vector<int> atomic_numbers(vec.size(), context);
+ compute::transform(
+ vec.begin(), vec.end(),
+ atomic_numbers.begin(),
+ compute::field<int>("number"),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 3, atomic_numbers, (1, 1, 8));
+}
+
+BOOST_AUTO_TEST_CASE(custom_kernel)
+{
+ std::vector<chemistry::Atom> data;
+ data.push_back(chemistry::Atom(1.f, 0.f, 0.f, 1));
+ data.push_back(chemistry::Atom(0.f, 1.f, 0.f, 1));
+ data.push_back(chemistry::Atom(0.f, 0.f, 0.f, 8));
+
+ compute::vector<chemistry::Atom> atoms(data.size(), context);
+ compute::copy(data.begin(), data.end(), atoms.begin(), queue);
+
+ std::string source = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void custom_kernel(__global const Atom *atoms,
+ __global float *distances)
+ {
+ const uint i = get_global_id(0);
+ const __global Atom *atom = &atoms[i];
+
+ const float4 center = { 0, 0, 0, 0 };
+ const float4 position = { atom->x, atom->y, atom->z, 0 };
+
+ distances[i] = distance(position, center);
+ }
+ );
+
+ // add type definition for Atom to the start of the program source
+ source = compute::type_definition<chemistry::Atom>() + "\n" + source;
+
+ compute::program program =
+ compute::program::build_with_source(source, context);
+
+ compute::vector<float> distances(atoms.size(), context);
+
+ compute::kernel custom_kernel = program.create_kernel("custom_kernel");
+ custom_kernel.set_arg(0, atoms);
+ custom_kernel.set_arg(1, distances);
+
+ queue.enqueue_1d_range_kernel(custom_kernel, 0, atoms.size(), 1);
+}
+
+// Creates a StructWithArray containing 'x', 'y', 'z'.
+StructWithArray make_struct_with_array(int x, int y, int z)
+{
+ StructWithArray s;
+ s.value = 0;
+ s.array[0] = x;
+ s.array[1] = y;
+ s.array[2] = z;
+ return s;
+}
+
+BOOST_AUTO_TEST_CASE(struct_with_array)
+{
+ compute::vector<StructWithArray> structs(context);
+
+ structs.push_back(make_struct_with_array(1, 2, 3), queue);
+ structs.push_back(make_struct_with_array(4, 5, 6), queue);
+ structs.push_back(make_struct_with_array(7, 8, 9), queue);
+
+ BOOST_COMPUTE_FUNCTION(int, sum_array, (StructWithArray x),
+ {
+ return x.array[0] + x.array[1] + x.array[2];
+ });
+
+ compute::vector<int> results(structs.size(), context);
+ compute::transform(
+ structs.begin(), structs.end(), results.begin(), sum_array, queue
+ );
+ CHECK_RANGE_EQUAL(int, 3, results, (6, 15, 24));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_svm_ptr.cpp b/src/boost/libs/compute/test/test_svm_ptr.cpp
new file mode 100644
index 00000000..1546deb7
--- /dev/null
+++ b/src/boost/libs/compute/test/test_svm_ptr.cpp
@@ -0,0 +1,156 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestSvmPtr
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/core.hpp>
+#include <boost/compute/svm.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(empty)
+{
+}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_0
+BOOST_AUTO_TEST_CASE(alloc)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ compute::svm_ptr<cl_int> ptr = compute::svm_alloc<cl_int>(context, 8);
+ compute::svm_free(context, ptr);
+}
+
+BOOST_AUTO_TEST_CASE(svmmemcpy)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ if(bug_in_svmmemcpy(device)){
+ std::cerr << "skipping svmmemcpy test case" << std::endl;
+ return;
+ }
+
+ cl_int input[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ cl_int output[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ compute::svm_ptr<cl_int> ptr = compute::svm_alloc<cl_int>(context, 8);
+ compute::svm_ptr<cl_int> ptr2 = compute::svm_alloc<cl_int>(context, 8);
+
+ // copying from and to host mem
+ queue.enqueue_svm_memcpy(ptr.get(), input, 8 * sizeof(cl_int));
+ queue.enqueue_svm_memcpy(output, ptr.get(), 8 * sizeof(cl_int));
+ queue.finish();
+
+ CHECK_HOST_RANGE_EQUAL(cl_int, 8, output, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ // copying between svm mem
+ queue.enqueue_svm_memcpy(ptr2.get(), ptr.get(), 8 * sizeof(cl_int));
+ queue.enqueue_svm_memcpy(output, ptr2.get(), 8 * sizeof(cl_int));
+ queue.finish();
+
+ CHECK_HOST_RANGE_EQUAL(cl_int, 8, output, (1, 2, 3, 4, 5, 6, 7, 8));
+
+ compute::svm_free(context, ptr);
+ compute::svm_free(context, ptr2);
+}
+
+BOOST_AUTO_TEST_CASE(sum_svm_kernel)
+{
+ REQUIRES_OPENCL_VERSION(2, 0);
+
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void sum_svm_mem(__global const int *ptr, __global int *result)
+ {
+ int sum = 0;
+ for(uint i = 0; i < 8; i++){
+ sum += ptr[i];
+ }
+ *result = sum;
+ }
+ );
+
+ compute::program program =
+ compute::program::build_with_source(source, context, "-cl-std=CL2.0");
+
+ compute::kernel sum_svm_mem_kernel = program.create_kernel("sum_svm_mem");
+
+ cl_int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::svm_ptr<cl_int> ptr = compute::svm_alloc<cl_int>(context, 8);
+ queue.enqueue_svm_map(ptr.get(), 8 * sizeof(cl_int), CL_MAP_WRITE);
+ for(size_t i = 0; i < 8; i ++) {
+ static_cast<cl_int*>(ptr.get())[i] = data[i];
+ }
+ queue.enqueue_svm_unmap(ptr.get());
+
+ compute::vector<cl_int> result(1, context);
+
+ sum_svm_mem_kernel.set_arg(0, ptr);
+ sum_svm_mem_kernel.set_arg(1, result);
+ queue.enqueue_task(sum_svm_mem_kernel);
+
+ queue.finish();
+ BOOST_CHECK_EQUAL(result[0], (36));
+
+ compute::svm_free(context, ptr);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_0
+
+#ifdef BOOST_COMPUTE_CL_VERSION_2_1
+BOOST_AUTO_TEST_CASE(migrate)
+{
+ REQUIRES_OPENCL_VERSION(2, 1);
+
+ compute::svm_ptr<cl_int> ptr =
+ compute::svm_alloc<cl_int>(context, 8);
+
+ // Migrate to device
+ std::vector<const void*> ptrs(1, ptr.get());
+ std::vector<size_t> sizes(1, 8 * sizeof(cl_int));
+ queue.enqueue_svm_migrate_memory(ptrs, sizes).wait();
+
+ // Set on device
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void foo(__global int *ptr)
+ {
+ for(int i = 0; i < 8; i++){
+ ptr[i] = i;
+ }
+ }
+ );
+ compute::program program =
+ compute::program::build_with_source(source, context, "-cl-std=CL2.0");
+ compute::kernel foo_kernel = program.create_kernel("foo");
+ foo_kernel.set_arg(0, ptr);
+ queue.enqueue_task(foo_kernel).wait();
+
+ // Migrate to host
+ queue.enqueue_svm_migrate_memory(
+ ptr.get(), 0, boost::compute::command_queue::migrate_to_host
+ ).wait();
+
+ // Check
+ CHECK_HOST_RANGE_EQUAL(
+ cl_int, 8,
+ static_cast<cl_int*>(ptr.get()),
+ (0, 1, 2, 3, 4, 5, 6, 7)
+ );
+ compute::svm_free(context, ptr);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_2_1
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_system.cpp b/src/boost/libs/compute/test/test_system.cpp
new file mode 100644
index 00000000..afc45fe6
--- /dev/null
+++ b/src/boost/libs/compute/test/test_system.cpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// 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 TestSystem
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+
+BOOST_AUTO_TEST_CASE(platform_count)
+{
+ BOOST_CHECK(boost::compute::system::platform_count() >= 1);
+}
+
+BOOST_AUTO_TEST_CASE(device_count)
+{
+ BOOST_CHECK(boost::compute::system::device_count() >= 1);
+}
+
+BOOST_AUTO_TEST_CASE(default_device)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+ BOOST_CHECK(device.id() != cl_device_id());
+}
+
+BOOST_AUTO_TEST_CASE(find_device)
+{
+ boost::compute::device device = boost::compute::system::default_device();
+ const std::string &name = device.name();
+ BOOST_CHECK(boost::compute::system::find_device(name).name() == device.name());
+}
diff --git a/src/boost/libs/compute/test/test_tabulate.cpp b/src/boost/libs/compute/test/test_tabulate.cpp
new file mode 100644
index 00000000..6ef82f45
--- /dev/null
+++ b/src/boost/libs/compute/test/test_tabulate.cpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// 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 TestTabulate
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/experimental/tabulate.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(tabulate_negative_int)
+{
+ BOOST_COMPUTE_FUNCTION(int, negate, (int x),
+ {
+ return -x;
+ });
+
+ compute::vector<int> vector(10, context);
+ compute::experimental::tabulate(vector.begin(), vector.end(), negate, queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (0, -1, -2, -3, -4, -5, -6, -7, -8, -9));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_threefry_engine.cpp b/src/boost/libs/compute/test/test_threefry_engine.cpp
new file mode 100644
index 00000000..3eddce73
--- /dev/null
+++ b/src/boost/libs/compute/test/test_threefry_engine.cpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013 Muhammad Junaid Muzammil <mjunaidmuzammil@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 TestThreefry
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/random/threefry_engine.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include <boost/compute/random/uniform_real_distribution.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(generate_uint)
+{
+ using boost::compute::uint_;
+
+ boost::compute::threefry_engine<> random_engine(queue);
+ boost::compute::vector<uint_> random_values(19, context);
+
+ random_engine.generate(random_values.begin(), random_values.end(), queue);
+ queue.finish();
+ CHECK_RANGE_EQUAL(
+ uint_, 19, random_values,
+ (uint_(0x6b200159),
+ uint_(0x99ba4efe),
+ uint_(0x508efb2c),
+ uint_(0xc0de3f32),
+ uint_(0x64a626ec),
+ uint_(0xfc15e573),
+ uint_(0xb8abc4d1),
+ uint_(0x537eb86),
+ uint_(0xac6dc2bb),
+ uint_(0xa7adb3c3),
+ uint_(0x5641e094),
+ uint_(0xe4ab4fd),
+ uint_(0xa53c1ce9),
+ uint_(0xabcf1dba),
+ uint_(0x2677a25a),
+ uint_(0x76cf5efc),
+ uint_(0x2d08247f),
+ uint_(0x815480f1),
+ uint_(0x2d1fa53a))
+ );
+}
+
+BOOST_AUTO_TEST_CASE(generate_float)
+{
+ using boost::compute::float_;
+
+ boost::compute::threefry_engine<> random_engine(queue);
+ boost::compute::uniform_real_distribution<float_> random_distribution(0.f, 4.f);
+
+ boost::compute::vector<float_> random_values(1024, context);
+ random_distribution.generate(
+ random_values.begin(), random_values.end(), random_engine, queue
+ );
+
+ std::vector<float_> random_values_host(1024);
+ boost::compute::copy(
+ random_values.begin(), random_values.end(),
+ random_values_host.begin(),
+ queue
+ );
+ queue.finish();
+
+ double sum = 0.0;
+ for(size_t i = 0; i < random_values_host.size(); i++)
+ {
+ BOOST_CHECK_LT(random_values_host[i], 4.0f);
+ BOOST_CHECK_GE(random_values_host[i], 0.0f);
+ sum += random_values_host[i];
+ }
+ double mean = sum / random_values_host.size();
+ // For 1024 it can be 10% off
+ BOOST_CHECK_CLOSE(mean, 2.0f, 10.0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_transform.cpp b/src/boost/libs/compute/test/test_transform.cpp
new file mode 100644
index 00000000..81b95c0e
--- /dev/null
+++ b/src/boost/libs/compute/test/test_transform.cpp
@@ -0,0 +1,324 @@
+//---------------------------------------------------------------------------//
+// 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()
diff --git a/src/boost/libs/compute/test/test_transform_if.cpp b/src/boost/libs/compute/test/test_transform_if.cpp
new file mode 100644
index 00000000..fc371327
--- /dev/null
+++ b/src/boost/libs/compute/test/test_transform_if.cpp
@@ -0,0 +1,40 @@
+//---------------------------------------------------------------------------//
+// 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 TestTransformIf
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/transform_if.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(transform_if_odd)
+{
+ using boost::compute::abs;
+ using boost::compute::lambda::_1;
+
+ int data[] = { -2, -3, -4, -5, -6, -7, -8, -9 };
+ compute::vector<int> input(data, data + 8, queue);
+ compute::vector<int> output(input.size(), context);
+
+ compute::vector<int>::iterator end = compute::transform_if(
+ input.begin(), input.end(), output.begin(), abs<int>(), _1 % 2 != 0, queue
+ );
+ BOOST_CHECK_EQUAL(std::distance(output.begin(), end), 4);
+
+ CHECK_RANGE_EQUAL(int, 4, output, (+3, +5, +7, +9));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_transform_iterator.cpp b/src/boost/libs/compute/test/test_transform_iterator.cpp
new file mode 100644
index 00000000..6c77bf75
--- /dev/null
+++ b/src/boost/libs/compute/test/test_transform_iterator.cpp
@@ -0,0 +1,108 @@
+//---------------------------------------------------------------------------//
+// 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 TestTransformIterator
+#include <boost/test/unit_test.hpp>
+
+#include <iterator>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ using boost::compute::float4_;
+
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::transform_iterator<
+ boost::compute::buffer_iterator<float>,
+ boost::compute::sqrt<float>
+ >::value_type,
+ float
+ >::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::transform_iterator<
+ boost::compute::buffer_iterator<float4_>,
+ boost::compute::length<float4_>
+ >::value_type,
+ float
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(base_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::transform_iterator<
+ boost::compute::buffer_iterator<int>, boost::compute::abs<int>
+ >::base_type,
+ boost::compute::buffer_iterator<int>
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ int data[] = { 1, -2, 3, -4, 5 };
+ boost::compute::vector<int> a(data, data + 5, queue);
+
+ boost::compute::vector<int> b(5, context);
+ boost::compute::copy(
+ boost::compute::make_transform_iterator(
+ a.begin(),
+ boost::compute::abs<int>()
+ ),
+ boost::compute::make_transform_iterator(
+ a.end(),
+ boost::compute::abs<int>()
+ ),
+ b.begin(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, b, (1, 2, 3, 4, 5));
+}
+
+BOOST_AUTO_TEST_CASE(copy_abs_doctest)
+{
+ int data[] = { -1, -2, -3, -4 };
+ boost::compute::vector<int> input(data, data + 4, queue);
+ boost::compute::vector<int> output(4, context);
+
+//! [copy_abs]
+// use abs() from boost.compute
+using boost::compute::abs;
+
+// copy the absolute value for each element in input to output
+boost::compute::copy(
+ boost::compute::make_transform_iterator(input.begin(), abs<int>()),
+ boost::compute::make_transform_iterator(input.end(), abs<int>()),
+ output.begin(),
+ queue
+);
+//! [copy_abs]
+
+ CHECK_RANGE_EQUAL(int, 4, output, (1, 2, 3, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_transform_reduce.cpp b/src/boost/libs/compute/test/test_transform_reduce.cpp
new file mode 100644
index 00000000..5766862d
--- /dev/null
+++ b/src/boost/libs/compute/test/test_transform_reduce.cpp
@@ -0,0 +1,101 @@
+//---------------------------------------------------------------------------//
+// 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 TestTransformReduce
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/transform_reduce.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(sum_abs_int_doctest)
+{
+ using boost::compute::abs;
+ using boost::compute::plus;
+
+ int data[] = { 1, -2, -3, -4, 5 };
+ compute::vector<int> vec(data, data + 5, queue);
+
+//! [sum_abs_int]
+int sum = 0;
+boost::compute::transform_reduce(
+ vec.begin(), vec.end(), &sum, abs<int>(), plus<int>(), queue
+);
+//! [sum_abs_int]
+
+ BOOST_CHECK_EQUAL(sum, 15);
+}
+
+BOOST_AUTO_TEST_CASE(multiply_vector_length)
+{
+ float data[] = { 2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 4.0f, 0.0f };
+ compute::vector<compute::float4_> vector(
+ reinterpret_cast<compute::float4_ *>(data),
+ reinterpret_cast<compute::float4_ *>(data) + 3,
+ queue
+ );
+
+ float product;
+ compute::transform_reduce(
+ vector.begin(),
+ vector.end(),
+ &product,
+ compute::length<compute::float4_>(),
+ compute::multiplies<float>(),
+ queue
+ );
+ BOOST_CHECK_CLOSE(product, 24.0f, 1e-4f);
+}
+
+BOOST_AUTO_TEST_CASE(mean_and_std_dev)
+{
+ using compute::lambda::_1;
+ using compute::lambda::pow;
+
+ float data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ compute::vector<float> vector(data, data + 10, queue);
+
+ float sum;
+ compute::reduce(
+ vector.begin(),
+ vector.end(),
+ &sum,
+ compute::plus<float>(),
+ queue
+ );
+
+ float mean = sum / vector.size();
+ BOOST_CHECK_CLOSE(mean, 5.5f, 1e-4);
+
+ compute::transform_reduce(
+ vector.begin(),
+ vector.end(),
+ &sum,
+ pow(_1 - mean, 2),
+ compute::plus<float>(),
+ queue
+ );
+
+ float variance = sum / vector.size();
+ BOOST_CHECK_CLOSE(variance, 8.25f, 1e-4);
+
+ float std_dev = std::sqrt(variance);
+ BOOST_CHECK_CLOSE(std_dev, 2.8722813232690143, 1e-4);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_tuple.cpp b/src/boost/libs/compute/test/test_tuple.cpp
new file mode 100644
index 00000000..ece24a37
--- /dev/null
+++ b/src/boost/libs/compute/test/test_tuple.cpp
@@ -0,0 +1,141 @@
+//---------------------------------------------------------------------------//
+// 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 TestTuple
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_io.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/tuple.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(vector_tuple_int_float)
+{
+ boost::compute::vector<boost::tuple<int, float> > vector(context);
+
+ vector.push_back(boost::make_tuple(1, 2.1f), queue);
+ vector.push_back(boost::make_tuple(2, 3.2f), queue);
+ vector.push_back(boost::make_tuple(3, 4.3f), queue);
+}
+
+BOOST_AUTO_TEST_CASE(copy_vector_tuple)
+{
+ // create vector of tuples on device
+ boost::compute::vector<boost::tuple<char, int, float> > input(context);
+ input.push_back(boost::make_tuple('a', 1, 2.3f), queue);
+ input.push_back(boost::make_tuple('c', 3, 4.5f), queue);
+ input.push_back(boost::make_tuple('f', 6, 7.8f), queue);
+
+ // copy on device
+ boost::compute::vector<boost::tuple<char, int, float> > output(context);
+
+ boost::compute::copy(
+ input.begin(),
+ input.end(),
+ output.begin(),
+ queue
+ );
+
+ // copy to host
+ std::vector<boost::tuple<char, int, float> > host_output(3);
+
+ boost::compute::copy(
+ input.begin(),
+ input.end(),
+ host_output.begin(),
+ queue
+ );
+
+ // check tuple data
+ BOOST_CHECK_EQUAL(host_output[0], boost::make_tuple('a', 1, 2.3f));
+ BOOST_CHECK_EQUAL(host_output[1], boost::make_tuple('c', 3, 4.5f));
+ BOOST_CHECK_EQUAL(host_output[2], boost::make_tuple('f', 6, 7.8f));
+}
+
+BOOST_AUTO_TEST_CASE(extract_tuple_elements)
+{
+ compute::vector<boost::tuple<char, int, float> > vector(context);
+ vector.push_back(boost::make_tuple('a', 1, 2.3f), queue);
+ vector.push_back(boost::make_tuple('c', 3, 4.5f), queue);
+ vector.push_back(boost::make_tuple('f', 6, 7.8f), queue);
+
+ compute::vector<char> chars(3, context);
+ compute::transform(
+ vector.begin(), vector.end(), chars.begin(), compute::get<0>(), queue
+ );
+ CHECK_RANGE_EQUAL(char, 3, chars, ('a', 'c', 'f'));
+
+ compute::vector<int> ints(3, context);
+ compute::transform(
+ vector.begin(), vector.end(), ints.begin(), compute::get<1>(), queue
+ );
+ CHECK_RANGE_EQUAL(int, 3, ints, (1, 3, 6));
+
+ compute::vector<float> floats(3, context);
+ compute::transform(
+ vector.begin(), vector.end(), floats.begin(), compute::get<2>(), queue
+ );
+ CHECK_RANGE_EQUAL(float, 3, floats, (2.3f, 4.5f, 7.8f));
+}
+
+BOOST_AUTO_TEST_CASE(fill_tuple_vector)
+{
+ if(bug_in_struct_assignment(device)){
+ std::cerr << "skipping fill_tuple_vector test" << std::endl;
+ return;
+ }
+
+ compute::vector<boost::tuple<char, int, float> > vector(5, context);
+ compute::fill(vector.begin(), vector.end(), boost::make_tuple('z', 4, 3.14f), queue);
+
+ std::vector<boost::tuple<char, int, float> > host_output(5);
+ compute::copy(vector.begin(), vector.end(), host_output.begin(), queue);
+ BOOST_CHECK_EQUAL(host_output[0], boost::make_tuple('z', 4, 3.14f));
+ BOOST_CHECK_EQUAL(host_output[1], boost::make_tuple('z', 4, 3.14f));
+ BOOST_CHECK_EQUAL(host_output[2], boost::make_tuple('z', 4, 3.14f));
+ BOOST_CHECK_EQUAL(host_output[3], boost::make_tuple('z', 4, 3.14f));
+ BOOST_CHECK_EQUAL(host_output[4], boost::make_tuple('z', 4, 3.14f));
+}
+
+#ifndef BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+BOOST_AUTO_TEST_CASE(variadic_tuple)
+{
+ BOOST_CHECK_EQUAL(
+ (compute::type_name<boost::tuple<char, short, int, float> >()),
+ "boost_tuple_char_short_int_float_t"
+ );
+}
+#endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
+
+#ifndef BOOST_COMPUTE_NO_STD_TUPLE
+BOOST_AUTO_TEST_CASE(std_tuple)
+{
+ BOOST_CHECK_EQUAL(
+ (compute::type_name<std::tuple<char, short, int, float>>()),
+ "std_tuple_char_short_int_float_t"
+ );
+}
+#endif // BOOST_COMPUTE_NO_STD_TUPLE
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_type_traits.cpp b/src/boost/libs/compute/test/test_type_traits.cpp
new file mode 100644
index 00000000..9654a286
--- /dev/null
+++ b/src/boost/libs/compute/test/test_type_traits.cpp
@@ -0,0 +1,131 @@
+//---------------------------------------------------------------------------//
+// 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 TestTypeTraits
+#include <boost/test/unit_test.hpp>
+
+#include <set>
+#include <list>
+#include <vector>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/compute/types.hpp>
+#include <boost/compute/type_traits.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+#include <boost/compute/detail/is_buffer_iterator.hpp>
+#include <boost/compute/detail/is_contiguous_iterator.hpp>
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(scalar_type)
+{
+ BOOST_STATIC_ASSERT((boost::is_same<bc::scalar_type<bc::int_>::type, int>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::scalar_type<bc::int2_>::type, int>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::scalar_type<bc::float_>::type, float>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::scalar_type<bc::float4_>::type, float>::value));
+}
+
+BOOST_AUTO_TEST_CASE(vector_size)
+{
+ BOOST_STATIC_ASSERT(bc::vector_size<bc::int_>::value == 1);
+ BOOST_STATIC_ASSERT(bc::vector_size<bc::int2_>::value == 2);
+ BOOST_STATIC_ASSERT(bc::vector_size<bc::float_>::value == 1);
+ BOOST_STATIC_ASSERT(bc::vector_size<bc::float4_>::value == 4);
+}
+
+BOOST_AUTO_TEST_CASE(is_vector_type)
+{
+ BOOST_STATIC_ASSERT(bc::is_vector_type<bc::int_>::value == false);
+ BOOST_STATIC_ASSERT(bc::is_vector_type<bc::int2_>::value == true);
+ BOOST_STATIC_ASSERT(bc::is_vector_type<bc::float_>::value == false);
+ BOOST_STATIC_ASSERT(bc::is_vector_type<bc::float4_>::value == true);
+}
+
+BOOST_AUTO_TEST_CASE(make_vector_type)
+{
+ BOOST_STATIC_ASSERT((boost::is_same<bc::make_vector_type<cl_uint, 2>::type, bc::uint2_>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::make_vector_type<int, 4>::type, bc::int4_>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::make_vector_type<float, 8>::type, bc::float8_>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<bc::make_vector_type<bc::char_, 16>::type, bc::char16_>::value));
+}
+
+BOOST_AUTO_TEST_CASE(is_fundamental_type)
+{
+ BOOST_STATIC_ASSERT((bc::is_fundamental<int>::value == true));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<bc::int_>::value == true));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<bc::int2_>::value == true));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<float>::value == true));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<bc::float_>::value == true));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<bc::float4_>::value == true));
+
+ BOOST_STATIC_ASSERT((bc::is_fundamental<std::pair<int, float> >::value == false));
+ BOOST_STATIC_ASSERT((bc::is_fundamental<std::complex<float> >::value == false));
+}
+
+BOOST_AUTO_TEST_CASE(type_name)
+{
+ // scalar types
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::char_>(), "char") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::uchar_>(), "uchar") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::short_>(), "short") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::ushort_>(), "ushort") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::int_>(), "int") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::uint_>(), "uint") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::long_>(), "long") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::ulong_>(), "ulong") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::float_>(), "float") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::double_>(), "double") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bool>(), "bool") == 0);
+
+ // vector types
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::char16_>(), "char16") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::uint4_>(), "uint4") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::ulong8_>(), "ulong8") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::float2_>(), "float2") == 0);
+ BOOST_CHECK(std::strcmp(bc::type_name<bc::double4_>(), "double4") == 0);
+}
+
+BOOST_AUTO_TEST_CASE(is_contiguous_iterator)
+{
+ using boost::compute::detail::is_contiguous_iterator;
+
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<int *>::value == true);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::vector<int>::iterator>::value == true);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::vector<int>::const_iterator>::value == true);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::list<int>::iterator>::value == false);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::set<int>::iterator>::value == false);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::insert_iterator<std::set<int> > >::value == false);
+ BOOST_STATIC_ASSERT(is_contiguous_iterator<std::back_insert_iterator<std::vector<int> > >::value == false);
+}
+
+BOOST_AUTO_TEST_CASE(is_buffer_iterator)
+{
+ using boost::compute::detail::is_buffer_iterator;
+
+ BOOST_STATIC_ASSERT(is_buffer_iterator<boost::compute::buffer_iterator<int> >::value == true);
+ BOOST_STATIC_ASSERT(is_buffer_iterator<boost::compute::constant_iterator<int> >::value == false);
+}
+
+BOOST_AUTO_TEST_CASE(is_device_iterator)
+{
+ using boost::compute::is_device_iterator;
+
+ BOOST_STATIC_ASSERT(is_device_iterator<boost::compute::buffer_iterator<int> >::value == true);
+ BOOST_STATIC_ASSERT(is_device_iterator<const boost::compute::buffer_iterator<int> >::value == true);
+ BOOST_STATIC_ASSERT(is_device_iterator<boost::compute::constant_iterator<int> >::value == true);
+ BOOST_STATIC_ASSERT(is_device_iterator<const boost::compute::constant_iterator<int> >::value == true);
+ BOOST_STATIC_ASSERT(is_device_iterator<float *>::value == false);
+ BOOST_STATIC_ASSERT(is_device_iterator<const float *>::value == false);
+ BOOST_STATIC_ASSERT(is_device_iterator<std::vector<int>::iterator>::value == false);
+ BOOST_STATIC_ASSERT(is_device_iterator<const std::vector<int>::iterator>::value == false);
+}
diff --git a/src/boost/libs/compute/test/test_types.cpp b/src/boost/libs/compute/test/test_types.cpp
new file mode 100644
index 00000000..3ee0e791
--- /dev/null
+++ b/src/boost/libs/compute/test/test_types.cpp
@@ -0,0 +1,97 @@
+//---------------------------------------------------------------------------//
+// 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 TestTypes
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <sstream>
+
+#include <boost/compute/types/fundamental.hpp>
+
+BOOST_AUTO_TEST_CASE(vector_ctor)
+{
+ boost::compute::int4_ i4(1, 2, 3, 4);
+ BOOST_CHECK(i4 == boost::compute::int4_(1, 2, 3, 4));
+ BOOST_CHECK_EQUAL(i4, boost::compute::int4_(1, 2, 3, 4));
+ BOOST_CHECK_EQUAL(i4[0], 1);
+ BOOST_CHECK_EQUAL(i4[1], 2);
+ BOOST_CHECK_EQUAL(i4[2], 3);
+ BOOST_CHECK_EQUAL(i4[3], 4);
+
+ i4 = boost::compute::int4_(1);
+ BOOST_CHECK(i4 == boost::compute::int4_(1, 1, 1, 1));
+ BOOST_CHECK(i4 == (boost::compute::vector_type<int, size_t(4)>(1)));
+ BOOST_CHECK_EQUAL(i4, boost::compute::int4_(1, 1, 1, 1));
+ BOOST_CHECK_EQUAL(i4[0], 1);
+ BOOST_CHECK_EQUAL(i4[1], 1);
+ BOOST_CHECK_EQUAL(i4[2], 1);
+ BOOST_CHECK_EQUAL(i4[3], 1);
+}
+
+BOOST_AUTO_TEST_CASE(vector_string)
+{
+ std::stringstream stream;
+ stream << boost::compute::int2_(1, 2);
+ BOOST_CHECK_EQUAL(stream.str(), std::string("int2(1, 2)"));
+}
+
+BOOST_AUTO_TEST_CASE(vector_accessors_basic)
+{
+ boost::compute::float4_ v;
+ v.x = 1;
+ v.y = 2;
+ v.z = 3;
+ v.w = 4;
+ BOOST_CHECK(v == boost::compute::float4_(1, 2, 3, 4));
+}
+
+BOOST_AUTO_TEST_CASE(vector_accessors_all)
+{
+ boost::compute::int2_ i2(1, 2);
+ BOOST_CHECK_EQUAL(i2.x, 1);
+ BOOST_CHECK_EQUAL(i2.y, 2);
+
+ boost::compute::int4_ i4(1, 2, 3, 4);
+ BOOST_CHECK_EQUAL(i4.x, 1);
+ BOOST_CHECK_EQUAL(i4.y, 2);
+ BOOST_CHECK_EQUAL(i4.z, 3);
+ BOOST_CHECK_EQUAL(i4.w, 4);
+
+ boost::compute::int8_ i8(1, 2, 3, 4, 5, 6, 7, 8);
+ BOOST_CHECK_EQUAL(i8.s0, 1);
+ BOOST_CHECK_EQUAL(i8.s1, 2);
+ BOOST_CHECK_EQUAL(i8.s2, 3);
+ BOOST_CHECK_EQUAL(i8.s3, 4);
+ BOOST_CHECK_EQUAL(i8.s4, 5);
+ BOOST_CHECK_EQUAL(i8.s5, 6);
+ BOOST_CHECK_EQUAL(i8.s6, 7);
+ BOOST_CHECK_EQUAL(i8.s7, 8);
+
+ boost::compute::int16_ i16(
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16);
+ BOOST_CHECK_EQUAL(i16.s0, 1);
+ BOOST_CHECK_EQUAL(i16.s1, 2);
+ BOOST_CHECK_EQUAL(i16.s2, 3);
+ BOOST_CHECK_EQUAL(i16.s3, 4);
+ BOOST_CHECK_EQUAL(i16.s4, 5);
+ BOOST_CHECK_EQUAL(i16.s5, 6);
+ BOOST_CHECK_EQUAL(i16.s6, 7);
+ BOOST_CHECK_EQUAL(i16.s7, 8);
+ BOOST_CHECK_EQUAL(i16.s8, 9);
+ BOOST_CHECK_EQUAL(i16.s9, 10);
+ BOOST_CHECK_EQUAL(i16.sa, 11);
+ BOOST_CHECK_EQUAL(i16.sb, 12);
+ BOOST_CHECK_EQUAL(i16.sc, 13);
+ BOOST_CHECK_EQUAL(i16.sd, 14);
+ BOOST_CHECK_EQUAL(i16.se, 15);
+ BOOST_CHECK_EQUAL(i16.sf, 16);
+}
diff --git a/src/boost/libs/compute/test/test_uniform_int_distribution.cpp b/src/boost/libs/compute/test/test_uniform_int_distribution.cpp
new file mode 100644
index 00000000..55338a28
--- /dev/null
+++ b/src/boost/libs/compute/test/test_uniform_int_distribution.cpp
@@ -0,0 +1,77 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestUniformIntDistribution
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_int_distribution.hpp>
+#include <boost/compute/lambda.hpp>
+
+#include "context_setup.hpp"
+
+namespace compute=boost::compute;
+
+BOOST_AUTO_TEST_CASE(uniform_int_distribution_doctest)
+{
+ using boost::compute::uint_;
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<uint_> vec(128, context);
+
+//! [generate]
+// initialize the default random engine
+boost::compute::default_random_engine engine(queue);
+
+// setup the uniform distribution to produce integers 0 and 1
+boost::compute::uniform_int_distribution<uint_> distribution(0, 1);
+
+// generate the random values and store them to 'vec'
+distribution.generate(vec.begin(), vec.end(), engine, queue);
+//! [generate]
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 > 1, queue
+ ),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(issue159) {
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<int> input(10, context);
+
+ // generate random numbers between 1 and 10
+ compute::default_random_engine rng(queue);
+ compute::uniform_int_distribution<int> d(1, 10);
+ d.generate(input.begin(), input.end(), rng, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ input.begin(), input.end(), _1 > 10, queue
+ ),
+ size_t(0)
+ );
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ input.begin(), input.end(), _1 < 1, queue
+ ),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_uniform_real_distribution.cpp b/src/boost/libs/compute/test/test_uniform_real_distribution.cpp
new file mode 100644
index 00000000..d5394427
--- /dev/null
+++ b/src/boost/libs/compute/test/test_uniform_real_distribution.cpp
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestUniformRealDistribution
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/function.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_real_distribution.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(uniform_real_distribution_doctest)
+{
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<float> vec(128, context);
+
+//! [generate]
+// initialize the default random engine
+boost::compute::default_random_engine engine(queue);
+
+// setup the uniform distribution to produce floats between 1 and 100
+boost::compute::uniform_real_distribution<float> distribution(1.0f, 100.0f);
+
+// generate the random values and store them to 'vec'
+distribution.generate(vec.begin(), vec.end(), engine, queue);
+//! [generate]
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 < 1.0f || _1 >= 100.0f, queue
+ ),
+ size_t(0)
+ );
+}
+
+template<class T>
+class range_test_engine
+{
+public:
+ explicit range_test_engine(boost::compute::command_queue &queue) {
+ (void) queue;
+ }
+
+ template<class OutputIterator, class Function>
+ void generate(OutputIterator first, OutputIterator last, Function op, boost::compute::command_queue &queue)
+ {
+ boost::compute::vector<T> tmp(std::distance(first, last), queue.get_context());
+
+ BOOST_COMPUTE_FUNCTION(T, max_random, (const T x),
+ {
+ if(get_global_id(0) < 1)
+ return (ValueType) MAX_RANDOM;
+ else
+ return (ValueType) 0;
+ });
+
+ max_random.define("MAX_RANDOM", "UINT_MAX");
+ max_random.define("ValueType", boost::compute::type_name<T>());
+
+ boost::compute::transform(tmp.begin(), tmp.end(), tmp.begin(), max_random, queue);
+ boost::compute::transform(tmp.begin(), tmp.end(), first, op, queue);
+ }
+};
+
+// For checking if result is in the correct range [low, hi)
+BOOST_AUTO_TEST_CASE(uniform_real_distribution_range)
+{
+ using boost::compute::lambda::_1;
+
+ boost::compute::vector<float> vec(32, context);
+
+ // initialize the range_test_engine
+ range_test_engine<boost::compute::uint_> engine(queue);
+
+ // setup the uniform distribution to produce floats between 0.9 and 1.0
+ boost::compute::uniform_real_distribution<float> distribution(0.9f, 1.0f);
+
+ // generate the random values and store them to 'vec'
+ distribution.generate(vec.begin(), vec.end(), engine, queue);
+
+ BOOST_CHECK_EQUAL(
+ boost::compute::count_if(
+ vec.begin(), vec.end(), _1 < 0.9f || _1 >= 1.0f, queue
+ ),
+ size_t(0)
+ );
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_unique.cpp b/src/boost/libs/compute/test/test_unique.cpp
new file mode 100644
index 00000000..f754323b
--- /dev/null
+++ b/src/boost/libs/compute/test/test_unique.cpp
@@ -0,0 +1,96 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestUnique
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/algorithm/none_of.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/algorithm/unique.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(unique_int)
+{
+ int data[] = {1, 6, 6, 4, 2, 2, 4};
+
+ compute::vector<int> input(data, data + 7, queue);
+
+ compute::vector<int>::iterator iter =
+ compute::unique(input.begin(), input.end(), queue);
+
+ BOOST_VERIFY(iter == input.begin() + 5);
+ CHECK_RANGE_EQUAL(int, 7, input, (1, 6, 4, 2, 4, 2, 4));
+}
+
+BOOST_AUTO_TEST_CASE(all_same_float)
+{
+ compute::vector<float> vec(1024, context);
+ compute::fill(vec.begin(), vec.end(), 3.14f, queue);
+
+ compute::vector<float>::iterator iter =
+ compute::unique(vec.begin(), vec.end(), queue);
+
+ BOOST_VERIFY(iter == vec.begin() + 1);
+
+ float first;
+ compute::copy_n(vec.begin(), 1, &first, queue);
+ BOOST_CHECK_EQUAL(first, 3.14f);
+}
+
+BOOST_AUTO_TEST_CASE(unique_even_uints)
+{
+ using compute::uint_;
+
+ // create vector filled with [0, 1, 2, ...]
+ compute::vector<uint_> vec(1024, context);
+ compute::iota(vec.begin(), vec.end(), 0, queue);
+
+ // all should be unique
+ compute::vector<uint_>::iterator iter = compute::unique(
+ vec.begin(), vec.end(), queue
+ );
+ BOOST_VERIFY(iter == vec.end());
+
+ // if odd, return the prior even number, else return the number
+ BOOST_COMPUTE_FUNCTION(uint_, odd_to_even, (uint_ x),
+ {
+ if(x & 1){
+ return x - 1;
+ }
+ else {
+ return x;
+ }
+ });
+
+ // set all odd numbers the previous even number
+ compute::transform(
+ vec.begin(), vec.end(), vec.begin(), odd_to_even, queue
+ );
+
+ // now the vector should contain [0, 0, 2, 2, 4, 4, ...]
+ iter = compute::unique(vec.begin(), vec.end(), queue);
+ BOOST_VERIFY(iter == vec.begin() + (vec.size() / 2));
+
+ // ensure all of the values are even
+ BOOST_COMPUTE_FUNCTION(bool, is_odd, (uint_ x),
+ {
+ return x & 1;
+ });
+ BOOST_VERIFY(compute::none_of(vec.begin(), vec.end(), is_odd, queue));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_unique_copy.cpp b/src/boost/libs/compute/test/test_unique_copy.cpp
new file mode 100644
index 00000000..eaaf55e1
--- /dev/null
+++ b/src/boost/libs/compute/test/test_unique_copy.cpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Roshan <thisisroshansmail@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 TestUniqueCopy
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/algorithm/unique_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(unique_copy_int)
+{
+ int data[] = {1, 6, 6, 4, 2, 2, 4};
+
+ bc::vector<int> input(data, data + 7, queue);
+ bc::vector<int> result(5, context);
+
+ bc::vector<int>::iterator iter =
+ bc::unique_copy(input.begin(), input.end(), result.begin(), queue);
+
+ BOOST_VERIFY(iter == result.begin() + 5);
+ CHECK_RANGE_EQUAL(int, 5, result, (1, 6, 4, 2, 4));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_unsupported_extension.cpp b/src/boost/libs/compute/test/test_unsupported_extension.cpp
new file mode 100644
index 00000000..d87198d0
--- /dev/null
+++ b/src/boost/libs/compute/test/test_unsupported_extension.cpp
@@ -0,0 +1,18 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Fabian Köhler <fabian2804@googlemail.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 TestUnsupportedExtension
+#include <boost/test/unit_test.hpp>
+#include <boost/compute/exception/unsupported_extension_error.hpp>
+
+BOOST_AUTO_TEST_CASE(unsupported_extension_error_what)
+{
+ boost::compute::unsupported_extension_error error("CL_DUMMY_EXTENSION");
+ BOOST_CHECK_EQUAL(std::string(error.what()), std::string("OpenCL extension CL_DUMMY_EXTENSION not supported"));
+}
diff --git a/src/boost/libs/compute/test/test_user_defined_types.cpp b/src/boost/libs/compute/test/test_user_defined_types.cpp
new file mode 100644
index 00000000..d9f75169
--- /dev/null
+++ b/src/boost/libs/compute/test/test_user_defined_types.cpp
@@ -0,0 +1,122 @@
+//---------------------------------------------------------------------------//
+// 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 TestUserDefinedTypes
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/struct.hpp>
+
+namespace compute = boost::compute;
+
+// user-defined data type containing two int's and a float
+struct UDD
+{
+ int a;
+ int b;
+ float c;
+};
+
+// make UDD available to OpenCL
+BOOST_COMPUTE_ADAPT_STRUCT(UDD, UDD, (a, b, c))
+
+// comparison operator for UDD
+bool operator==(const UDD &lhs, const UDD &rhs)
+{
+ return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c;
+}
+
+// output stream operator for UDD
+std::ostream& operator<<(std::ostream &stream, const UDD &x)
+{
+ return stream << "(" << x.a << ", " << x.b << ", " << x.c << ")";
+}
+
+// function to generate a random UDD on the host
+UDD rand_UDD()
+{
+ UDD udd;
+ udd.a = rand() % 100;
+ udd.b = rand() % 100;
+ udd.c = (float)(rand() % 100) / 1.3f;
+
+ return udd;
+}
+
+// function to compare two UDD's on the host by their first component
+bool compare_UDD_host(const UDD &lhs, const UDD &rhs)
+{
+ return lhs.a < rhs.a;
+}
+
+// function to compate two UDD's on the device by their first component
+BOOST_COMPUTE_FUNCTION(bool, compare_UDD_device, (UDD lhs, UDD rhs),
+{
+ return lhs.a < rhs.a;
+});
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+// see: issue #11 (https://github.com/boostorg/compute/issues/11)
+BOOST_AUTO_TEST_CASE(issue_11)
+{
+ if(device.vendor() == "NVIDIA" && device.platform().name() == "Apple"){
+ // FIXME: this test currently segfaults on NVIDIA GPUs on Apple
+ std::cerr << "skipping issue test on NVIDIA GPU on Apple platform" << std::endl;
+ return;
+ }
+
+ // create vector of random values on the host
+ std::vector<UDD> host_vector(10);
+ std::generate(host_vector.begin(), host_vector.end(), rand_UDD);
+
+ // transfer the values to the device
+ compute::vector<UDD> device_vector(host_vector.size(), context);
+ compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // sort values on the device
+ compute::sort(
+ device_vector.begin(),
+ device_vector.end(),
+ compare_UDD_device,
+ queue
+ );
+
+ // sort values on the host
+ std::sort(
+ host_vector.begin(),
+ host_vector.end(),
+ compare_UDD_host
+ );
+
+ // copy sorted device values back to the host
+ std::vector<UDD> tmp(10);
+ compute::copy(
+ device_vector.begin(),
+ device_vector.end(),
+ tmp.begin(),
+ queue
+ );
+
+ // verify sorted values
+ for(size_t i = 0; i < host_vector.size(); i++){
+ BOOST_CHECK_EQUAL(tmp[i], host_vector[i]);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_user_event.cpp b/src/boost/libs/compute/test/test_user_event.cpp
new file mode 100644
index 00000000..2afbd146
--- /dev/null
+++ b/src/boost/libs/compute/test/test_user_event.cpp
@@ -0,0 +1,35 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestUserEvent
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/user_event.hpp>
+
+#include "context_setup.hpp"
+
+BOOST_AUTO_TEST_CASE(empty){}
+
+#ifdef BOOST_COMPUTE_CL_VERSION_1_1
+BOOST_AUTO_TEST_CASE(user_event)
+{
+ REQUIRES_OPENCL_VERSION(1, 1);
+
+ boost::compute::user_event event(context);
+ BOOST_CHECK(event.get() != cl_event());
+ BOOST_CHECK(event.status() != CL_COMPLETE);
+
+ event.set_status(CL_COMPLETE);
+ event.wait();
+ BOOST_CHECK(event.status() == CL_COMPLETE);
+}
+#endif // BOOST_COMPUTE_CL_VERSION_1_1
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_valarray.cpp b/src/boost/libs/compute/test/test_valarray.cpp
new file mode 100644
index 00000000..f6c97673
--- /dev/null
+++ b/src/boost/libs/compute/test/test_valarray.cpp
@@ -0,0 +1,361 @@
+//---------------------------------------------------------------------------//
+// 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 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()
diff --git a/src/boost/libs/compute/test/test_vector.cpp b/src/boost/libs/compute/test/test_vector.cpp
new file mode 100644
index 00000000..c3dd8b79
--- /dev/null
+++ b/src/boost/libs/compute/test/test_vector.cpp
@@ -0,0 +1,502 @@
+//---------------------------------------------------------------------------//
+// 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 TestVector
+#include <boost/test/unit_test.hpp>
+#include <boost/concept_check.hpp>
+
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/algorithm/remove.hpp>
+#include <boost/compute/allocator/pinned_allocator.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "quirks.hpp"
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(concept_check)
+{
+ BOOST_CONCEPT_ASSERT((boost::Container<bc::vector<int> >));
+ //BOOST_CONCEPT_ASSERT((boost::SequenceConcept<bc::vector<int> >));
+ BOOST_CONCEPT_ASSERT((boost::ReversibleContainer<bc::vector<int> >));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<bc::vector<int>::iterator>));
+ BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<bc::vector<int>::const_iterator>));
+}
+
+BOOST_AUTO_TEST_CASE(size)
+{
+ bc::vector<int> empty_vector(context);
+ BOOST_CHECK_EQUAL(empty_vector.size(), size_t(0));
+ BOOST_CHECK_EQUAL(empty_vector.empty(), true);
+
+ bc::vector<int> int_vector(10, context);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(10));
+ BOOST_CHECK_EQUAL(int_vector.empty(), false);
+}
+
+BOOST_AUTO_TEST_CASE(resize)
+{
+ bc::vector<int> int_vector(10, context);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(10));
+
+ int_vector.resize(20, queue);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(20));
+
+ int_vector.resize(5, queue);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(5));
+}
+
+BOOST_AUTO_TEST_CASE(reserve)
+{
+ const float growth_factor = 1.5f;
+
+ bc::vector<int> int_vector(10, context);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(10));
+ BOOST_CHECK_EQUAL(int_vector.capacity(), size_t(10));
+
+ int_vector.reserve(20, queue);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(10));
+ BOOST_CHECK_EQUAL(int_vector.capacity(), size_t(20 * growth_factor));
+
+ int_vector.reserve(5, queue);
+ BOOST_CHECK_EQUAL(int_vector.size(), size_t(10));
+ BOOST_CHECK_EQUAL(int_vector.capacity(), size_t(20 * growth_factor));
+}
+
+BOOST_AUTO_TEST_CASE(array_operator)
+{
+ bc::vector<int> vector(10, context);
+ bc::fill(vector.begin(), vector.end(), 0, queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ bc::fill(vector.begin(), vector.end(), 42, queue);
+ CHECK_RANGE_EQUAL(int, 10, vector, (42, 42, 42, 42, 42, 42, 42, 42, 42, 42));
+
+ vector[0] = 9;
+ CHECK_RANGE_EQUAL(int, 10, vector, (9, 42, 42, 42, 42, 42, 42, 42, 42, 42));
+}
+
+BOOST_AUTO_TEST_CASE(front_and_back)
+{
+ int int_data[] = { 1, 2, 3, 4, 5 };
+ bc::vector<int> int_vector(5, context);
+ bc::copy(int_data, int_data + 5, int_vector.begin(), queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int_vector.front(), 1);
+ BOOST_CHECK_EQUAL(int_vector.back(), 5);
+
+ bc::fill(int_vector.begin(), int_vector.end(), 10, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(int_vector.front(), 10);
+ BOOST_CHECK_EQUAL(int_vector.back(), 10);
+
+ float float_data[] = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
+ bc::vector<float> float_vector(5, context);
+ bc::copy(float_data, float_data + 5, float_vector.begin(), queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(float_vector.front(), 1.1f);
+ BOOST_CHECK_EQUAL(float_vector.back(), 5.5f);
+}
+
+BOOST_AUTO_TEST_CASE(host_iterator_constructor)
+{
+ std::vector<int> host_vector;
+ host_vector.push_back(10);
+ host_vector.push_back(20);
+ host_vector.push_back(30);
+ host_vector.push_back(40);
+
+ bc::vector<int> device_vector(host_vector.begin(), host_vector.end(),
+ queue);
+ CHECK_RANGE_EQUAL(int, 4, device_vector, (10, 20, 30, 40));
+}
+
+BOOST_AUTO_TEST_CASE(device_iterator_constructor)
+{
+ int data[] = { 1, 5, 10, 15 };
+ bc::vector<int> a(data, data + 4, queue);
+ CHECK_RANGE_EQUAL(int, 4, a, (1, 5, 10, 15));
+
+ bc::vector<int> b(a.begin(), a.end(), queue);
+ CHECK_RANGE_EQUAL(int, 4, b, (1, 5, 10, 15));
+}
+
+BOOST_AUTO_TEST_CASE(push_back)
+{
+ bc::vector<int> vector(context);
+ BOOST_VERIFY(vector.empty());
+
+ vector.push_back(12, queue);
+ BOOST_VERIFY(!vector.empty());
+ BOOST_CHECK_EQUAL(vector.size(), size_t(1));
+ CHECK_RANGE_EQUAL(int, 1, vector, (12));
+
+ vector.push_back(24, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(2));
+ CHECK_RANGE_EQUAL(int, 2, vector, (12, 24));
+
+ vector.push_back(36, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(3));
+ CHECK_RANGE_EQUAL(int, 3, vector, (12, 24, 36));
+
+ for(int i = 0; i < 100; i++){
+ vector.push_back(i, queue);
+ }
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.size(), size_t(103));
+ BOOST_CHECK_EQUAL(vector[0], 12);
+ BOOST_CHECK_EQUAL(vector[1], 24);
+ BOOST_CHECK_EQUAL(vector[2], 36);
+ BOOST_CHECK_EQUAL(vector[102], 99);
+}
+
+BOOST_AUTO_TEST_CASE(at)
+{
+ bc::vector<int> vector(context);
+ vector.push_back(1, queue);
+ vector.push_back(2, queue);
+ vector.push_back(3, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.at(0), 1);
+ BOOST_CHECK_EQUAL(vector.at(1), 2);
+ BOOST_CHECK_EQUAL(vector.at(2), 3);
+ BOOST_CHECK_THROW(vector.at(3), std::out_of_range);
+}
+
+BOOST_AUTO_TEST_CASE(erase)
+{
+ int data[] = { 1, 2, 5, 7, 9 };
+ bc::vector<int> vector(data, data + 5, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.size(), size_t(5));
+
+ vector.erase(vector.begin() + 1, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, vector, (1, 5, 7, 9));
+
+ vector.erase(vector.begin() + 2, vector.end(), queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(2));
+ CHECK_RANGE_EQUAL(int, 2, vector, (1, 5));
+}
+
+BOOST_AUTO_TEST_CASE(max_size)
+{
+ bc::vector<int> vector(100, context);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(100));
+ BOOST_VERIFY(vector.max_size() > vector.size());
+}
+
+#ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
+BOOST_AUTO_TEST_CASE(move_ctor)
+{
+ int data[] = { 11, 12, 13, 14 };
+ bc::vector<int> a(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ bc::vector<int> b(std::move(a));
+ BOOST_CHECK(a.size() == 0);
+ BOOST_CHECK(a.get_buffer().get() == 0);
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+}
+
+BOOST_AUTO_TEST_CASE(move_ctor_custom_alloc)
+{
+ int data[] = { 11, 12, 13, 14 };
+ bc::vector<int, bc::pinned_allocator<int> > a(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ bc::vector<int, bc::pinned_allocator<int> > b(std::move(a));
+ BOOST_CHECK(a.size() == 0);
+ BOOST_CHECK(a.get_buffer().get() == 0);
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+}
+#endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
+
+#ifdef BOOST_COMPUTE_USE_CPP11
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+BOOST_AUTO_TEST_CASE(initializer_list_ctor)
+{
+ // ctor with std::initializer_list<T> always uses
+ // default_queue in this case
+ bc::vector<int> vector = { 2, -4, 6, 8 };
+ BOOST_CHECK_EQUAL(vector.size(), size_t(4));
+ BOOST_CHECK_EQUAL(vector[0], 2);
+ BOOST_CHECK_EQUAL(vector[1], -4);
+ BOOST_CHECK_EQUAL(vector[2], 6);
+ BOOST_CHECK_EQUAL(vector[3], 8);
+}
+#endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+#endif // BOOST_COMPUTE_USE_CPP11
+
+BOOST_AUTO_TEST_CASE(vector_double)
+{
+ if(!device.supports_extension("cl_khr_fp64")){
+ return;
+ }
+
+ bc::vector<double> vector(context);
+ vector.push_back(1.21, queue);
+ vector.push_back(3.14, queue);
+ vector.push_back(7.89, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(3));
+ CHECK_RANGE_EQUAL(double, 3, vector, (1.21, 3.14, 7.89));
+
+ bc::vector<double> other(vector.begin(), vector.end(), queue);
+ CHECK_RANGE_EQUAL(double, 3, other, (1.21, 3.14, 7.89));
+
+ bc::fill(other.begin(), other.end(), 8.95, queue);
+ CHECK_RANGE_EQUAL(double, 3, other, (8.95, 8.95, 8.95));
+}
+
+BOOST_AUTO_TEST_CASE(vector_iterator)
+{
+ bc::vector<int> vector(context);
+ vector.push_back(2, queue);
+ vector.push_back(4, queue);
+ vector.push_back(6, queue);
+ vector.push_back(8, queue);
+ queue.finish();
+ BOOST_CHECK_EQUAL(vector.size(), size_t(4));
+ BOOST_CHECK_EQUAL(vector[0], 2);
+ BOOST_CHECK_EQUAL(*vector.begin(), 2);
+ BOOST_CHECK_EQUAL(vector.begin()[0], 2);
+ BOOST_CHECK_EQUAL(vector[1], 4);
+ BOOST_CHECK_EQUAL(*(vector.begin()+1), 4);
+ BOOST_CHECK_EQUAL(vector.begin()[1], 4);
+ BOOST_CHECK_EQUAL(vector[2], 6);
+ BOOST_CHECK_EQUAL(*(vector.begin()+2), 6);
+ BOOST_CHECK_EQUAL(vector.begin()[2], 6);
+ BOOST_CHECK_EQUAL(vector[3], 8);
+ BOOST_CHECK_EQUAL(*(vector.begin()+3), 8);
+ BOOST_CHECK_EQUAL(vector.begin()[3], 8);
+}
+
+BOOST_AUTO_TEST_CASE(vector_erase_remove)
+{
+ int data[] = { 2, 6, 3, 4, 2, 4, 5, 6, 1 };
+ bc::vector<int> vector(data, data + 9, queue);
+ BOOST_CHECK_EQUAL(vector.size(), size_t(9));
+
+ // remove 4's
+ vector.erase(bc::remove(vector.begin(), vector.end(), 4, queue), vector.end());
+ BOOST_CHECK_EQUAL(vector.size(), size_t(7));
+ BOOST_VERIFY(bc::find(vector.begin(), vector.end(), 4, queue) == vector.end());
+
+ // remove 2's
+ vector.erase(bc::remove(vector.begin(), vector.end(), 2, queue), vector.end());
+ BOOST_CHECK_EQUAL(vector.size(), size_t(5));
+ BOOST_VERIFY(bc::find(vector.begin(), vector.end(), 2, queue) == vector.end());
+
+ // remove 6's
+ vector.erase(bc::remove(vector.begin(), vector.end(), 6, queue), vector.end());
+ BOOST_CHECK_EQUAL(vector.size(), size_t(3));
+ BOOST_VERIFY(bc::find(vector.begin(), vector.end(), 6, queue) == vector.end());
+
+ // check the rest of the values
+ CHECK_RANGE_EQUAL(int, 3, vector, (3, 5, 1));
+}
+
+// see issue #132 (https://github.com/boostorg/compute/issues/132)
+BOOST_AUTO_TEST_CASE(swap_between_contexts)
+{
+ compute::context ctx1(device);
+ compute::context ctx2(device);
+
+ compute::vector<int> vec1(32, ctx1);
+ compute::vector<int> vec2(32, ctx2);
+
+ BOOST_CHECK(vec1.get_allocator().get_context() == ctx1);
+ BOOST_CHECK(vec2.get_allocator().get_context() == ctx2);
+
+ vec1.swap(vec2);
+
+ BOOST_CHECK(vec1.get_allocator().get_context() == ctx2);
+ BOOST_CHECK(vec2.get_allocator().get_context() == ctx1);
+
+ vec1.resize(64);
+ vec2.resize(64);
+}
+
+BOOST_AUTO_TEST_CASE(assign_from_std_vector)
+{
+ std::vector<int> host_vector;
+ host_vector.push_back(1);
+ host_vector.push_back(9);
+ host_vector.push_back(7);
+ host_vector.push_back(9);
+
+ compute::vector<int> device_vector(context);
+ device_vector.assign(host_vector.begin(), host_vector.end(), queue);
+ BOOST_CHECK_EQUAL(device_vector.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, device_vector, (1, 9, 7, 9));
+}
+
+BOOST_AUTO_TEST_CASE(assign_constant_value)
+{
+ compute::vector<float> device_vector(10, context);
+ device_vector.assign(3, 6.28f, queue);
+ BOOST_CHECK_EQUAL(device_vector.size(), size_t(3));
+ CHECK_RANGE_EQUAL(float, 3, device_vector, (6.28f, 6.28f, 6.28f));
+}
+
+BOOST_AUTO_TEST_CASE(resize_throw_exception)
+{
+ if(bug_in_clcreatebuffer(device)) {
+ std::cerr
+ << "skipping resize_throw_exception test on Apple platform"
+ << std::endl;
+ return;
+ }
+
+ // create vector with eight items
+ int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ compute::vector<int> vec(data, data + 8, queue);
+
+ // try to resize to 2x larger than the global memory size
+ BOOST_CHECK_THROW(
+ vec.resize((device.global_memory_size() / sizeof(int)) * 2),
+ boost::compute::opencl_error
+ );
+
+ // ensure vector data is still the same
+ BOOST_CHECK_EQUAL(vec.size(), size_t(8));
+ CHECK_RANGE_EQUAL(int, 8, vec, (1, 2, 3, 4, 5, 6, 7, 8));
+}
+
+BOOST_AUTO_TEST_CASE(copy_ctor_custom_alloc)
+{
+ int data[] = { 11, 12, 13, 14 };
+ bc::vector<int, bc::pinned_allocator<int> > a(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ bc::vector<int, bc::pinned_allocator<int> > b(a, queue);
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+}
+
+BOOST_AUTO_TEST_CASE(copy_ctor_different_alloc)
+{
+ int data[] = { 11, 12, 13, 14 };
+ bc::vector<int> a(data, data + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ bc::vector<int, bc::pinned_allocator<int> > b(a, queue);
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+
+ std::vector<int> host_vector;
+ host_vector.push_back(1);
+ host_vector.push_back(9);
+ host_vector.push_back(7);
+ host_vector.push_back(9);
+
+ bc::vector<int, bc::pinned_allocator<int> > c(host_vector, queue);
+ BOOST_CHECK_EQUAL(c.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, c, (1, 9, 7, 9));
+}
+
+BOOST_AUTO_TEST_CASE(assignment_operator)
+{
+ int adata[] = { 11, 12, 13, 14 };
+ bc::vector<int> a(adata, adata + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ bc::vector<int> b = a;
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+
+ bc::vector<int, bc::pinned_allocator<int> > c(context);
+ c = b;
+ BOOST_CHECK_EQUAL(c.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, c, (11, 12, 13, 14));
+
+ int ddata[] = { 21, 22, 23 };
+ bc::vector<int, bc::pinned_allocator<int> > d(ddata, ddata + 3, queue);
+ BOOST_CHECK_EQUAL(d.size(), size_t(3));
+ CHECK_RANGE_EQUAL(int, 3, d, (21, 22, 23));
+
+ a = d;
+ BOOST_CHECK_EQUAL(a.size(), size_t(3));
+ CHECK_RANGE_EQUAL(int, 3, a, (21, 22, 23));
+
+ std::vector<int> host_vector;
+ host_vector.push_back(1);
+ host_vector.push_back(9);
+ host_vector.push_back(7);
+ host_vector.push_back(9);
+
+ d = host_vector;
+ BOOST_CHECK_EQUAL(d.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, d, (1, 9, 7, 9));
+}
+
+BOOST_AUTO_TEST_CASE(swap_ctor_custom_alloc)
+{
+ int adata[] = { 11, 12, 13, 14 };
+ bc::vector<int, bc::pinned_allocator<int> > a(adata, adata + 4, queue);
+ BOOST_CHECK_EQUAL(a.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, a, (11, 12, 13, 14));
+
+ int bdata[] = { 21, 22, 23 };
+ bc::vector<int, bc::pinned_allocator<int> > b(bdata, bdata + 3, queue);
+ BOOST_CHECK_EQUAL(b.size(), size_t(3));
+ CHECK_RANGE_EQUAL(int, 3, b, (21, 22, 23));
+
+ a.swap(b);
+ BOOST_CHECK_EQUAL(a.size(), size_t(3));
+ CHECK_RANGE_EQUAL(int, 3, a, (21, 22, 23));
+ BOOST_CHECK_EQUAL(b.size(), size_t(4));
+ CHECK_RANGE_EQUAL(int, 4, b, (11, 12, 13, 14));
+}
+
+BOOST_AUTO_TEST_CASE(shrink_to_fit)
+{
+ bc::vector<bc::int_> int_vector(5, context);
+ BOOST_CHECK_EQUAL(int_vector.size(), 5);
+ BOOST_CHECK(int_vector.capacity() >= 5);
+
+ int_vector.reserve(15);
+ BOOST_CHECK_EQUAL(int_vector.size(), 5);
+ BOOST_CHECK(int_vector.capacity() >= 15);
+
+ int_vector.shrink_to_fit();
+ BOOST_CHECK_EQUAL(int_vector.size(), 5);
+ BOOST_CHECK_EQUAL(int_vector.capacity(), 5);
+
+ int_vector.clear();
+ BOOST_CHECK_EQUAL(int_vector.size(), 0);
+ BOOST_CHECK_EQUAL(int_vector.capacity(), 5);
+
+ int_vector.shrink_to_fit();
+ BOOST_CHECK_EQUAL(int_vector.size(), 0);
+ BOOST_CHECK_EQUAL(int_vector.capacity(), 0);
+
+ int_vector.reserve(15);
+ BOOST_CHECK_EQUAL(int_vector.size(), 0);
+ BOOST_CHECK(int_vector.capacity() >= 15);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_wait_list.cpp b/src/boost/libs/compute/test/test_wait_list.cpp
new file mode 100644
index 00000000..f6e0570a
--- /dev/null
+++ b/src/boost/libs/compute/test/test_wait_list.cpp
@@ -0,0 +1,82 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 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 TestWaitList
+#include <boost/test/unit_test.hpp>
+
+#include <algorithm>
+#include <vector>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/wait_list.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(create_wait_list)
+{
+ compute::wait_list events;
+ BOOST_CHECK_EQUAL(events.size(), size_t(0));
+ BOOST_CHECK_EQUAL(events.empty(), true);
+ BOOST_CHECK(events.get_event_ptr() == 0);
+}
+
+#ifndef BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+BOOST_AUTO_TEST_CASE(create_wait_list_from_initializer_list)
+{
+ compute::event event0;
+ compute::event event1;
+ compute::event event2;
+ compute::wait_list events = { event0, event1, event2 };
+ BOOST_CHECK_EQUAL(events.size(), size_t(3));
+ CHECK_RANGE_EQUAL(compute::event, 3, events, (event0, event1, event2));
+}
+#endif // BOOST_COMPUTE_NO_HDR_INITIALIZER_LIST
+
+BOOST_AUTO_TEST_CASE(insert_future)
+{
+ // create vector on the host
+ std::vector<int> host_vector(4);
+ std::fill(host_vector.begin(), host_vector.end(), 7);
+
+ // create vector on the device
+ compute::vector<int> device_vector(4, context);
+
+ // create wait list
+ compute::wait_list events;
+
+ // copy values to device
+ compute::future<void> future = compute::copy_async(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // add future event to the wait list
+ events.insert(future);
+ BOOST_CHECK_EQUAL(events.size(), size_t(1));
+ BOOST_CHECK(events.get_event_ptr() != 0);
+
+ // wait for copy to complete
+ events.wait();
+
+ // check values
+ CHECK_RANGE_EQUAL(int, 4, device_vector, (7, 7, 7, 7));
+
+ // clear the event list
+ events.clear();
+ BOOST_CHECK_EQUAL(events.size(), size_t(0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/boost/libs/compute/test/test_zip_iterator.cpp b/src/boost/libs/compute/test/test_zip_iterator.cpp
new file mode 100644
index 00000000..ae76d580
--- /dev/null
+++ b/src/boost/libs/compute/test/test_zip_iterator.cpp
@@ -0,0 +1,232 @@
+//---------------------------------------------------------------------------//
+// 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 TestZipIterator
+#include <boost/test/unit_test.hpp>
+
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/tuple/tuple_io.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/constant_iterator.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+#include <boost/compute/types/tuple.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace compute = boost::compute;
+
+BOOST_AUTO_TEST_CASE(value_type)
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_same<
+ boost::compute::zip_iterator<
+ boost::tuple<
+ boost::compute::buffer_iterator<float>,
+ boost::compute::buffer_iterator<int>
+ >
+ >::value_type,
+ boost::tuple<float, int>
+ >::value
+ ));
+}
+
+BOOST_AUTO_TEST_CASE(distance)
+{
+ boost::compute::vector<char> char_vector(5, context);
+ boost::compute::vector<int> int_vector(5, context);
+
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.begin(),
+ int_vector.begin()
+ )
+ ),
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.end(),
+ int_vector.end()
+ )
+ )
+ ),
+ ptrdiff_t(5)
+ );
+
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.begin(),
+ int_vector.begin()
+ )
+ ) + 1,
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.end(),
+ int_vector.end()
+ )
+ ) - 1
+ ),
+ ptrdiff_t(3)
+ );
+
+ BOOST_CHECK_EQUAL(
+ std::distance(
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.begin() + 2,
+ int_vector.begin() + 2
+ )
+ ),
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.end() - 1,
+ int_vector.end() - 1
+ )
+ )
+ ),
+ ptrdiff_t(2)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(copy)
+{
+ // create three separate vectors of three different types
+ char char_data[] = { 'x', 'y', 'z' };
+ boost::compute::vector<char> char_vector(char_data, char_data + 3, queue);
+
+ int int_data[] = { 4, 7, 9 };
+ boost::compute::vector<int> int_vector(int_data, int_data + 3, queue);
+
+ float float_data[] = { 3.2f, 4.5f, 7.6f };
+ boost::compute::vector<float> float_vector(float_data, float_data + 3, queue);
+
+ // zip all three vectors into a single tuple vector
+ boost::compute::vector<boost::tuple<char, int, float> > tuple_vector(3, context);
+
+ boost::compute::copy(
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.begin(),
+ int_vector.begin(),
+ float_vector.begin()
+ )
+ ),
+ boost::compute::make_zip_iterator(
+ boost::make_tuple(
+ char_vector.end(),
+ int_vector.end(),
+ float_vector.end()
+ )
+ ),
+ tuple_vector.begin(),
+ queue
+ );
+
+ // copy tuple vector to host
+ std::vector<boost::tuple<char, int, float> > host_vector(3);
+
+ boost::compute::copy(
+ tuple_vector.begin(),
+ tuple_vector.end(),
+ host_vector.begin(),
+ queue
+ );
+
+ // check tuple values
+ BOOST_CHECK_EQUAL(host_vector[0], boost::make_tuple('x', 4, 3.2f));
+ BOOST_CHECK_EQUAL(host_vector[1], boost::make_tuple('y', 7, 4.5f));
+ BOOST_CHECK_EQUAL(host_vector[2], boost::make_tuple('z', 9, 7.6f));
+}
+
+BOOST_AUTO_TEST_CASE(zip_iterator_get)
+{
+ int data1[] = { 0, 2, 4, 6, 8 };
+ int data2[] = { 1, 3, 5, 7, 9 };
+
+ compute::vector<int> input1(data1, data1 + 5, queue);
+ compute::vector<int> input2(data2, data2 + 5, queue);
+ compute::vector<int> output(5, context);
+
+ // extract first component from (input1)
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.end())
+ ),
+ output.begin(),
+ compute::get<0>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (0, 2, 4, 6, 8));
+
+ // extract first component from (input2, input1)
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input2.begin(), input1.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input2.end(), input1.end())
+ ),
+ output.begin(),
+ compute::get<0>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 7, 9));
+
+ // extract second component from (input1, input2, input1)
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.begin(), input2.begin(), input1.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(input1.end(), input2.end(), input1.end())
+ ),
+ output.begin(),
+ compute::get<1>(),
+ queue
+ );
+ CHECK_RANGE_EQUAL(int, 5, output, (1, 3, 5, 7, 9));
+}
+
+BOOST_AUTO_TEST_CASE(zip_constant_iterator)
+{
+ compute::vector<int> result(4, context);
+
+ compute::transform(
+ compute::make_zip_iterator(
+ boost::make_tuple(
+ compute::make_constant_iterator(7)
+ )
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(
+ compute::make_constant_iterator(7, result.size())
+ )
+ ),
+ result.begin(),
+ compute::get<0>(),
+ queue
+ );
+
+ CHECK_RANGE_EQUAL(int, 4, result, (7, 7, 7, 7));
+}
+
+BOOST_AUTO_TEST_SUITE_END()