summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/compute
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/compute
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/compute')
-rw-r--r--src/boost/libs/compute/CMakeLists.txt129
-rw-r--r--src/boost/libs/compute/CONTRIBUTING.md46
-rw-r--r--src/boost/libs/compute/LICENSE_1_0.txt23
-rw-r--r--src/boost/libs/compute/README.md90
-rw-r--r--src/boost/libs/compute/cmake/BoostComputeConfig.cmake.in6
-rw-r--r--src/boost/libs/compute/cmake/FindBolt.cmake149
-rw-r--r--src/boost/libs/compute/cmake/FindEigen.cmake160
-rw-r--r--src/boost/libs/compute/cmake/FindTBB.cmake286
-rw-r--r--src/boost/libs/compute/cmake/opencl/FindOpenCL.cmake84
-rw-r--r--src/boost/libs/compute/example/CMakeLists.txt166
-rw-r--r--src/boost/libs/compute/example/amd_cpp_kernel.cpp116
-rw-r--r--src/boost/libs/compute/example/batched_determinant.cpp96
-rw-r--r--src/boost/libs/compute/example/black_scholes.cpp168
-rw-r--r--src/boost/libs/compute/example/copy_data.cpp49
-rw-r--r--src/boost/libs/compute/example/fizz_buzz.cpp160
-rw-r--r--src/boost/libs/compute/example/hello_world.cpp30
-rw-r--r--src/boost/libs/compute/example/host_sort.cpp56
-rw-r--r--src/boost/libs/compute/example/inline_ptx.cpp72
-rw-r--r--src/boost/libs/compute/example/k_means.cpp229
-rw-r--r--src/boost/libs/compute/example/list_devices.cpp45
-rw-r--r--src/boost/libs/compute/example/longest_vector.cpp58
-rw-r--r--src/boost/libs/compute/example/mandelbrot.cpp224
-rw-r--r--src/boost/libs/compute/example/mapped_view.cpp45
-rw-r--r--src/boost/libs/compute/example/matrix_transpose.cpp355
-rw-r--r--src/boost/libs/compute/example/memory_limits.cpp37
-rw-r--r--src/boost/libs/compute/example/monte_carlo.cpp73
-rw-r--r--src/boost/libs/compute/example/nbody.cpp236
-rw-r--r--src/boost/libs/compute/example/opencl_test.cpp165
-rw-r--r--src/boost/libs/compute/example/opencv_convolution.cpp265
-rw-r--r--src/boost/libs/compute/example/opencv_flip.cpp101
-rw-r--r--src/boost/libs/compute/example/opencv_histogram.cpp228
-rw-r--r--src/boost/libs/compute/example/opencv_optical_flow.cpp289
-rw-r--r--src/boost/libs/compute/example/opencv_sobel_filter.cpp254
-rw-r--r--src/boost/libs/compute/example/opengl_sphere.cpp242
-rw-r--r--src/boost/libs/compute/example/point_centroid.cpp68
-rw-r--r--src/boost/libs/compute/example/price_cross.cpp87
-rw-r--r--src/boost/libs/compute/example/print_vector.cpp45
-rw-r--r--src/boost/libs/compute/example/qimage_blur.cpp145
-rw-r--r--src/boost/libs/compute/example/random_walk.cpp153
-rw-r--r--src/boost/libs/compute/example/resize_image.cpp253
-rw-r--r--src/boost/libs/compute/example/simple_kernel.cpp84
-rw-r--r--src/boost/libs/compute/example/simple_moving_average.cpp139
-rw-r--r--src/boost/libs/compute/example/sort_vector.cpp68
-rw-r--r--src/boost/libs/compute/example/threefry_engine.cpp43
-rw-r--r--src/boost/libs/compute/example/time_copy.cpp63
-rw-r--r--src/boost/libs/compute/example/transform_sqrt.cpp58
-rw-r--r--src/boost/libs/compute/example/vector_addition.cpp57
-rw-r--r--src/boost/libs/compute/index.html20
-rw-r--r--src/boost/libs/compute/meta/libraries.json14
-rw-r--r--src/boost/libs/compute/perf/CMakeLists.txt210
-rw-r--r--src/boost/libs/compute/perf/perf.hpp109
-rwxr-xr-xsrc/boost/libs/compute/perf/perf.py238
-rw-r--r--src/boost/libs/compute/perf/perf_accumulate.cpp140
-rw-r--r--src/boost/libs/compute/perf/perf_bernoulli_distribution.cpp46
-rw-r--r--src/boost/libs/compute/perf/perf_binary_find.cpp71
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_accumulate.cpp51
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_count.cpp57
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_exclusive_scan.cpp52
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_fill.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_inner_product.cpp56
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_max_element.cpp69
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_merge.cpp60
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_partial_sum.cpp53
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_reduce_by_key.cpp100
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_saxpy.cpp76
-rw-r--r--src/boost/libs/compute/perf/perf_bolt_sort.cpp50
-rw-r--r--src/boost/libs/compute/perf/perf_cart_to_polar.cpp158
-rw-r--r--src/boost/libs/compute/perf/perf_comparison_sort.cpp86
-rw-r--r--src/boost/libs/compute/perf/perf_copy_if.cpp122
-rw-r--r--src/boost/libs/compute/perf/perf_copy_to_device.cpp55
-rw-r--r--src/boost/libs/compute/perf/perf_count.cpp77
-rw-r--r--src/boost/libs/compute/perf/perf_discrete_distribution.cpp48
-rw-r--r--src/boost/libs/compute/perf/perf_erase_remove.cpp61
-rw-r--r--src/boost/libs/compute/perf/perf_exclusive_scan.cpp97
-rw-r--r--src/boost/libs/compute/perf/perf_fill.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_find.cpp88
-rw-r--r--src/boost/libs/compute/perf/perf_find_end.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_host_sort.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_includes.cpp68
-rw-r--r--src/boost/libs/compute/perf/perf_inner_product.cpp74
-rw-r--r--src/boost/libs/compute/perf/perf_is_permutation.cpp66
-rw-r--r--src/boost/libs/compute/perf/perf_is_sorted.cpp63
-rw-r--r--src/boost/libs/compute/perf/perf_max_element.cpp93
-rw-r--r--src/boost/libs/compute/perf/perf_merge.cpp69
-rw-r--r--src/boost/libs/compute/perf/perf_next_permutation.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_nth_element.cpp60
-rw-r--r--src/boost/libs/compute/perf/perf_partial_sum.cpp97
-rw-r--r--src/boost/libs/compute/perf/perf_partition.cpp66
-rw-r--r--src/boost/libs/compute/perf/perf_partition_point.cpp68
-rw-r--r--src/boost/libs/compute/perf/perf_prev_permutation.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_random_number_engine.cpp101
-rw-r--r--src/boost/libs/compute/perf/perf_reduce_by_key.cpp114
-rw-r--r--src/boost/libs/compute/perf/perf_reverse.cpp60
-rw-r--r--src/boost/libs/compute/perf/perf_reverse_copy.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_rotate.cpp60
-rw-r--r--src/boost/libs/compute/perf/perf_rotate_copy.cpp62
-rw-r--r--src/boost/libs/compute/perf/perf_saxpy.cpp162
-rw-r--r--src/boost/libs/compute/perf/perf_search.cpp65
-rw-r--r--src/boost/libs/compute/perf/perf_search_n.cpp61
-rw-r--r--src/boost/libs/compute/perf/perf_set_difference.cpp75
-rw-r--r--src/boost/libs/compute/perf/perf_set_intersection.cpp75
-rw-r--r--src/boost/libs/compute/perf/perf_set_symmetric_difference.cpp75
-rw-r--r--src/boost/libs/compute/perf/perf_set_union.cpp75
-rw-r--r--src/boost/libs/compute/perf/perf_sort.cpp130
-rw-r--r--src/boost/libs/compute/perf/perf_sort_by_key.cpp79
-rw-r--r--src/boost/libs/compute/perf/perf_sort_float.cpp72
-rw-r--r--src/boost/libs/compute/perf/perf_stable_partition.cpp62
-rw-r--r--src/boost/libs/compute/perf/perf_stl_accumulate.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_stl_count.cpp45
-rw-r--r--src/boost/libs/compute/perf/perf_stl_find.cpp58
-rw-r--r--src/boost/libs/compute/perf/perf_stl_find_end.cpp44
-rw-r--r--src/boost/libs/compute/perf/perf_stl_includes.cpp48
-rw-r--r--src/boost/libs/compute/perf/perf_stl_inner_product.cpp46
-rw-r--r--src/boost/libs/compute/perf/perf_stl_is_permutation.cpp45
-rw-r--r--src/boost/libs/compute/perf/perf_stl_max_element.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_stl_merge.cpp38
-rw-r--r--src/boost/libs/compute/perf/perf_stl_next_permutation.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_stl_partial_sum.cpp51
-rw-r--r--src/boost/libs/compute/perf/perf_stl_partition.cpp46
-rw-r--r--src/boost/libs/compute/perf/perf_stl_partition_point.cpp48
-rw-r--r--src/boost/libs/compute/perf/perf_stl_prev_permutation.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_stl_reverse.cpp41
-rw-r--r--src/boost/libs/compute/perf/perf_stl_reverse_copy.cpp45
-rw-r--r--src/boost/libs/compute/perf/perf_stl_rotate.cpp41
-rw-r--r--src/boost/libs/compute/perf/perf_stl_rotate_copy.cpp43
-rw-r--r--src/boost/libs/compute/perf/perf_stl_saxpy.cpp52
-rw-r--r--src/boost/libs/compute/perf/perf_stl_search.cpp44
-rw-r--r--src/boost/libs/compute/perf/perf_stl_search_n.cpp41
-rw-r--r--src/boost/libs/compute/perf/perf_stl_set_difference.cpp54
-rw-r--r--src/boost/libs/compute/perf/perf_stl_set_intersection.cpp54
-rw-r--r--src/boost/libs/compute/perf/perf_stl_set_symmetric_difference.cpp54
-rw-r--r--src/boost/libs/compute/perf/perf_stl_set_union.cpp54
-rw-r--r--src/boost/libs/compute/perf/perf_stl_sort.cpp33
-rw-r--r--src/boost/libs/compute/perf/perf_stl_stable_partition.cpp47
-rw-r--r--src/boost/libs/compute/perf/perf_stl_unique.cpp41
-rw-r--r--src/boost/libs/compute/perf/perf_stl_unique_copy.cpp44
-rw-r--r--src/boost/libs/compute/perf/perf_tbb_accumulate.cpp75
-rw-r--r--src/boost/libs/compute/perf/perf_tbb_merge.cpp95
-rw-r--r--src/boost/libs/compute/perf/perf_tbb_sort.cpp35
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_accumulate.cu45
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_count.cu49
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_exclusive_scan.cu48
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_find.cu65
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_inner_product.cu49
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_merge.cu63
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_partial_sum.cu48
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_partition.cu60
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_reduce_by_key.cu92
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_reverse.cu48
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_reverse_copy.cu47
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_rotate.cu51
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_saxpy.cu63
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_set_difference.cu61
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_sort.cu48
-rw-r--r--src/boost/libs/compute/perf/perf_thrust_unique.cu50
-rw-r--r--src/boost/libs/compute/perf/perf_uniform_int_distribution.cpp46
-rw-r--r--src/boost/libs/compute/perf/perf_unique.cpp60
-rw-r--r--src/boost/libs/compute/perf/perf_unique_copy.cpp61
-rwxr-xr-xsrc/boost/libs/compute/perf/perfdoc.py70
-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
324 files changed, 34564 insertions, 0 deletions
diff --git a/src/boost/libs/compute/CMakeLists.txt b/src/boost/libs/compute/CMakeLists.txt
new file mode 100644
index 00000000..71e7722e
--- /dev/null
+++ b/src/boost/libs/compute/CMakeLists.txt
@@ -0,0 +1,129 @@
+# ---------------------------------------------------------------------------
+# 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
+#
+# ---------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 2.8)
+
+project(BoostCompute)
+
+set(CMAKE_MODULE_PATH ${BoostCompute_SOURCE_DIR}/cmake)
+if (CMAKE_VERSION VERSION_LESS "3.1.0")
+ list(APPEND CMAKE_MODULE_PATH "${BoostCompute_SOURCE_DIR}/cmake/opencl")
+endif()
+
+# find OpenCL
+find_package(OpenCL REQUIRED)
+include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS})
+
+# find Boost
+find_package(Boost 1.54 REQUIRED)
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
+
+# optional support for c++11
+option(BOOST_COMPUTE_USE_CPP11 "Use C++11 features" OFF)
+if(NOT MSVC)
+ if(${BOOST_COMPUTE_USE_CPP11})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ endif()
+endif()
+
+# optional support for offline-caching
+option(BOOST_COMPUTE_USE_OFFLINE_CACHE "Use offline cache for OpenCL program binaries" OFF)
+if(${BOOST_COMPUTE_USE_OFFLINE_CACHE})
+ add_definitions(-DBOOST_COMPUTE_USE_OFFLINE_CACHE)
+endif()
+
+# thread-safety options
+option(BOOST_COMPUTE_THREAD_SAFE "Compile with BOOST_COMPUTE_THREAD_SAFE defined" OFF)
+if(${BOOST_COMPUTE_THREAD_SAFE})
+ add_definitions(-DBOOST_COMPUTE_THREAD_SAFE)
+ if(${BOOST_COMPUTE_USE_CPP11})
+ if(MSVC)
+ if (MSVC_VERSION GREATER 1800)
+ add_definitions(-DBOOST_COMPUTE_HAVE_THREAD_LOCAL)
+ endif()
+ else()
+ add_definitions(-DBOOST_COMPUTE_HAVE_THREAD_LOCAL)
+ endif()
+ endif()
+endif()
+
+# optional third-party libraries
+option(BOOST_COMPUTE_HAVE_EIGEN "Have Eigen" OFF)
+option(BOOST_COMPUTE_HAVE_OPENCV "Have OpenCV" OFF)
+option(BOOST_COMPUTE_HAVE_QT "Have Qt" OFF)
+option(BOOST_COMPUTE_HAVE_VTK "Have VTK" OFF)
+option(BOOST_COMPUTE_HAVE_CUDA "Have CUDA" OFF)
+option(BOOST_COMPUTE_HAVE_TBB "Have TBB" OFF)
+option(BOOST_COMPUTE_HAVE_BOLT "Have BOLT" OFF)
+
+include_directories(include)
+
+if(${OpenCL_HEADER_CL_EXT_FOUND})
+ add_definitions(-DBOOST_COMPUTE_HAVE_HDR_CL_EXT)
+endif()
+
+if(WIN32)
+ # optional support for boost dynamic libraries
+ option(BOOST_COMPUTE_BOOST_ALL_DYN_LINK "Use boost dynamic link libraries" OFF)
+ if(${BOOST_COMPUTE_BOOST_ALL_DYN_LINK})
+ add_definitions(-DBOOST_ALL_DYN_LINK)
+ else()
+ # for default use statis libs
+ set(Boost_USE_STATIC_LIBS ON)
+ endif()
+ link_directories(${Boost_LIBRARY_DIRS})
+endif()
+
+# compiler options
+option(BOOST_COMPUTE_ENABLE_COVERAGE "Enable code coverage generation" OFF)
+
+# Visual Studio C++
+if(MSVC)
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+ add_definitions(-D_SCL_SECURE_NO_WARNINGS)
+ add_definitions(-DNOMINMAX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4003") # Not enough actual parameters for a BOOST_PP macro
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") # Warning C4244: 'initializing': conversion from 'double' to 'int', possible loss of data
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4305") # Warning C4305: 'initializing': truncation from 'double' to 'float'
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800") # Warning C4800: 'uint32_t' : forcing value to bool 'true' or 'false' (performance warning)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4838") # Warning C4838: conversion from 'double' to 'float' requires a narrowing conversion
+endif()
+
+option(BOOST_COMPUTE_BUILD_TESTS "Build the Boost.Compute tests" OFF)
+if(${BOOST_COMPUTE_BUILD_TESTS})
+ enable_testing()
+ add_subdirectory(test)
+endif()
+
+option(BOOST_COMPUTE_BUILD_BENCHMARKS "Build the Boost.Compute benchmarks" OFF)
+if(${BOOST_COMPUTE_BUILD_BENCHMARKS})
+ add_subdirectory(perf)
+endif()
+
+option(BOOST_COMPUTE_BUILD_EXAMPLES "Build the Boost.Compute examples" OFF)
+if(${BOOST_COMPUTE_BUILD_EXAMPLES})
+ add_subdirectory(example)
+endif()
+
+# configure cmake config file
+configure_file(
+ cmake/BoostComputeConfig.cmake.in
+ ${BoostCompute_BINARY_DIR}/BoostComputeConfig.cmake
+ @ONLY
+)
+
+# install cmake config file
+install(
+ FILES ${BoostCompute_BINARY_DIR}/BoostComputeConfig.cmake
+ DESTINATION lib/cmake/BoostCompute
+)
+
+# install header files
+install(DIRECTORY include/boost DESTINATION include/compute)
diff --git a/src/boost/libs/compute/CONTRIBUTING.md b/src/boost/libs/compute/CONTRIBUTING.md
new file mode 100644
index 00000000..d8b5fa23
--- /dev/null
+++ b/src/boost/libs/compute/CONTRIBUTING.md
@@ -0,0 +1,46 @@
+# Contributing to Boost.Compute #
+
+## Reporting Issues ##
+
+We value your feedback about issues you encounter. The more information you
+provide the easier it is for developers to resolve the problem.
+
+Issues should be reported to the [issue tracker](
+https://github.com/boostorg/compute/issues?state=open).
+
+Issues can also be used to submit feature requests.
+
+## Submitting Pull Requests ##
+
+Base your changes on `master` but submit your pull-request to `develop`. This
+can be changed by clicking the "Edit" button on the pull-request page. The
+develop branch is used for integration and testing of changes before merging
+into the stable `master` branch.
+
+Please try to rebase your changes on the current master branch before
+submitting. This keeps the git history cleaner and easier to understand.
+
+## Coding Style ##
+
+* Indentation is four-spaces (not tabs)
+* Try to keep line-length under 80 characters
+* Follow the STL/Boost naming conventions (e.g. lower case with underscores)
+* When in doubt, match the style of existing code
+* Otherwise, do whatever you want
+
+Also see the [Boost Library Requirements]
+(http://www.boost.org/development/requirements.html)).
+
+## Running Tests ##
+
+To build the tests you must enable the `BOOST_COMPUTE_BUILD_TESTS` option in
+`cmake`. The tests can be run by executing the `ctest` command from the build
+directory.
+
+Please report any tests failures to the issue tracker along with the test
+output and information on your system and compute device.
+
+## Support ##
+
+Feel free to send an email to kyle.r.lutz@gmail.com with any problems or
+questions.
diff --git a/src/boost/libs/compute/LICENSE_1_0.txt b/src/boost/libs/compute/LICENSE_1_0.txt
new file mode 100644
index 00000000..36b7cd93
--- /dev/null
+++ b/src/boost/libs/compute/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/boost/libs/compute/README.md b/src/boost/libs/compute/README.md
new file mode 100644
index 00000000..f8556116
--- /dev/null
+++ b/src/boost/libs/compute/README.md
@@ -0,0 +1,90 @@
+# Boost.Compute #
+
+[![Build Status](https://travis-ci.org/boostorg/compute.svg?branch=master)](https://travis-ci.org/boostorg/compute)
+[![Build status](https://ci.appveyor.com/api/projects/status/4s2nvfc97m7w23oi/branch/master?svg=true)](https://ci.appveyor.com/project/jszuppe/compute/branch/master)
+[![Coverage Status](https://coveralls.io/repos/boostorg/compute/badge.svg?branch=master)](https://coveralls.io/r/boostorg/compute)
+[![Gitter](https://badges.gitter.im/boostorg/compute.svg)](https://gitter.im/boostorg/compute?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+Boost.Compute is a GPU/parallel-computing library for C++ based on OpenCL.
+
+The core library is a thin C++ wrapper over the OpenCL API and provides
+access to compute devices, contexts, command queues and memory buffers.
+
+On top of the core library is a generic, STL-like interface providing common
+algorithms (e.g. `transform()`, `accumulate()`, `sort()`) along with common
+containers (e.g. `vector<T>`, `flat_set<T>`). It also features a number of
+extensions including parallel-computing algorithms (e.g. `exclusive_scan()`,
+`scatter()`, `reduce()`) and a number of fancy iterators (e.g.
+`transform_iterator<>`, `permutation_iterator<>`, `zip_iterator<>`).
+
+The full documentation is available at http://boostorg.github.io/compute/.
+
+## Example ##
+
+The following example shows how to sort a vector of floats on the GPU:
+
+```c++
+#include <vector>
+#include <algorithm>
+#include <boost/compute.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get the default compute device
+ compute::device gpu = compute::system::default_device();
+
+ // create a compute context and command queue
+ compute::context ctx(gpu);
+ compute::command_queue queue(ctx, gpu);
+
+ // generate random numbers on the host
+ std::vector<float> host_vector(1000000);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ // create vector on the device
+ compute::vector<float> device_vector(1000000, ctx);
+
+ // copy data to the device
+ compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // sort data on the device
+ compute::sort(
+ device_vector.begin(), device_vector.end(), queue
+ );
+
+ // copy data back to the host
+ compute::copy(
+ device_vector.begin(), device_vector.end(), host_vector.begin(), queue
+ );
+
+ return 0;
+}
+```
+
+Boost.Compute is a header-only library, so no linking is required. The example
+above can be compiled with:
+
+`g++ -I/path/to/compute/include sort.cpp -lOpenCL`
+
+More examples can be found in the [tutorial](
+http://boostorg.github.io/compute/boost_compute/tutorial.html) and under the
+[examples](https://github.com/boostorg/compute/tree/master/example) directory.
+
+## Support ##
+Questions about the library (both usage and development) can be posted to the
+[mailing list](https://groups.google.com/forum/#!forum/boost-compute).
+
+Bugs and feature requests can be reported through the [issue tracker](
+https://github.com/boostorg/compute/issues?state=open).
+
+Also feel free to send me an email with any problems, questions, or feedback.
+
+## Help Wanted ##
+The Boost.Compute project is currently looking for additional developers with
+interest in parallel computing.
+
+Please send an email to Kyle Lutz (kyle.r.lutz@gmail.com) for more information.
diff --git a/src/boost/libs/compute/cmake/BoostComputeConfig.cmake.in b/src/boost/libs/compute/cmake/BoostComputeConfig.cmake.in
new file mode 100644
index 00000000..5f03d0db
--- /dev/null
+++ b/src/boost/libs/compute/cmake/BoostComputeConfig.cmake.in
@@ -0,0 +1,6 @@
+# Config file for Boost.Compute (https://github.com/boostorg/compute)
+#
+# Sets the following variables:
+# BoostCompute_INCLUDE_DIRS - include directories for Boost.Compute
+
+set(BoostCompute_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/include/compute")
diff --git a/src/boost/libs/compute/cmake/FindBolt.cmake b/src/boost/libs/compute/cmake/FindBolt.cmake
new file mode 100644
index 00000000..0820de0d
--- /dev/null
+++ b/src/boost/libs/compute/cmake/FindBolt.cmake
@@ -0,0 +1,149 @@
+############################################################################
+# © 2012,2014 Advanced Micro Devices, Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+############################################################################
+
+# Locate an BOLT implementation.
+#
+# Defines the following variables:
+#
+# BOLT_FOUND - Found an Bolt imlementation
+#
+# Also defines the library variables below as normal
+# variables.
+#
+# BOLT_LIBRARIES - These contain debug/optimized keywords when a debugging library is found
+# BOLT_INCLUDE_DIRS - All relevant Bolt include directories
+#
+# Accepts the following variables as input:
+#
+# BOLT_ROOT - (as a CMake or environment variable)
+# The root directory of an BOLT installation
+#
+# FIND_LIBRARY_USE_LIB64_PATHS - Global property that controls whether FindBOLT should search for
+# 64bit or 32bit libs
+#
+#-----------------------
+# Example Usage:
+#
+# find_package(BOLT REQUIRED)
+# include_directories(${BOLT_INCLUDE_DIRS})
+#
+# add_executable(foo foo.cc)
+# target_link_libraries(foo ${BOLT_LIBRARIES})
+#
+#-----------------------
+
+# This module helps to use BOLT_FIND_COMPONENTS, BOLT_FIND_REQUIRED, BOLT_FIND_QUIETLY
+include( FindPackageHandleStandardArgs )
+
+# Search for 64bit libs if FIND_LIBRARY_USE_LIB64_PATHS is set to true in the global environment, 32bit libs else
+get_property( LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS )
+
+# Debug print statements
+#message( "BOLT_LIBRARY_PATH_SUFFIXES: ${BOLT_LIBRARY_PATH_SUFFIXES}" )
+#message( "ENV{BOLT_ROOT}: $ENV{BOLT_ROOT}" )
+#message( "BOLT_FIND_COMPONENTS: ${BOLT_FIND_COMPONENTS}" )
+#message( "BOLT_FIND_REQUIRED: ${BOLT_FIND_REQUIRED}" )
+
+# Set the component to find if the user does not specify explicitely
+if( NOT BOLT_FIND_COMPONENTS )
+ set( BOLT_FIND_COMPONENTS CL )
+endif( )
+if(WIN32)
+if( MSVC_VERSION VERSION_LESS 1600 )
+ set( myMSVCVer "vc90" )
+elseif( MSVC_VERSION VERSION_LESS 1700 )
+ set( myMSVCVer "vc100" )
+elseif( MSVC_VERSION VERSION_LESS 1800 )
+ set( myMSVCVer "vc110" )
+else()
+ set( myMSVCVer "vc120" )
+endif( )
+else()
+ set( myMSVCVer "gcc" )
+endif()
+
+if(WIN32)
+ set( BoltLibName "clBolt.runtime.${myMSVCVer}")
+ set( LIB_EXT "lib")
+else()
+ set( BoltLibName "libclBolt.runtime.${myMSVCVer}")
+ set( LIB_EXT "a")
+endif()
+
+# Eventually, Bolt may support multiple backends, but for now it only supports CL
+list( FIND BOLT_FIND_COMPONENTS CL find_CL )
+if( NOT find_CL EQUAL -1 )
+ set( BOLT_LIBNAME_BASE ${BoltLibName} )
+endif( )
+
+if( NOT find_CL EQUAL -1 )
+ # Find and set the location of main BOLT static lib file
+ find_library( BOLT_LIBRARY_STATIC_RELEASE
+ NAMES ${BOLT_LIBNAME_BASE}.${LIB_EXT}
+ HINTS
+ ${BOLT_ROOT}
+ ENV BOLT_ROOT
+ DOC "BOLT static library path"
+ PATH_SUFFIXES lib
+ )
+ mark_as_advanced( BOLT_LIBRARY_STATIC_RELEASE )
+
+ # Find and set the location of main BOLT static lib file
+ find_library( BOLT_LIBRARY_STATIC_DEBUG
+ NAMES ${BOLT_LIBNAME_BASE}.debug.${LIB_EXT}
+ HINTS
+ ${BOLT_ROOT}
+ ENV BOLT_ROOT
+ DOC "BOLT static library path"
+ PATH_SUFFIXES lib
+ )
+ mark_as_advanced( BOLT_LIBRARY_STATIC_DEBUG )
+
+ if( BOLT_LIBRARY_STATIC_RELEASE )
+ set( BOLT_LIBRARY_STATIC optimized ${BOLT_LIBRARY_STATIC_RELEASE} )
+ else( )
+ set( BOLT_LIBRARY_STATIC "" )
+ message( "${BOLT_LIBNAME_BASE}.${LIB_EXT}: Release static bolt library not found" )
+ endif( )
+
+ if( BOLT_LIBRARY_STATIC_DEBUG )
+ set( BOLT_LIBRARY_STATIC ${BOLT_LIBRARY_STATIC} debug ${BOLT_LIBRARY_STATIC_DEBUG} )
+ else( )
+ message( "${BOLT_LIBNAME_BASE}.debug.${LIB_EXT}: Debug static bolt library not found" )
+ endif( )
+
+ find_path( BOLT_INCLUDE_DIRS
+ NAMES bolt/cl/bolt.h
+ HINTS
+ ${BOLT_ROOT}
+ ENV BOLT_ROOT
+ DOC "BOLT header file path"
+ PATH_SUFFIXES include
+ )
+ mark_as_advanced( BOLT_INCLUDE_DIRS )
+
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS( BOLT DEFAULT_MSG BOLT_LIBRARY_STATIC BOLT_INCLUDE_DIRS )
+endif( )
+
+if( BOLT_FOUND )
+ list( APPEND BOLT_LIBRARIES ${BOLT_LIBRARY_STATIC} )
+else( )
+ if( NOT BOLT_FIND_QUIETLY )
+ message( WARNING "FindBOLT could not find the BOLT library" )
+ message( STATUS "Did you remember to set the BOLT_ROOT environment variable?" )
+ endif( )
+endif()
diff --git a/src/boost/libs/compute/cmake/FindEigen.cmake b/src/boost/libs/compute/cmake/FindEigen.cmake
new file mode 100644
index 00000000..2cd3e12c
--- /dev/null
+++ b/src/boost/libs/compute/cmake/FindEigen.cmake
@@ -0,0 +1,160 @@
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2013 Google Inc. All rights reserved.
+# http://code.google.com/p/ceres-solver/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: alexs.mac@gmail.com (Alex Stewart)
+#
+
+# FindEigen.cmake - Find Eigen library, version >= 3.
+#
+# This module defines the following variables:
+#
+# EIGEN_FOUND: TRUE iff Eigen is found.
+# EIGEN_INCLUDE_DIRS: Include directories for Eigen.
+#
+# EIGEN_VERSION: Extracted from Eigen/src/Core/util/Macros.h
+# EIGEN_WORLD_VERSION: Equal to 3 if EIGEN_VERSION = 3.2.0
+# EIGEN_MAJOR_VERSION: Equal to 2 if EIGEN_VERSION = 3.2.0
+# EIGEN_MINOR_VERSION: Equal to 0 if EIGEN_VERSION = 3.2.0
+#
+# The following variables control the behaviour of this module:
+#
+# EIGEN_INCLUDE_DIR_HINTS: List of additional directories in which to
+# search for eigen includes, e.g: /timbuktu/eigen3.
+#
+# The following variables are also defined by this module, but in line with
+# CMake recommended FindPackage() module style should NOT be referenced directly
+# by callers (use the plural variables detailed above instead). These variables
+# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
+# are NOT re-called (i.e. search for library is not repeated) if these variables
+# are set with valid values _in the CMake cache_. This means that if these
+# variables are set directly in the cache, either by the user in the CMake GUI,
+# or by the user passing -DVAR=VALUE directives to CMake when called (which
+# explicitly defines a cache variable), then they will be used verbatim,
+# bypassing the HINTS variables and other hard-coded search locations.
+#
+# EIGEN_INCLUDE_DIR: Include directory for CXSparse, not including the
+# include directory of any dependencies.
+
+# Called if we failed to find Eigen or any of it's required dependencies,
+# unsets all public (designed to be used externally) variables and reports
+# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
+MACRO(EIGEN_REPORT_NOT_FOUND REASON_MSG)
+ UNSET(EIGEN_FOUND)
+ UNSET(EIGEN_INCLUDE_DIRS)
+ # Make results of search visible in the CMake GUI if Eigen has not
+ # been found so that user does not have to toggle to advanced view.
+ MARK_AS_ADVANCED(CLEAR EIGEN_INCLUDE_DIR)
+ # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
+ # use the camelcase library name, not uppercase.
+ IF (Eigen_FIND_QUIETLY)
+ MESSAGE(STATUS "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
+ ELSEIF (Eigen_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Failed to find Eigen - " ${REASON_MSG} ${ARGN})
+ ELSE()
+ # Neither QUIETLY nor REQUIRED, use no priority which emits a message
+ # but continues configuration and allows generation.
+ MESSAGE("-- Failed to find Eigen - " ${REASON_MSG} ${ARGN})
+ ENDIF ()
+ENDMACRO(EIGEN_REPORT_NOT_FOUND)
+
+# Search user-installed locations first, so that we prefer user installs
+# to system installs where both exist.
+#
+# TODO: Add standard Windows search locations for Eigen.
+LIST(APPEND EIGEN_CHECK_INCLUDE_DIRS
+ /usr/local/include/eigen3
+ /usr/local/homebrew/include/eigen3 # Mac OS X
+ /opt/local/var/macports/software/eigen3 # Mac OS X.
+ /opt/local/include/eigen3
+ /usr/include/eigen3)
+
+# Search supplied hint directories first if supplied.
+FIND_PATH(EIGEN_INCLUDE_DIR
+ NAMES Eigen/Core
+ PATHS ${EIGEN_INCLUDE_DIR_HINTS}
+ ${EIGEN_CHECK_INCLUDE_DIRS})
+IF (NOT EIGEN_INCLUDE_DIR OR
+ NOT EXISTS ${EIGEN_INCLUDE_DIR})
+ EIGEN_REPORT_NOT_FOUND(
+ "Could not find eigen3 include directory, set EIGEN_INCLUDE_DIR to "
+ "path to eigen3 include directory, e.g. /usr/local/include/eigen3.")
+ENDIF (NOT EIGEN_INCLUDE_DIR OR
+ NOT EXISTS ${EIGEN_INCLUDE_DIR})
+
+# Mark internally as found, then verify. EIGEN_REPORT_NOT_FOUND() unsets
+# if called.
+SET(EIGEN_FOUND TRUE)
+
+# Extract Eigen version from Eigen/src/Core/util/Macros.h
+IF (EIGEN_INCLUDE_DIR)
+ SET(EIGEN_VERSION_FILE ${EIGEN_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h)
+ IF (NOT EXISTS ${EIGEN_VERSION_FILE})
+ EIGEN_REPORT_NOT_FOUND(
+ "Could not find file: ${EIGEN_VERSION_FILE} "
+ "containing version information in Eigen install located at: "
+ "${EIGEN_INCLUDE_DIR}.")
+ ELSE (NOT EXISTS ${EIGEN_VERSION_FILE})
+ FILE(READ ${EIGEN_VERSION_FILE} EIGEN_VERSION_FILE_CONTENTS)
+
+ STRING(REGEX MATCH "#define EIGEN_WORLD_VERSION [0-9]+"
+ EIGEN_WORLD_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
+ STRING(REGEX REPLACE "#define EIGEN_WORLD_VERSION ([0-9]+)" "\\1"
+ EIGEN_WORLD_VERSION "${EIGEN_WORLD_VERSION}")
+
+ STRING(REGEX MATCH "#define EIGEN_MAJOR_VERSION [0-9]+"
+ EIGEN_MAJOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
+ STRING(REGEX REPLACE "#define EIGEN_MAJOR_VERSION ([0-9]+)" "\\1"
+ EIGEN_MAJOR_VERSION "${EIGEN_MAJOR_VERSION}")
+
+ STRING(REGEX MATCH "#define EIGEN_MINOR_VERSION [0-9]+"
+ EIGEN_MINOR_VERSION "${EIGEN_VERSION_FILE_CONTENTS}")
+ STRING(REGEX REPLACE "#define EIGEN_MINOR_VERSION ([0-9]+)" "\\1"
+ EIGEN_MINOR_VERSION "${EIGEN_MINOR_VERSION}")
+
+ # This is on a single line s/t CMake does not interpret it as a list of
+ # elements and insert ';' separators which would result in 3.;2.;0 nonsense.
+ SET(EIGEN_VERSION "${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}")
+ ENDIF (NOT EXISTS ${EIGEN_VERSION_FILE})
+ENDIF (EIGEN_INCLUDE_DIR)
+
+# Set standard CMake FindPackage variables if found.
+IF (EIGEN_FOUND)
+ SET(EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR})
+ENDIF (EIGEN_FOUND)
+
+# Handle REQUIRED / QUIET optional arguments and version.
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Eigen
+ REQUIRED_VARS EIGEN_INCLUDE_DIRS
+ VERSION_VAR EIGEN_VERSION)
+
+# Only mark internal variables as advanced if we found Eigen, otherwise
+# leave it visible in the standard GUI for the user to set manually.
+IF (EIGEN_FOUND)
+ MARK_AS_ADVANCED(FORCE EIGEN_INCLUDE_DIR)
+ENDIF (EIGEN_FOUND)
diff --git a/src/boost/libs/compute/cmake/FindTBB.cmake b/src/boost/libs/compute/cmake/FindTBB.cmake
new file mode 100644
index 00000000..d299fd14
--- /dev/null
+++ b/src/boost/libs/compute/cmake/FindTBB.cmake
@@ -0,0 +1,286 @@
+# Locate Intel Threading Building Blocks include paths and libraries
+# FindTBB.cmake can be found at https://code.google.com/p/findtbb/
+# Written by Hannes Hofmann <hannes.hofmann _at_ informatik.uni-erlangen.de>
+# Improvements by Gino van den Bergen <gino _at_ dtecta.com>,
+# Florian Uhlig <F.Uhlig _at_ gsi.de>,
+# Jiri Marsik <jiri.marsik89 _at_ gmail.com>
+
+# The MIT License
+#
+# Copyright (c) 2011 Hannes Hofmann
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler.
+# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21"
+# TBB_ARCH_PLATFORM is set by the build script `tbbvars[.bat|.sh|.csh], which can be found
+# in the TBB installation directory (TBB_INSTALL_DIR).
+#
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+#
+# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER.
+# TBB_ARCHITECTURE [ ia32 | em64t | itanium ]
+# which architecture to use
+# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9
+# which compiler to use (detected automatically on Windows)
+
+# This module respects
+# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR}
+
+# This module defines
+# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc.
+# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc
+# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug
+# TBB_INSTALL_DIR, the base TBB install directory
+# TBB_LIBRARIES, the libraries to link against to use TBB.
+# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols.
+# TBB_FOUND, If false, don't try to use TBB.
+# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h
+
+
+if (WIN32)
+ # has em64t/vc8 em64t/vc9
+ # has ia32/vc7.1 ia32/vc8 ia32/vc9
+ set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB")
+ set(_TBB_LIB_NAME "tbb")
+ set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+ if (MSVC71)
+ set (_TBB_COMPILER "vc7.1")
+ endif(MSVC71)
+ if (MSVC80)
+ set(_TBB_COMPILER "vc8")
+ endif(MSVC80)
+ if (MSVC90)
+ set(_TBB_COMPILER "vc9")
+ endif(MSVC90)
+ if(MSVC10)
+ set(_TBB_COMPILER "vc10")
+ endif(MSVC10)
+ # Todo: add other Windows compilers such as ICL.
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+endif (WIN32)
+
+if (UNIX)
+ if (APPLE)
+ # MAC
+ set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions")
+ # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug
+ set(_TBB_LIB_NAME "tbb")
+ set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+ # default flavor on apple: ia32/cc4.0.1_os10.4.9
+ # Jiri: There is no reason to presume there is only one flavor and
+ # that user's setting of variables should be ignored.
+ if(NOT TBB_COMPILER)
+ set(_TBB_COMPILER "cc4.0.1_os10.4.9")
+ elseif (NOT TBB_COMPILER)
+ set(_TBB_COMPILER ${TBB_COMPILER})
+ endif(NOT TBB_COMPILER)
+ if(NOT TBB_ARCHITECTURE)
+ set(_TBB_ARCHITECTURE "ia32")
+ elseif(NOT TBB_ARCHITECTURE)
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+ endif(NOT TBB_ARCHITECTURE)
+ else (APPLE)
+ # LINUX
+ set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include")
+ set(_TBB_LIB_NAME "tbb")
+ set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc")
+ set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug")
+ set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug")
+ # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21
+ # has ia32/*
+ # has itanium/*
+ set(_TBB_COMPILER ${TBB_COMPILER})
+ set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE})
+ endif (APPLE)
+endif (UNIX)
+
+if (CMAKE_SYSTEM MATCHES "SunOS.*")
+# SUN
+# not yet supported
+# has em64t/cc3.4.3_kernel5.10
+# has ia32/*
+endif (CMAKE_SYSTEM MATCHES "SunOS.*")
+
+
+#-- Clear the public variables
+set (TBB_FOUND "NO")
+
+
+#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR}
+# first: use CMake variable TBB_INSTALL_DIR
+if (TBB_INSTALL_DIR)
+ set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR})
+endif (TBB_INSTALL_DIR)
+# second: use environment variable
+if (NOT _TBB_INSTALL_DIR)
+ if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR})
+ endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "")
+ # Intel recommends setting TBB21_INSTALL_DIR
+ if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR})
+ endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "")
+ if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR})
+ endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "")
+ if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+ set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR})
+ endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "")
+endif (NOT _TBB_INSTALL_DIR)
+# third: try to find path automatically
+if (NOT _TBB_INSTALL_DIR)
+ if (_TBB_DEFAULT_INSTALL_DIR)
+ set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR})
+ endif (_TBB_DEFAULT_INSTALL_DIR)
+endif (NOT _TBB_INSTALL_DIR)
+# sanity check
+if (NOT _TBB_INSTALL_DIR)
+ message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}")
+else (NOT _TBB_INSTALL_DIR)
+# finally: set the cached CMake variable TBB_INSTALL_DIR
+if (NOT TBB_INSTALL_DIR)
+ set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory")
+ mark_as_advanced(TBB_INSTALL_DIR)
+endif (NOT TBB_INSTALL_DIR)
+
+
+#-- A macro to rewrite the paths of the library. This is necessary, because
+# find_library() always found the em64t/vc9 version of the TBB libs
+macro(TBB_CORRECT_LIB_DIR var_name)
+# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+ string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t")
+ string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}})
+ string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+ string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+ string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+ string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}})
+endmacro(TBB_CORRECT_LIB_DIR var_content)
+
+
+#-- Look for include directory and set ${TBB_INCLUDE_DIR}
+set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include)
+# Jiri: tbbvars now sets the CPATH environment variable to the directory
+# containing the headers.
+find_path(TBB_INCLUDE_DIR
+ tbb/task_scheduler_init.h
+ PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH
+)
+mark_as_advanced(TBB_INCLUDE_DIR)
+
+
+#-- Look for libraries
+# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh]
+if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+ set (_TBB_LIBRARY_DIR
+ ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM}
+ ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib
+ )
+endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "")
+# Jiri: This block isn't mutually exclusive with the previous one
+# (hence no else), instead I test if the user really specified
+# the variables in question.
+if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+ # HH: deprecated
+ message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).")
+ # Jiri: It doesn't hurt to look in more places, so I store the hints from
+ # ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER
+ # variables and search them both.
+ set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR})
+endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL ""))
+
+# GvdB: Mac OS X distribution places libraries directly in lib directory.
+list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib)
+
+# Jiri: No reason not to check the default paths. From recent versions,
+# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH
+# variables, which now point to the directories of the lib files.
+# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS
+# argument instead of the implicit PATHS as it isn't hard-coded
+# but computed by system introspection. Searching the LIBRARY_PATH
+# and LD_LIBRARY_PATH environment variables is now even more important
+# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates
+# the use of TBB built from sources.
+find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+
+#Extract path from TBB_LIBRARY name
+get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_LIBRARY)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY)
+mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY)
+
+#-- Look for debug libraries
+# Jiri: Changed the same way as for the release libraries.
+find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR}
+ PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH)
+
+# Jiri: Self-built TBB stores the debug libraries in a separate directory.
+# Extract path from TBB_LIBRARY_DEBUG name
+get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH)
+
+#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG)
+#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG)
+mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG)
+
+
+if (TBB_INCLUDE_DIR)
+ if (TBB_LIBRARY)
+ set (TBB_FOUND "YES")
+ set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES})
+ set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES})
+ set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE)
+ set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE)
+ # Jiri: Self-built TBB stores the debug libraries in a separate directory.
+ set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE)
+ mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES)
+ message(STATUS "Found Intel TBB")
+ endif (TBB_LIBRARY)
+endif (TBB_INCLUDE_DIR)
+
+if (NOT TBB_FOUND)
+ message("ERROR: Intel TBB NOT found!")
+ message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}")
+ # do only throw fatal, if this pkg is REQUIRED
+ if (TBB_FIND_REQUIRED)
+ message(FATAL_ERROR "Could NOT find TBB library.
+ On ubuntu try
+ apt-get install libtbb-dev
+")
+ endif (TBB_FIND_REQUIRED)
+endif (NOT TBB_FOUND)
+
+endif (NOT _TBB_INSTALL_DIR)
+
+if (TBB_FOUND)
+ set(TBB_INTERFACE_VERSION 0)
+ FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
+ STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
+ set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
+endif (TBB_FOUND)
diff --git a/src/boost/libs/compute/cmake/opencl/FindOpenCL.cmake b/src/boost/libs/compute/cmake/opencl/FindOpenCL.cmake
new file mode 100644
index 00000000..0a60e8d1
--- /dev/null
+++ b/src/boost/libs/compute/cmake/opencl/FindOpenCL.cmake
@@ -0,0 +1,84 @@
+# - Try to find OpenCL
+# This module tries to find an OpenCL implementation on your system. It supports
+# AMD / ATI, Apple and NVIDIA implementations.
+#
+# To set the paths manually, define these environment variables:
+# OpenCL_INCPATH - Include path (e.g. OpenCL_INCPATH=/opt/cuda/4.0/cuda/include)
+# OpenCL_LIBPATH - Library path (e.h. OpenCL_LIBPATH=/usr/lib64/nvidia)
+#
+# Once done this will define
+# OpenCL_FOUND - system has OpenCL
+# OpenCL_INCLUDE_DIRS - the OpenCL include directory
+# OpenCL_LIBRARIES - link these to use OpenCL
+
+FIND_PACKAGE(PackageHandleStandardArgs)
+
+SET (OpenCL_VERSION_STRING "0.1.0")
+SET (OpenCL_VERSION_MAJOR 0)
+SET (OpenCL_VERSION_MINOR 1)
+SET (OpenCL_VERSION_PATCH 0)
+
+IF (APPLE)
+
+ FIND_LIBRARY(OpenCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX")
+ FIND_PATH(OpenCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX")
+ FIND_PATH(_OpenCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX")
+
+ELSE (APPLE)
+
+ IF (WIN32)
+ # The AMD SDK currently installs both x86 and x86_64 libraries
+ # This is only a hack to find out architecture
+ IF( CMAKE_SIZEOF_VOID_P EQUAL 8 )
+ SET(OpenCL_LIB_DIR "$ENV{AMDAPPSDKROOT}/lib/x86_64")
+ ELSE( CMAKE_SIZEOF_VOID_P EQUAL 8 )
+ SET(OpenCL_LIB_DIR "$ENV{AMDAPPSDKROOT}/lib/x86")
+ ENDIF( CMAKE_SIZEOF_VOID_P EQUAL 8 )
+
+ FIND_LIBRARY(OpenCL_LIBRARIES OpenCL.lib PATHS
+ ${OpenCL_LIB_DIR} $ENV{OpenCL_LIBPATH} $ENV{CUDA_LIB_PATH})
+
+ GET_FILENAME_COMPONENT(_OpenCL_INC_CAND ${OpenCL_LIB_DIR}/../../include ABSOLUTE)
+
+ # On Win32 search relative to the library
+ FIND_PATH(OpenCL_INCLUDE_DIRS CL/cl.h PATHS
+ ${_OpenCL_INC_CAND} $ENV{OpenCL_INCPATH} $ENV{CUDA_INC_PATH})
+ FIND_PATH(_OpenCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS
+ ${_OpenCL_INC_CAND} $ENV{OpenCL_INCPATH} $ENV{CUDA_INC_PATH})
+
+ ELSE (WIN32)
+
+ # Unix style platforms
+ FIND_LIBRARY(OpenCL_LIBRARIES OpenCL
+ PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH
+ )
+
+ GET_FILENAME_COMPONENT(OpenCL_LIB_DIR ${OpenCL_LIBRARIES} PATH)
+ GET_FILENAME_COMPONENT(_OpenCL_INC_CAND ${OpenCL_LIB_DIR}/../../include ABSOLUTE)
+
+ # The AMD SDK currently does not place its headers
+ # in /usr/include, therefore also search relative
+ # to the library
+ FIND_PATH(OpenCL_INCLUDE_DIRS CL/cl.h PATHS "$ENV{CUDADIR}/include" ${_OpenCL_INC_CAND} "/usr/local/cuda/include" "/opt/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH)
+ FIND_PATH(_OpenCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS "$ENV{CUDADIR}/include" ${_OpenCL_INC_CAND} "/usr/local/cuda/include" "/opt/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH)
+ # for Mali GPUs, libmali must be linked
+ FIND_LIBRARY(OpenCL_LIBRARIES_MALI mali
+ PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH "/usr/lib64" "$ENV{CUDADIR}/lib64"
+ )
+ IF (OpenCL_LIBRARIES_MALI)
+ SET(OpenCL_LIBRARIES ${OpenCL_LIBRARIES} ${OpenCL_LIBRARIES_MALI})
+ ENDIF (OpenCL_LIBRARIES_MALI)
+ ENDIF (WIN32)
+
+ENDIF (APPLE)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenCL DEFAULT_MSG OpenCL_LIBRARIES OpenCL_INCLUDE_DIRS)
+
+IF(_OpenCL_CPP_INCLUDE_DIRS)
+ SET( OpenCL_HAS_CPP_BINDINGS TRUE )
+ LIST( APPEND OpenCL_INCLUDE_DIRS ${_OpenCL_CPP_INCLUDE_DIRS} )
+ # This is often the same, so clean up
+ LIST( REMOVE_DUPLICATES OpenCL_INCLUDE_DIRS )
+ENDIF(_OpenCL_CPP_INCLUDE_DIRS)
+
+MARK_AS_ADVANCED( OpenCL_INCLUDE_DIRS )
diff --git a/src/boost/libs/compute/example/CMakeLists.txt b/src/boost/libs/compute/example/CMakeLists.txt
new file mode 100644
index 00000000..a5708cb0
--- /dev/null
+++ b/src/boost/libs/compute/example/CMakeLists.txt
@@ -0,0 +1,166 @@
+# ---------------------------------------------------------------------------
+# 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
+#
+# ---------------------------------------------------------------------------
+
+include_directories(../include)
+
+set(EXAMPLES
+ amd_cpp_kernel
+ black_scholes
+ copy_data
+ fizz_buzz
+ hello_world
+ host_sort
+ inline_ptx
+ longest_vector
+ list_devices
+ mapped_view
+ memory_limits
+ monte_carlo
+ point_centroid
+ price_cross
+ print_vector
+ sort_vector
+ simple_kernel
+ time_copy
+ transform_sqrt
+ vector_addition
+ simple_moving_average
+ matrix_transpose
+)
+
+# boost library link dependencies
+set(EXAMPLE_BOOST_COMPONENTS program_options)
+
+if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
+ set(EXAMPLE_BOOST_COMPONENTS ${EXAMPLE_BOOST_COMPONENTS} system filesystem)
+endif()
+
+if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
+ set(EXAMPLE_BOOST_COMPONENTS ${EXAMPLE_BOOST_COMPONENTS} system thread)
+endif()
+
+if(MSVC AND EXAMPLE_BOOST_COMPONENTS)
+ set(EXAMPLE_BOOST_COMPONENTS ${EXAMPLE_BOOST_COMPONENTS} chrono)
+endif()
+
+if(EXAMPLE_BOOST_COMPONENTS)
+ list(REMOVE_DUPLICATES EXAMPLE_BOOST_COMPONENTS)
+endif()
+find_package(Boost 1.54 REQUIRED COMPONENTS ${EXAMPLE_BOOST_COMPONENTS})
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
+
+foreach(EXAMPLE ${EXAMPLES})
+ add_executable(${EXAMPLE} ${EXAMPLE}.cpp)
+ target_link_libraries(${EXAMPLE} ${OpenCL_LIBRARIES} ${Boost_LIBRARIES})
+
+ # add example program to list of tests (if testing is enabled)
+ if(${BOOST_COMPUTE_BUILD_TESTS})
+ add_test("example.${EXAMPLE}" ${EXAMPLE})
+ endif()
+endforeach()
+
+# opencl test example
+add_executable(opencl_test opencl_test.cpp)
+target_link_libraries(opencl_test ${OpenCL_LIBRARIES})
+
+# eigen examples
+if(${BOOST_COMPUTE_HAVE_EIGEN})
+ find_package(Eigen REQUIRED)
+ include_directories(SYSTEM ${EIGEN_INCLUDE_DIRS})
+ add_executable(batched_determinant batched_determinant.cpp)
+ target_link_libraries(batched_determinant ${OpenCL_LIBRARIES} ${Boost_LIBRARIES})
+endif()
+
+# opencv examples
+if(${BOOST_COMPUTE_HAVE_OPENCV})
+ find_package(OpenCV REQUIRED)
+ include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
+
+ set(OPENCV_EXAMPLES
+ k_means
+ opencv_flip
+ random_walk
+ opencv_optical_flow
+ opencv_convolution
+ opencv_sobel_filter
+ opencv_histogram
+ )
+
+ foreach(EXAMPLE ${OPENCV_EXAMPLES})
+ add_executable(${EXAMPLE} ${EXAMPLE}.cpp)
+ target_link_libraries(${EXAMPLE} ${OpenCL_LIBRARIES} ${Boost_LIBRARIES} ${OpenCV_LIBS})
+ endforeach()
+endif()
+
+# opengl/vtk examples
+if(${BOOST_COMPUTE_HAVE_VTK})
+ find_package(VTK REQUIRED)
+ include(${VTK_USE_FILE})
+ add_executable(opengl_sphere opengl_sphere.cpp)
+ target_link_libraries(opengl_sphere ${OpenCL_LIBRARIES} ${Boost_LIBRARIES} ${VTK_LIBRARIES})
+ if(APPLE)
+ target_link_libraries(opengl_sphere "-framework OpenGL")
+ elseif(UNIX)
+ target_link_libraries(opengl_sphere GL)
+ endif()
+endif()
+
+# qt examples
+if(${BOOST_COMPUTE_HAVE_QT})
+
+ # look for Qt4 in the first place
+ find_package(Qt4 QUIET)
+
+ if(${QT4_FOUND})
+ # build with Qt4
+ find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtOpenGL)
+ set(QT_USE_QTOPENGL TRUE)
+ include(${QT_USE_FILE})
+ else()
+
+ # look for Qt5
+ find_package(Qt5Widgets QUIET)
+
+ if(${Qt5Widgets_FOUND})
+ # build with Qt5
+ find_package(Qt5Core REQUIRED)
+ find_package(Qt5Widgets REQUIRED)
+ find_package(Qt5OpenGL REQUIRED)
+ include_directories(${Qt5OpenGL_INCLUDE_DIRS})
+ 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()
+
+ # required by both versions
+ set(CMAKE_AUTOMOC TRUE)
+ include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+ # add examples
+ add_executable(qimage_blur qimage_blur.cpp)
+ target_link_libraries(qimage_blur ${OpenCL_LIBRARIES} ${Boost_LIBRARIES} ${QT_LIBRARIES})
+
+ set(QT_OPENGL_EXAMPLES
+ mandelbrot
+ nbody
+ resize_image
+ )
+ foreach(EXAMPLE ${QT_OPENGL_EXAMPLES})
+ add_executable(${EXAMPLE} ${EXAMPLE}.cpp)
+ target_link_libraries(${EXAMPLE} ${OpenCL_LIBRARIES} ${Boost_LIBRARIES} ${QT_LIBRARIES})
+ if(APPLE)
+ target_link_libraries(${EXAMPLE} "-framework OpenGL")
+ elseif(UNIX)
+ target_link_libraries(${EXAMPLE} GL)
+ endif()
+ endforeach()
+endif()
diff --git a/src/boost/libs/compute/example/amd_cpp_kernel.cpp b/src/boost/libs/compute/example/amd_cpp_kernel.cpp
new file mode 100644
index 00000000..0207312f
--- /dev/null
+++ b/src/boost/libs/compute/example/amd_cpp_kernel.cpp
@@ -0,0 +1,116 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to use the static c++ kernel language
+// extension (currently only supported by AMD) to compile and
+// execute a templated c++ kernel.
+// Using platform vendor info to decide if this is AMD platform
+int main()
+{
+ // get default device and setup context
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ // check the platform vendor string
+ if(device.platform().vendor() != "Advanced Micro Devices, Inc."){
+ std::cerr << "error: static C++ kernel language is only "
+ << "supported on AMD devices."
+ << std::endl;
+ return 0;
+ }
+
+ // create input int values and copy them to the device
+ int int_data[] = { 1, 2, 3, 4};
+ compute::vector<int> int_vector(int_data, int_data + 4, queue);
+
+ // create input float values and copy them to the device
+ float float_data[] = { 2.0f, 4.0f, 6.0f, 8.0f };
+ compute::vector<float> float_vector(float_data, float_data + 4, queue);
+
+ // create kernel source with a templated function and templated kernel
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // define our templated function which returns the square of its input
+ template<typename T>
+ inline T square(const T x)
+ {
+ return x * x;
+ }
+
+ // define our templated kernel which calls square on each value in data
+ template<typename T>
+ __kernel void square_kernel(__global T *data)
+ {
+ const uint i = get_global_id(0);
+ data[i] = square(data[i]);
+ }
+
+ // explicitly instantiate the square kernel for int's. this allows
+ // for it to be called from the host with the given mangled name.
+ template __attribute__((mangled_name(square_kernel_int)))
+ __kernel void square_kernel(__global int *data);
+
+ // also instantiate the square kernel for float's.
+ template __attribute__((mangled_name(square_kernel_float)))
+ __kernel void square_kernel(__global float *data);
+ );
+
+ // build the program. must enable the c++ static kernel language
+ // by passing the "-x clc++" compile option.
+ compute::program square_program =
+ compute::program::build_with_source(source, context, "-x clc++");
+
+ // create the square kernel for int's by using its mangled name declared
+ // in the explicit template instantiation.
+ compute::kernel square_int_kernel(square_program, "square_kernel_int");
+ square_int_kernel.set_arg(0, int_vector);
+
+ // execute the square int kernel
+ queue.enqueue_1d_range_kernel(square_int_kernel, 0, int_vector.size(), 4);
+
+ // print out the squared int values
+ std::cout << "int's: ";
+ compute::copy(
+ int_vector.begin(), int_vector.end(),
+ std::ostream_iterator<int>(std::cout, " "),
+ queue
+ );
+ std::cout << std::endl;
+
+ // now create the square kernel for float's
+ compute::kernel square_float_kernel(square_program, "square_kernel_float");
+ square_float_kernel.set_arg(0, float_vector);
+
+ // execute the square int kernel
+ queue.enqueue_1d_range_kernel(square_float_kernel, 0, float_vector.size(), 4);
+
+ // print out the squared float values
+ std::cout << "float's: ";
+ compute::copy(
+ float_vector.begin(), float_vector.end(),
+ std::ostream_iterator<float>(std::cout, " "),
+ queue
+ );
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/batched_determinant.cpp b/src/boost/libs/compute/example/batched_determinant.cpp
new file mode 100644
index 00000000..0029151e
--- /dev/null
+++ b/src/boost/libs/compute/example/batched_determinant.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+
+#include <Eigen/Core>
+#include <Eigen/LU>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to compute the determinant of many 4x4 matrices
+// using a determinant function and the transform() algorithm. in OpenCL the
+// float16 type can be used to store a 4x4 matrix and the components are laid
+// out in the following order:
+//
+// M = [ s0 s4 s8 sc ]
+// [ s1 s5 s9 sd ]
+// [ s2 s6 sa se ]
+// [ s3 s7 sb sf ]
+//
+// the input matrices are created using eigen's random matrix and then
+// used again at the end to verify the results of the determinant function.
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ size_t n = 1000;
+
+ // create random 4x4 matrices on the host
+ std::vector<Eigen::Matrix4f> matrices(n);
+ for(size_t i = 0; i < n; i++){
+ matrices[i] = Eigen::Matrix4f::Random();
+ }
+
+ // copy matrices to the device
+ using compute::float16_;
+ compute::vector<float16_> input(n, context);
+ compute::copy(
+ matrices.begin(), matrices.end(), input.begin(), queue
+ );
+
+ // function returning the determinant of a 4x4 matrix.
+ BOOST_COMPUTE_FUNCTION(float, determinant4x4, (const float16_ m),
+ {
+ return m.s0*m.s5*m.sa*m.sf + m.s0*m.s6*m.sb*m.sd + m.s0*m.s7*m.s9*m.se +
+ m.s1*m.s4*m.sb*m.se + m.s1*m.s6*m.s8*m.sf + m.s1*m.s7*m.sa*m.sc +
+ m.s2*m.s4*m.s9*m.sf + m.s2*m.s5*m.sb*m.sc + m.s2*m.s7*m.s8*m.sd +
+ m.s3*m.s4*m.sa*m.sd + m.s3*m.s5*m.s8*m.se + m.s3*m.s6*m.s9*m.sc -
+ m.s0*m.s5*m.sb*m.se - m.s0*m.s6*m.s9*m.sf - m.s0*m.s7*m.sa*m.sd -
+ m.s1*m.s4*m.sa*m.sf - m.s1*m.s6*m.sb*m.sc - m.s1*m.s7*m.s8*m.se -
+ m.s2*m.s4*m.sb*m.sd - m.s2*m.s5*m.s8*m.sf - m.s2*m.s7*m.s9*m.sc -
+ m.s3*m.s4*m.s9*m.se - m.s3*m.s5*m.sa*m.sc - m.s3*m.s6*m.s8*m.sd;
+ });
+
+ // calculate determinants on the gpu
+ compute::vector<float> determinants(n, context);
+ compute::transform(
+ input.begin(), input.end(), determinants.begin(), determinant4x4, queue
+ );
+
+ // check determinants
+ std::vector<float> host_determinants(n);
+ compute::copy(
+ determinants.begin(), determinants.end(), host_determinants.begin(), queue
+ );
+
+ for(size_t i = 0; i < n; i++){
+ float det = matrices[i].determinant();
+
+ if(std::abs(det - host_determinants[i]) > 1e-6){
+ std::cerr << "error: wrong determinant at " << i << " ("
+ << host_determinants[i] << " != " << det << ")"
+ << std::endl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/black_scholes.cpp b/src/boost/libs/compute/example/black_scholes.cpp
new file mode 100644
index 00000000..13a0e097
--- /dev/null
+++ b/src/boost/libs/compute/example/black_scholes.cpp
@@ -0,0 +1,168 @@
+//---------------------------------------------------------------------------//
+// 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 <cstdlib>
+#include <iostream>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// return a random float between lo and hi
+float rand_float(float lo, float hi)
+{
+ float x = (float) std::rand() / (float) RAND_MAX;
+
+ return (1.0f - x) * lo + x * hi;
+}
+
+// this example demostrates a black-scholes option pricing kernel.
+int main()
+{
+ // number of options
+ const int N = 4000000;
+
+ // black-scholes parameters
+ const float risk_free_rate = 0.02f;
+ const float volatility = 0.30f;
+
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // initialize option data on host
+ std::vector<float> stock_price_data(N);
+ std::vector<float> option_strike_data(N);
+ std::vector<float> option_years_data(N);
+
+ std::srand(5347);
+ for(int i = 0; i < N; i++){
+ stock_price_data[i] = rand_float(5.0f, 30.0f);
+ option_strike_data[i] = rand_float(1.0f, 100.0f);
+ option_years_data[i] = rand_float(0.25f, 10.0f);
+ }
+
+ // create memory buffers on the device
+ compute::vector<float> call_result(N, context);
+ compute::vector<float> put_result(N, context);
+ compute::vector<float> stock_price(N, context);
+ compute::vector<float> option_strike(N, context);
+ compute::vector<float> option_years(N, context);
+
+ // copy initial values to the device
+ compute::copy_n(stock_price_data.begin(), N, stock_price.begin(), queue);
+ compute::copy_n(option_strike_data.begin(), N, option_strike.begin(), queue);
+ compute::copy_n(option_years_data.begin(), N, option_years.begin(), queue);
+
+ // source code for black-scholes program
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // approximation of the cumulative normal distribution function
+ static float cnd(float d)
+ {
+ const float A1 = 0.319381530f;
+ const float A2 = -0.356563782f;
+ const float A3 = 1.781477937f;
+ const float A4 = -1.821255978f;
+ const float A5 = 1.330274429f;
+ const float RSQRT2PI = 0.39894228040143267793994605993438f;
+
+ float K = 1.0f / (1.0f + 0.2316419f * fabs(d));
+ float cnd =
+ RSQRT2PI * exp(-0.5f * d * d) *
+ (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5)))));
+
+ if(d > 0){
+ cnd = 1.0f - cnd;
+ }
+
+ return cnd;
+ }
+
+ // black-scholes option pricing kernel
+ __kernel void black_scholes(__global float *call_result,
+ __global float *put_result,
+ __global const float *stock_price,
+ __global const float *option_strike,
+ __global const float *option_years,
+ float risk_free_rate,
+ float volatility)
+ {
+ const uint opt = get_global_id(0);
+
+ float S = stock_price[opt];
+ float X = option_strike[opt];
+ float T = option_years[opt];
+ float R = risk_free_rate;
+ float V = volatility;
+
+ float sqrtT = sqrt(T);
+ float d1 = (log(S / X) + (R + 0.5f * V * V) * T) / (V * sqrtT);
+ float d2 = d1 - V * sqrtT;
+ float CNDD1 = cnd(d1);
+ float CNDD2 = cnd(d2);
+
+ float expRT = exp(-R * T);
+ call_result[opt] = S * CNDD1 - X * expRT * CNDD2;
+ put_result[opt] = X * expRT * (1.0f - CNDD2) - S * (1.0f - CNDD1);
+ }
+ );
+
+ // build black-scholes program
+ compute::program program = compute::program::create_with_source(source, context);
+ program.build();
+
+ // setup black-scholes kernel
+ compute::kernel kernel(program, "black_scholes");
+ kernel.set_arg(0, call_result);
+ kernel.set_arg(1, put_result);
+ kernel.set_arg(2, stock_price);
+ kernel.set_arg(3, option_strike);
+ kernel.set_arg(4, option_years);
+ kernel.set_arg(5, risk_free_rate);
+ kernel.set_arg(6, volatility);
+
+ // execute black-scholes kernel
+ queue.enqueue_1d_range_kernel(kernel, 0, N, 0);
+
+ // print out the first option's put and call prices
+ float call0, put0;
+ compute::copy_n(put_result.begin(), 1, &put0, queue);
+ compute::copy_n(call_result.begin(), 1, &call0, queue);
+
+ std::cout << "option 0 call price: " << call0 << std::endl;
+ std::cout << "option 0 put price: " << put0 << std::endl;
+
+ // due to the differences in the random-number generators between Operating Systems
+ // and/or compilers, we will get different "expected" results for this example
+#ifdef __APPLE__
+ double expected_call0 = 0.000249461;
+ double expected_put0 = 26.2798;
+#elif _MSC_VER
+ double expected_call0 = 8.21412;
+ double expected_put0 = 2.25904;
+#else
+ double expected_call0 = 0.0999f;
+ double expected_put0 = 43.0524f;
+#endif
+
+ // check option prices
+ if(std::abs(call0 - expected_call0) > 1e-4 || std::abs(put0 - expected_put0) > 1e-4){
+ std::cerr << "error: option prices are wrong" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/copy_data.cpp b/src/boost/libs/compute/example/copy_data.cpp
new file mode 100644
index 00000000..0550287f
--- /dev/null
+++ b/src/boost/libs/compute/example/copy_data.cpp
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+//[copy_data_example
+
+#include <vector>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get default device and setup context
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ // create data array on host
+ int host_data[] = { 1, 3, 5, 7, 9 };
+
+ // create vector on device
+ compute::vector<int> device_vector(5, context);
+
+ // copy from host to device
+ compute::copy(
+ host_data, host_data + 5, device_vector.begin(), queue
+ );
+
+ // create vector on host
+ std::vector<int> host_vector(5);
+
+ // copy data back to host
+ compute::copy(
+ device_vector.begin(), device_vector.end(), host_vector.begin(), queue
+ );
+
+ return 0;
+}
+
+//]
diff --git a/src/boost/libs/compute/example/fizz_buzz.cpp b/src/boost/libs/compute/example/fizz_buzz.cpp
new file mode 100644
index 00000000..2c69995f
--- /dev/null
+++ b/src/boost/libs/compute/example/fizz_buzz.cpp
@@ -0,0 +1,160 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+const char fizz_buzz_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // returns the length of the string for the number 'n'. This is used
+ // during the first pass when we calculate the amount of space needed
+ // for each string in the fizz-buzz sequence.
+ inline uint fizz_buzz_string_length(uint n)
+ {
+ if((n % 5 == 0) && (n % 3 == 0)){
+ return sizeof("fizzbuzz");
+ }
+ else if(n % 5 == 0){
+ return sizeof("fizz");
+ }
+ else if(n % 3 == 0){
+ return sizeof("buzz");
+ }
+ else {
+ uint digits = 0;
+ while(n){
+ n /= 10;
+ digits++;
+ }
+ return digits + 1;
+ }
+ }
+
+ // first-pass kernel which calculates the string length for each number
+ // and writes it to the string_lengths array. these will then be passed
+ // to exclusive_scan() to calculate the output offsets for each string.
+ __kernel void fizz_buzz_allocate_strings(__global uint *string_lengths)
+ {
+ const uint i = get_global_id(0);
+ const uint n = i + 1;
+
+ string_lengths[i] = fizz_buzz_string_length(n);
+ }
+
+ // copy the string 's' with length 'n' to 'result' (just like strncpy())
+ inline void copy_string(__constant const char *s, uint n, __global char *result)
+ {
+ while(n--){
+ result[n] = s[n];
+ }
+ }
+
+ // reverse the string [start, end).
+ inline void reverse_string(__global char *start, __global char *end)
+ {
+ while(start < end){
+ char tmp = *end;
+ *end = *start;
+ *start = tmp;
+ start++;
+ end--;
+ }
+ }
+
+ // second-pass kernel which copies the fizz-buzz string for each number to
+ // buffer using the previously calculated offsets.
+ __kernel void fizz_buzz_copy_strings(__global const uint *offsets, __global char *buffer)
+ {
+ const uint i = get_global_id(0);
+ const uint n = i + 1;
+ const uint offset = offsets[i];
+
+ if((n % 5 == 0) && (n % 3 == 0)){
+ copy_string("fizzbuzz\n", 9, buffer + offset);
+ }
+ else if(n % 5 == 0){
+ copy_string("fizz\n", 5, buffer + offset);
+ }
+ else if(n % 3 == 0){
+ copy_string("buzz\n", 5, buffer + offset);
+ }
+ else {
+ // convert number to string and write it to the output
+ __global char *number = buffer + offset;
+ uint n_ = n;
+ while(n_){
+ *number++ = (n_%10) + '0';
+ n_ /= 10;
+ }
+ reverse_string(buffer + offset, number - 1);
+ *number = '\n';
+ }
+ }
+);
+
+int main()
+{
+ using compute::dim;
+ using compute::uint_;
+
+ // fizz-buzz up to 100
+ size_t n = 100;
+
+ // get the default device
+ compute::device device = compute::system::default_device();
+ compute::context ctx(device);
+ compute::command_queue queue(ctx, device);
+
+ // compile the fizz-buzz program
+ compute::program fizz_buzz_program =
+ compute::program::create_with_source(fizz_buzz_source, ctx);
+ fizz_buzz_program.build();
+
+ // create a vector for the output string and computing offsets
+ compute::vector<char> output(ctx);
+ compute::vector<uint_> offsets(n, ctx);
+
+ // run the allocate kernel to calculate string lengths
+ compute::kernel allocate_kernel(fizz_buzz_program, "fizz_buzz_allocate_strings");
+ allocate_kernel.set_arg(0, offsets);
+ queue.enqueue_nd_range_kernel(allocate_kernel, dim(0), dim(n), dim(1));
+
+ // allocate space for the output string
+ output.resize(
+ compute::accumulate(offsets.begin(), offsets.end(), 0, queue)
+ );
+
+ // scan string lengths for each number to calculate the output offsets
+ compute::exclusive_scan(
+ offsets.begin(), offsets.end(), offsets.begin(), queue
+ );
+
+ // run the copy kernel to fill the output buffer
+ compute::kernel copy_kernel(fizz_buzz_program, "fizz_buzz_copy_strings");
+ copy_kernel.set_arg(0, offsets);
+ copy_kernel.set_arg(1, output);
+ queue.enqueue_nd_range_kernel(copy_kernel, dim(0), dim(n), dim(1));
+
+ // copy the string to the host and print it to stdout
+ std::string str;
+ str.resize(output.size());
+ compute::copy(output.begin(), output.end(), str.begin(), queue);
+ std::cout << str;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/hello_world.cpp b/src/boost/libs/compute/example/hello_world.cpp
new file mode 100644
index 00000000..ef45fdd6
--- /dev/null
+++ b/src/boost/libs/compute/example/hello_world.cpp
@@ -0,0 +1,30 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+//[hello_world_example
+
+#include <iostream>
+
+#include <boost/compute/core.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get the default device
+ compute::device device = compute::system::default_device();
+
+ // print the device's name and platform
+ std::cout << "hello from " << device.name();
+ std::cout << " (platform: " << device.platform().name() << ")" << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/compute/example/host_sort.cpp b/src/boost/libs/compute/example/host_sort.cpp
new file mode 100644
index 00000000..b5ff52cf
--- /dev/null
+++ b/src/boost/libs/compute/example/host_sort.cpp
@@ -0,0 +1,56 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <vector>
+
+#include <boost/spirit/include/karma.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+
+namespace compute = boost::compute;
+namespace karma = boost::spirit::karma;
+
+int rand_int()
+{
+ return rand() % 100;
+}
+
+// this example demonstrates how to sort a std::vector of ints on the GPU
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // create vector of random values on the host
+ std::vector<int> vector(8);
+ std::generate(vector.begin(), vector.end(), rand_int);
+
+ // print input vector
+ std::cout << "input: [ "
+ << karma::format(karma::int_ % ", ", vector)
+ << " ]"
+ << std::endl;
+
+ // sort vector
+ compute::sort(vector.begin(), vector.end(), queue);
+
+ // print sorted vector
+ std::cout << "output: [ "
+ << karma::format(karma::int_ % ", ", vector)
+ << " ]"
+ << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/inline_ptx.cpp b/src/boost/libs/compute/example/inline_ptx.cpp
new file mode 100644
index 00000000..fe4e32f0
--- /dev/null
+++ b/src/boost/libs/compute/example/inline_ptx.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to embed PTX assembly instructions
+// directly into boost.compute functions and use them with the
+// transform() algorithm.
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // check to ensure we have an nvidia device
+ if(gpu.vendor() != "NVIDIA Corporation"){
+ std::cerr << "error: inline PTX assembly is only supported "
+ << "on NVIDIA devices."
+ << std::endl;
+ return 0;
+ }
+
+ // create input values and copy them to the device
+ using compute::uint_;
+ uint_ data[] = { 0x00, 0x01, 0x11, 0xFF };
+ compute::vector<uint_> input(data, data + 4, queue);
+
+ // function returning the number of bits set (aka population count or
+ // popcount) using the "popc" inline ptx assembly instruction.
+ BOOST_COMPUTE_FUNCTION(uint_, nvidia_popc, (uint_ x),
+ {
+ uint count;
+ asm("popc.b32 %0, %1;" : "=r"(count) : "r"(x));
+ return count;
+ });
+
+ // calculate the popcount for each input value
+ compute::vector<uint_> output(input.size(), context);
+ compute::transform(
+ input.begin(), input.end(), output.begin(), nvidia_popc, queue
+ );
+
+ // copy results back to the host and print them out
+ std::vector<uint_> counts(output.size());
+ compute::copy(output.begin(), output.end(), counts.begin(), queue);
+
+ for(size_t i = 0; i < counts.size(); i++){
+ std::cout << "0x" << std::hex << data[i]
+ << " has " << counts[i]
+ << " bits set" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/k_means.cpp b/src/boost/libs/compute/example/k_means.cpp
new file mode 100644
index 00000000..cd291a9b
--- /dev/null
+++ b/src/boost/libs/compute/example/k_means.cpp
@@ -0,0 +1,229 @@
+//---------------------------------------------------------------------------//
+// 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 <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_real_distribution.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+using compute::dim;
+using compute::int_;
+using compute::float_;
+using compute::float2_;
+
+// the k-means example implements the k-means clustering algorithm
+int main()
+{
+ // number of clusters
+ size_t k = 6;
+
+ // number of points
+ size_t n_points = 4500;
+
+ // height and width of image
+ size_t height = 800;
+ size_t width = 800;
+
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ // generate random, uniformily-distributed points
+ compute::default_random_engine random_engine(queue);
+ compute::uniform_real_distribution<float_> uniform_distribution(0, 800);
+
+ compute::vector<float2_> points(n_points, context);
+ uniform_distribution.generate(
+ compute::make_buffer_iterator<float_>(points.get_buffer(), 0),
+ compute::make_buffer_iterator<float_>(points.get_buffer(), n_points * 2),
+ random_engine,
+ queue
+ );
+
+ // initialize all points to cluster 0
+ compute::vector<int_> clusters(n_points, context);
+ compute::fill(clusters.begin(), clusters.end(), 0, queue);
+
+ // create initial means with the first k points
+ compute::vector<float2_> means(k, context);
+ compute::copy_n(points.begin(), k, means.begin(), queue);
+
+ // k-means clustering program source
+ const char k_means_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void assign_clusters(__global const float2 *points,
+ __global const float2 *means,
+ const int k,
+ __global int *clusters)
+ {
+ const uint gid = get_global_id(0);
+
+ const float2 point = points[gid];
+
+ // find the closest cluster
+ float current_distance = 0;
+ int closest_cluster = -1;
+
+ // find closest cluster mean to the point
+ for(int i = 0; i < k; i++){
+ const float2 mean = means[i];
+
+ int distance_to_mean = distance(point, mean);
+ if(closest_cluster == -1 || distance_to_mean < current_distance){
+ current_distance = distance_to_mean;
+ closest_cluster = i;
+ }
+ }
+
+ // write new cluster
+ clusters[gid] = closest_cluster;
+ }
+
+ __kernel void update_means(__global const float2 *points,
+ const uint n_points,
+ __global float2 *means,
+ __global const int *clusters)
+ {
+ const uint k = get_global_id(0);
+
+ float2 sum = { 0, 0 };
+ float count = 0;
+ for(uint i = 0; i < n_points; i++){
+ if(clusters[i] == k){
+ sum += points[i];
+ count += 1;
+ }
+ }
+
+ means[k] = sum / count;
+ }
+ );
+
+ // build the k-means program
+ compute::program k_means_program =
+ compute::program::build_with_source(k_means_source, context);
+
+ // setup the k-means kernels
+ compute::kernel assign_clusters_kernel(k_means_program, "assign_clusters");
+ assign_clusters_kernel.set_arg(0, points);
+ assign_clusters_kernel.set_arg(1, means);
+ assign_clusters_kernel.set_arg(2, int_(k));
+ assign_clusters_kernel.set_arg(3, clusters);
+
+ compute::kernel update_means_kernel(k_means_program, "update_means");
+ update_means_kernel.set_arg(0, points);
+ update_means_kernel.set_arg(1, int_(n_points));
+ update_means_kernel.set_arg(2, means);
+ update_means_kernel.set_arg(3, clusters);
+
+ // run the k-means algorithm
+ for(int iteration = 0; iteration < 25; iteration++){
+ queue.enqueue_1d_range_kernel(assign_clusters_kernel, 0, n_points, 0);
+ queue.enqueue_1d_range_kernel(update_means_kernel, 0, k, 0);
+ }
+
+ // create output image
+ compute::image2d image(
+ context, width, height, compute::image_format(CL_RGBA, CL_UNSIGNED_INT8)
+ );
+
+ // program with two kernels, one to fill the image with white, and then
+ // one the draw to points calculated in coordinates on the image
+ const char draw_walk_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void draw_points(__global const float2 *points,
+ __global const int *clusters,
+ __write_only image2d_t image)
+ {
+ const uint i = get_global_id(0);
+ const float2 coord = points[i];
+
+ // map cluster number to color
+ uint4 color = { 0, 0, 0, 0 };
+ switch(clusters[i]){
+ case 0:
+ color = (uint4)(255, 0, 0, 255);
+ break;
+ case 1:
+ color = (uint4)(0, 255, 0, 255);
+ break;
+ case 2:
+ color = (uint4)(0, 0, 255, 255);
+ break;
+ case 3:
+ color = (uint4)(255, 255, 0, 255);
+ break;
+ case 4:
+ color = (uint4)(255, 0, 255, 255);
+ break;
+ case 5:
+ color = (uint4)(0, 255, 255, 255);
+ break;
+ }
+
+ // draw a 3x3 pixel point
+ for(int x = -1; x <= 1; x++){
+ for(int y = -1; y <= 1; y++){
+ if(coord.x + x > 0 && coord.x + x < get_image_width(image) &&
+ coord.y + y > 0 && coord.y + y < get_image_height(image)){
+ write_imageui(image, (int2)(coord.x, coord.y) + (int2)(x, y), color);
+ }
+ }
+ }
+ }
+
+ __kernel void fill_gray(__write_only image2d_t image)
+ {
+ const int2 coord = { get_global_id(0), get_global_id(1) };
+
+ if(coord.x < get_image_width(image) && coord.y < get_image_height(image)){
+ uint4 gray = { 15, 15, 15, 15 };
+ write_imageui(image, coord, gray);
+ }
+ }
+ );
+
+ // build the program
+ compute::program draw_program =
+ compute::program::build_with_source(draw_walk_source, context);
+
+ // fill image with dark gray
+ compute::kernel fill_kernel(draw_program, "fill_gray");
+ fill_kernel.set_arg(0, image);
+
+ queue.enqueue_nd_range_kernel(
+ fill_kernel, dim(0, 0), dim(width, height), dim(1, 1)
+ );
+
+ // draw points colored according to cluster
+ compute::kernel draw_kernel(draw_program, "draw_points");
+ draw_kernel.set_arg(0, points);
+ draw_kernel.set_arg(1, clusters);
+ draw_kernel.set_arg(2, image);
+ queue.enqueue_1d_range_kernel(draw_kernel, 0, n_points, 0);
+
+ // show image
+ compute::opencv_imshow("k-means", image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/list_devices.cpp b/src/boost/libs/compute/example/list_devices.cpp
new file mode 100644
index 00000000..b7bdbc94
--- /dev/null
+++ b/src/boost/libs/compute/example/list_devices.cpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <boost/compute/core.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ std::vector<compute::platform> platforms = compute::system::platforms();
+
+ for(size_t i = 0; i < platforms.size(); i++){
+ const compute::platform &platform = platforms[i];
+
+ std::cout << "Platform '" << platform.name() << "'" << std::endl;
+
+ std::vector<compute::device> devices = platform.devices();
+ for(size_t j = 0; j < devices.size(); j++){
+ const compute::device &device = devices[j];
+
+ std::string type;
+ if(device.type() & compute::device::gpu)
+ type = "GPU Device";
+ else if(device.type() & compute::device::cpu)
+ type = "CPU Device";
+ else if(device.type() & compute::device::accelerator)
+ type = "Accelerator Device";
+ else
+ type = "Unknown Device";
+
+ std::cout << " " << type << ": " << device.name() << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/longest_vector.cpp b/src/boost/libs/compute/example/longest_vector.cpp
new file mode 100644
index 00000000..faada332
--- /dev/null
+++ b/src/boost/libs/compute/example/longest_vector.cpp
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <iterator>
+
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/geometry.hpp>
+#include <boost/compute/iterator/transform_iterator.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to use the max_element() algorithm along with
+// a transform_iterator and the length() function to find the longest
+// 4-component vector in an array of vectors
+int main()
+{
+ using compute::float4_;
+
+ // vectors data
+ float data[] = { 1.0f, 2.0f, 3.0f, 0.0f,
+ 4.0f, 5.0f, 6.0f, 0.0f,
+ 7.0f, 8.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f };
+
+ // create device vector with the vector data
+ compute::vector<float4_> vector(
+ reinterpret_cast<float4_ *>(data),
+ reinterpret_cast<float4_ *>(data) + 4
+ );
+
+ // find the longest vector
+ compute::vector<float4_>::const_iterator iter =
+ compute::max_element(
+ compute::make_transform_iterator(
+ vector.begin(), compute::length<float4_>()
+ ),
+ compute::make_transform_iterator(
+ vector.end(), compute::length<float4_>()
+ )
+ ).base();
+
+ // print the index of the longest vector
+ std::cout << "longest vector index: "
+ << std::distance(vector.begin(), iter)
+ << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/mandelbrot.cpp b/src/boost/libs/compute/example/mandelbrot.cpp
new file mode 100644
index 00000000..5ddb3687
--- /dev/null
+++ b/src/boost/libs/compute/example/mandelbrot.cpp
@@ -0,0 +1,224 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <algorithm>
+
+#include <QtGlobal>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QtOpenGL>
+
+#ifndef Q_MOC_RUN
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/interop/opengl.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+#endif // Q_MOC_RUN
+
+namespace compute = boost::compute;
+
+// opencl source code
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ // map value to color
+ float4 color(uint i)
+ {
+ uchar c = i;
+ uchar x = 35;
+ uchar y = 25;
+ uchar z = 15;
+ uchar max = 255;
+
+ if(i == 256)
+ return (float4)(0, 0, 0, 255);
+ else
+ return (float4)(max-x*i, max-y*i, max-z*i, max) / 255.f;
+ }
+
+ __kernel void mandelbrot(__write_only image2d_t image)
+ {
+ const uint x_coord = get_global_id(0);
+ const uint y_coord = get_global_id(1);
+ const uint width = get_global_size(0);
+ const uint height = get_global_size(1);
+
+ float x_origin = ((float) x_coord / width) * 3.25f - 2.0f;
+ float y_origin = ((float) y_coord / height) * 2.5f - 1.25f;
+
+ float x = 0.0f;
+ float y = 0.0f;
+
+ uint i = 0;
+ while(x*x + y*y <= 4.f && i < 256){
+ float tmp = x*x - y*y + x_origin;
+ y = 2*x*y + y_origin;
+ x = tmp;
+ i++;
+ }
+
+ int2 coord = { x_coord, y_coord };
+ write_imagef(image, coord, color(i));
+ };
+);
+
+class MandelbrotWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ MandelbrotWidget(QWidget *parent = 0);
+ ~MandelbrotWidget();
+
+ void initializeGL();
+ void resizeGL(int width, int height);
+ void paintGL();
+ void keyPressEvent(QKeyEvent* event);
+
+private:
+ compute::context context_;
+ compute::command_queue queue_;
+ compute::program program_;
+ GLuint gl_texture_;
+ compute::opengl_texture cl_texture_;
+};
+
+MandelbrotWidget::MandelbrotWidget(QWidget *parent)
+ : QGLWidget(parent)
+{
+ gl_texture_ = 0;
+}
+
+MandelbrotWidget::~MandelbrotWidget()
+{
+}
+
+void MandelbrotWidget::initializeGL()
+{
+ // setup opengl
+ glDisable(GL_LIGHTING);
+
+ // create the OpenGL/OpenCL shared context
+ context_ = compute::opengl_create_shared_context();
+
+ // get gpu device
+ compute::device gpu = context_.get_device();
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // setup command queue
+ queue_ = compute::command_queue(context_, gpu);
+
+ // build mandelbrot program
+ program_ = compute::program::create_with_source(source, context_);
+ program_.build();
+}
+
+void MandelbrotWidget::resizeGL(int width, int height)
+{
+#if QT_VERSION >= 0x050000
+ // scale height/width based on device pixel ratio
+ width /= windowHandle()->devicePixelRatio();
+ height /= windowHandle()->devicePixelRatio();
+#endif
+
+ // resize viewport
+ glViewport(0, 0, width, height);
+
+ // delete old texture
+ if(gl_texture_){
+ glDeleteTextures(1, &gl_texture_);
+ gl_texture_ = 0;
+ }
+
+ // generate new texture
+ glGenTextures(1, &gl_texture_);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0
+ );
+
+ // create opencl object for the texture
+ cl_texture_ = compute::opengl_texture(
+ context_, GL_TEXTURE_2D, 0, gl_texture_, CL_MEM_WRITE_ONLY
+ );
+}
+
+void MandelbrotWidget::paintGL()
+{
+ using compute::dim;
+
+ float w = width();
+ float h = height();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, w, 0.0, h, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // setup the mandelbrot kernel
+ compute::kernel kernel(program_, "mandelbrot");
+ kernel.set_arg(0, cl_texture_);
+
+ // acquire the opengl texture so it can be used in opencl
+ compute::opengl_enqueue_acquire_gl_objects(1, &cl_texture_.get(), queue_);
+
+ // execute the mandelbrot kernel
+ queue_.enqueue_nd_range_kernel(
+ kernel, dim(0, 0), dim(width(), height()), dim(1, 1)
+ );
+
+ // release the opengl texture so it can be used by opengl
+ compute::opengl_enqueue_release_gl_objects(1, &cl_texture_.get(), queue_);
+
+ // ensure opencl is finished before rendering in opengl
+ queue_.finish();
+
+ // draw a single quad with the mandelbrot image texture
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(0, 0);
+ glTexCoord2f(0, 1); glVertex2f(0, h);
+ glTexCoord2f(1, 1); glVertex2f(w, h);
+ glTexCoord2f(1, 0); glVertex2f(w, 0);
+ glEnd();
+}
+
+void MandelbrotWidget::keyPressEvent(QKeyEvent* event)
+{
+ if(event->key() == Qt::Key_Escape) {
+ this->close();
+ }
+}
+
+// the mandelbrot example shows how to create a mandelbrot image in
+// OpenCL and render the image as a texture in OpenGL
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ MandelbrotWidget widget;
+ widget.show();
+
+ return app.exec();
+}
+
+#include "mandelbrot.moc"
diff --git a/src/boost/libs/compute/example/mapped_view.cpp b/src/boost/libs/compute/example/mapped_view.cpp
new file mode 100644
index 00000000..1e05107a
--- /dev/null
+++ b/src/boost/libs/compute/example/mapped_view.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/reduce.hpp>
+#include <boost/compute/container/mapped_view.hpp>
+
+namespace compute = boost::compute;
+
+// this example demonstrates how to use the mapped_view class to map
+// an array of numbers to device memory and use the reduce() algorithm
+// to calculate the sum.
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // create data on host
+ int data[] = { 4, 2, 3, 7, 8, 9, 1, 6 };
+
+ // create mapped view on device
+ compute::mapped_view<int> view(data, 8, context);
+
+ // use reduce() to calculate sum on the device
+ int sum = 0;
+ compute::reduce(view.begin(), view.end(), &sum, queue);
+
+ // print the sum on the host
+ std::cout << "sum: " << sum << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/matrix_transpose.cpp b/src/boost/libs/compute/example/matrix_transpose.cpp
new file mode 100644
index 00000000..ee9b1e9d
--- /dev/null
+++ b/src/boost/libs/compute/example/matrix_transpose.cpp
@@ -0,0 +1,355 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Benoit Dequidt <benoit.dequidt@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 <iostream>
+#include <cstdlib>
+
+#include <boost/program_options.hpp>
+
+#include <boost/compute/core.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+using compute::uint_;
+
+const uint_ TILE_DIM = 32;
+const uint_ BLOCK_ROWS = 8;
+
+// generate a copy kernel program
+compute::kernel make_copy_kernel(const compute::context& context)
+{
+ // source for the copy_kernel program
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void copy_kernel(__global const float *src, __global float *dst)
+ {
+ uint x = get_group_id(0) * TILE_DIM + get_local_id(0);
+ uint y = get_group_id(1) * TILE_DIM + get_local_id(1);
+
+ uint width = get_num_groups(0) * TILE_DIM;
+
+ for(uint i = 0 ; i < TILE_DIM ; i+= BLOCK_ROWS){
+ dst[(y+i)*width +x] = src[(y+i)*width + x];
+ }
+ }
+ );
+
+ // setup compilation flags for the copy program
+ std::stringstream options;
+ options << "-DTILE_DIM=" << TILE_DIM << " -DBLOCK_ROWS=" << BLOCK_ROWS;
+
+ // create and build the copy program
+ compute::program program =
+ compute::program::build_with_source(source, context, options.str());
+
+ // create and return the copy kernel
+ return program.create_kernel("copy_kernel");
+}
+
+// generate a naive transpose kernel
+compute::kernel make_naive_transpose_kernel(const compute::context& context)
+{
+ // source for the naive_transpose kernel
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void naive_transpose(__global const float *src, __global float *dst)
+ {
+ uint x = get_group_id(0) * TILE_DIM + get_local_id(0);
+ uint y = get_group_id(1) * TILE_DIM + get_local_id(1);
+
+ uint width = get_num_groups(0) * TILE_DIM;
+
+ for(uint i = 0 ; i < TILE_DIM; i+= BLOCK_ROWS){
+ dst[x*width + y+i] = src[(y+i)*width + x];
+ }
+ }
+ );
+
+ // setup compilation flags for the naive_transpose program
+ std::stringstream options;
+ options << "-DTILE_DIM=" << TILE_DIM << " -DBLOCK_ROWS=" << BLOCK_ROWS;
+
+ // create and build the naive_transpose program
+ compute::program program =
+ compute::program::build_with_source(source, context, options.str());
+
+ // create and return the naive_transpose kernel
+ return program.create_kernel("naive_transpose");
+}
+
+// generates a coalesced transpose kernel
+compute::kernel make_coalesced_transpose_kernel(const compute::context& context)
+{
+ // source for the coalesced_transpose kernel
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void coalesced_transpose(__global const float *src, __global float *dst)
+ {
+ __local float tile[TILE_DIM][TILE_DIM];
+
+ // compute indexes
+ uint x = get_group_id(0) * TILE_DIM + get_local_id(0);
+ uint y = get_group_id(1) * TILE_DIM + get_local_id(1);
+
+ uint width = get_num_groups(0) * TILE_DIM;
+
+ // load inside local memory
+ for(uint i = 0 ; i < TILE_DIM; i+= BLOCK_ROWS){
+ tile[get_local_id(1)+i][get_local_id(0)] = src[(y+i)*width + x];
+ }
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ // transpose indexes
+ x = get_group_id(1) * TILE_DIM + get_local_id(0);
+ y = get_group_id(0) * TILE_DIM + get_local_id(1);
+
+ // write output from local memory
+ for(uint i = 0 ; i < TILE_DIM ; i+=BLOCK_ROWS){
+ dst[(y+i)*width + x] = tile[get_local_id(0)][get_local_id(1)+i];
+ }
+ }
+ );
+
+ // setup compilation flags for the coalesced_transpose program
+ std::stringstream options;
+ options << "-DTILE_DIM=" << TILE_DIM << " -DBLOCK_ROWS=" << BLOCK_ROWS;
+
+ // create and build the coalesced_transpose program
+ compute::program program =
+ compute::program::build_with_source(source, context, options.str());
+
+ // create and return coalesced_transpose kernel
+ return program.create_kernel("coalesced_transpose");
+}
+
+// generate a coalesced withtout bank conflicts kernel
+compute::kernel make_coalesced_no_bank_conflicts_kernel(const compute::context& context)
+{
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void coalesced_no_bank_conflicts(__global const float *src, __global float *dst)
+ {
+ // TILE_DIM+1 is here to avoid bank conflicts in local memory
+ __local float tile[TILE_DIM][TILE_DIM+1];
+
+ // compute indexes
+ uint x = get_group_id(0) * TILE_DIM + get_local_id(0);
+ uint y = get_group_id(1) * TILE_DIM + get_local_id(1);
+
+ uint width = get_num_groups(0) * TILE_DIM;
+
+ // load inside local memory
+ for(uint i = 0 ; i < TILE_DIM; i+= BLOCK_ROWS){
+ tile[get_local_id(1)+i][get_local_id(0)] = src[(y+i)*width + x];
+ }
+
+ barrier(CLK_LOCAL_MEM_FENCE);
+
+ // transpose indexes
+ x = get_group_id(1) * TILE_DIM + get_local_id(0);
+ y = get_group_id(0) * TILE_DIM + get_local_id(1);
+
+ // write output from local memory
+ for(uint i = 0 ; i < TILE_DIM ; i+=BLOCK_ROWS){
+ dst[(y+i)*width + x] = tile[get_local_id(0)][get_local_id(1)+i];
+ }
+ }
+ );
+
+ // setup compilation flags for the coalesced_no_bank_conflicts program
+ std::stringstream options;
+ options << "-DTILE_DIM=" << TILE_DIM << " -DBLOCK_ROWS=" << BLOCK_ROWS;
+
+ // create and build the coalesced_no_bank_conflicts program
+ compute::program program =
+ compute::program::build_with_source(source, context, options.str());
+
+ // create and return the coalesced_no_bank_conflicts kernel
+ return program.create_kernel("coalesced_no_bank_conflicts");
+}
+
+// compare 'expectedResult' to 'transposedMatrix'. prints an error message if not equal.
+bool check_transposition(const std::vector<float>& expectedResult,
+ uint_ size,
+ const std::vector<float>& transposedMatrix)
+{
+ for(uint_ i = 0 ; i < size ; ++i){
+ if(expectedResult[i] != transposedMatrix[i]){
+ std::cout << "idx = " << i << " , expected " << expectedResult[i]
+ << " , got " << transposedMatrix[i] << std::endl;
+ std::cout << "FAILED" << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+// generate a matrix inside 'in' and do the tranposition inside 'out'
+void generate_matrix(std::vector<float>& in, std::vector<float>& out, uint_ rows, uint_ cols)
+{
+ // generate a matrix
+ for(uint_ i = 0 ; i < rows ; ++i){
+ for(uint_ j = 0 ; j < cols ; ++j){
+ in[i*cols + j] = i*cols + j;
+ }
+ }
+
+ // store transposed result
+ for(uint_ j = 0; j < cols ; ++j){
+ for(uint_ i = 0 ; i < rows ; ++i){
+ out[j*rows + i] = in[i*cols + j];
+ }
+ }
+}
+
+// neccessary for 64-bit integer on win32
+#ifdef _WIN32
+#define uint64_t unsigned __int64
+#endif
+
+int main(int argc, char *argv[])
+{
+ // setup command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("rows", po::value<uint_>()->default_value(4096), "number of matrix rows")
+ ("cols", po::value<uint_>()->default_value(4096), "number of matrix columns")
+ ;
+
+ // parse command line
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, options), vm);
+ po::notify(vm);
+
+ // check command line arguments
+ if(vm.count("help")){
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ // get number rows and columns for the matrix
+ const uint_ rows = vm["rows"].as<uint_>();
+ const uint_ cols = vm["cols"].as<uint_>();
+
+ // get the default device
+ compute::device device = compute::system::default_device();
+
+ // print out device name and matrix information
+ std::cout << "Device: " << device.name() << std::endl;
+ std::cout << "Matrix Size: " << rows << "x" << cols << std::endl;
+ std::cout << "Grid Size: " << rows/TILE_DIM << "x" << cols/TILE_DIM << " blocks" << std::endl;
+ std::cout << "Local Size: " << TILE_DIM << "x" << BLOCK_ROWS << " threads" << std::endl;
+ std::cout << std::endl;
+
+ // On OSX this example does not work on CPU devices
+ #if defined(__APPLE__)
+ if(device.type() & compute::device::cpu) {
+ std::cout << "On OSX this example does not work on CPU devices" << std::endl;
+ return 0;
+ }
+ #endif
+
+ const size_t global_work_size[2] = {rows, cols*BLOCK_ROWS/TILE_DIM};
+ const size_t local_work_size[2] = {TILE_DIM, BLOCK_ROWS};
+
+ // setup input data on the host
+ const uint_ size = rows * cols;
+ std::vector<float> h_input(size);
+ std::vector<float> h_output(size);
+ std::vector<float> expectedResult(size);
+ generate_matrix(h_input, expectedResult, rows, cols);
+
+ // create a context for the device
+ compute::context context(device);
+
+ // device vectors
+ compute::vector<float> d_input(size, context);
+ compute::vector<float> d_output(size, context);
+
+ // command_queue with profiling
+ compute::command_queue queue(context, device, compute::command_queue::enable_profiling);
+
+ // copy input data
+ compute::copy(h_input.begin(), h_input.end(), d_input.begin(), queue);
+
+ // simple copy kernel
+ std::cout << "Testing copy_kernel:" << std::endl;
+ compute::kernel kernel = make_copy_kernel(context);
+ kernel.set_arg(0, d_input);
+ kernel.set_arg(1, d_output);
+
+ compute::event start;
+ start = queue.enqueue_nd_range_kernel(kernel, 2, 0, global_work_size, local_work_size);
+ queue.finish();
+ uint64_t elapsed = start.duration<boost::chrono::nanoseconds>().count();
+
+ std::cout << " Elapsed: " << elapsed << " ns" << std::endl;
+ std::cout << " BandWidth: " << 2*rows*cols*sizeof(float) / elapsed << " GB/s" << std::endl;
+ compute::copy(d_output.begin(), d_output.end(), h_output.begin(), queue);
+
+ check_transposition(h_input, rows*cols, h_output);
+ std::cout << std::endl;
+
+ // naive_transpose kernel
+ std::cout << "Testing naive_transpose:" << std::endl;
+ kernel = make_naive_transpose_kernel(context);
+ kernel.set_arg(0, d_input);
+ kernel.set_arg(1, d_output);
+
+ start = queue.enqueue_nd_range_kernel(kernel, 2, 0, global_work_size, local_work_size);
+ queue.finish();
+ elapsed = start.duration<boost::chrono::nanoseconds>().count();
+ std::cout << " Elapsed: " << elapsed << " ns" << std::endl;
+ std::cout << " BandWidth: " << 2*rows*cols*sizeof(float) / elapsed << " GB/s" << std::endl;
+ compute::copy(d_output.begin(), d_output.end(), h_output.begin(), queue);
+
+ check_transposition(expectedResult, rows*cols, h_output);
+ std::cout << std::endl;
+
+ // coalesced_transpose kernel
+ std::cout << "Testing coalesced_transpose:" << std::endl;
+ kernel = make_coalesced_transpose_kernel(context);
+ kernel.set_arg(0, d_input);
+ kernel.set_arg(1, d_output);
+
+ start = queue.enqueue_nd_range_kernel(kernel, 2, 0, global_work_size, local_work_size);
+ queue.finish();
+ elapsed = start.duration<boost::chrono::nanoseconds>().count();
+ std::cout << " Elapsed: " << elapsed << " ns" << std::endl;
+ std::cout << " BandWidth: " << 2*rows*cols*sizeof(float) / elapsed << " GB/s" << std::endl;
+
+ compute::copy(d_output.begin(), d_output.end(), h_output.begin(), queue);
+
+ check_transposition(expectedResult, rows*cols, h_output);
+ std::cout << std::endl;
+
+ // coalesced_no_bank_conflicts kernel
+ std::cout << "Testing coalesced_no_bank_conflicts:" << std::endl;
+
+ kernel = make_coalesced_no_bank_conflicts_kernel(context);
+ kernel.set_arg(0, d_input);
+ kernel.set_arg(1, d_output);
+
+ start = queue.enqueue_nd_range_kernel(kernel, 2, 0, global_work_size, local_work_size);
+ queue.finish();
+ elapsed = start.duration<boost::chrono::nanoseconds>().count();
+ std::cout << " Elapsed: " << elapsed << " ns" << std::endl;
+ std::cout << " BandWidth: " << 2*rows*cols*sizeof(float) / elapsed << " GB/s" << std::endl;
+
+ compute::copy(d_output.begin(), d_output.end(), h_output.begin(), queue);
+
+ check_transposition(expectedResult, rows*cols, h_output);
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/memory_limits.cpp b/src/boost/libs/compute/example/memory_limits.cpp
new file mode 100644
index 00000000..8d0e4a7a
--- /dev/null
+++ b/src/boost/libs/compute/example/memory_limits.cpp
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <boost/compute/core.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get the default device
+ compute::device device = compute::system::default_device();
+
+ std::cout << "device: " << device.name() << std::endl;
+ std::cout << " global memory size: "
+ << device.get_info<cl_ulong>(CL_DEVICE_GLOBAL_MEM_SIZE) / 1024 / 1024
+ << " MB"
+ << std::endl;
+ std::cout << " local memory size: "
+ << device.get_info<cl_ulong>(CL_DEVICE_LOCAL_MEM_SIZE) / 1024
+ << " KB"
+ << std::endl;
+ std::cout << " constant memory size: "
+ << device.get_info<cl_ulong>(CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE) / 1024
+ << " KB"
+ << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/monte_carlo.cpp b/src/boost/libs/compute/example/monte_carlo.cpp
new file mode 100644
index 00000000..8ae26209
--- /dev/null
+++ b/src/boost/libs/compute/example/monte_carlo.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+
+#include <boost/compute/function.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/count_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/buffer_iterator.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ using compute::uint_;
+ using compute::uint2_;
+
+
+#ifdef CI_BUILD // lower number of points for CI builds
+ size_t n = 2000;
+#else
+ // ten million random points
+ size_t n = 10000000;
+#endif
+
+ // generate random numbers
+ compute::default_random_engine rng(queue);
+ compute::vector<uint_> vector(n * 2, context);
+ rng.generate(vector.begin(), vector.end(), queue);
+
+ // function returing true if the point is within the unit circle
+ BOOST_COMPUTE_FUNCTION(bool, is_in_unit_circle, (const uint2_ point),
+ {
+ const float x = point.x / (float) UINT_MAX - 1;
+ const float y = point.y / (float) UINT_MAX - 1;
+
+ return (x*x + y*y) < 1.0f;
+ });
+
+ // iterate over vector<uint> as vector<uint2>
+ compute::buffer_iterator<uint2_> start =
+ compute::make_buffer_iterator<uint2_>(vector.get_buffer(), 0);
+ compute::buffer_iterator<uint2_> end =
+ compute::make_buffer_iterator<uint2_>(vector.get_buffer(), vector.size() / 2);
+
+ // count number of random points within the unit circle
+ size_t count = compute::count_if(start, end, is_in_unit_circle, queue);
+
+ // print out values
+ float count_f = static_cast<float>(count);
+ std::cout << "count: " << count << " / " << n << std::endl;
+ std::cout << "ratio: " << count_f / float(n) << std::endl;
+ std::cout << "pi = " << (count_f / float(n)) * 4.0f << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/nbody.cpp b/src/boost/libs/compute/example/nbody.cpp
new file mode 100644
index 00000000..9379c63b
--- /dev/null
+++ b/src/boost/libs/compute/example/nbody.cpp
@@ -0,0 +1,236 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+
+#define GL_GLEXT_PROTOTYPES
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
+#else
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+
+#include <QtGlobal>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QtOpenGL>
+#include <QTimer>
+
+#include <boost/program_options.hpp>
+#include <boost/random/uniform_real_distribution.hpp>
+#include <boost/random/mersenne_twister.hpp>
+
+#ifndef Q_MOC_RUN
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/interop/opengl.hpp>
+#include <boost/compute/utility/source.hpp>
+#endif // Q_MOC_RUN
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+using compute::uint_;
+using compute::float4_;
+
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void updateVelocity(__global const float4* position, __global float4* velocity, float dt, uint N)
+ {
+ uint gid = get_global_id(0);
+
+ float4 r = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float f = 0.0f;
+ for(uint i = 0; i != gid; i++) {
+ if(i != gid) {
+ r = position[i]-position[gid];
+ f = length(r)+0.001f;
+ f *= f*f;
+ f = dt/f;
+ velocity[gid] += f*r;
+ }
+ }
+ }
+ __kernel void updatePosition(__global float4* position, __global const float4* velocity, float dt)
+ {
+ uint gid = get_global_id(0);
+
+ position[gid].xyz += dt*velocity[gid].xyz;
+ }
+);
+
+class NBodyWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ NBodyWidget(std::size_t particles, float dt, QWidget* parent = 0);
+ ~NBodyWidget();
+
+ void initializeGL();
+ void resizeGL(int width, int height);
+ void paintGL();
+ void updateParticles();
+ void keyPressEvent(QKeyEvent* event);
+
+private:
+ QTimer* timer;
+
+ compute::context m_context;
+ compute::command_queue m_queue;
+ compute::program m_program;
+ compute::opengl_buffer m_position;
+ compute::vector<float4_>* m_velocity;
+ compute::kernel m_velocity_kernel;
+ compute::kernel m_position_kernel;
+
+ bool m_initial_draw;
+
+ const uint_ m_particles;
+ const float m_dt;
+};
+
+NBodyWidget::NBodyWidget(std::size_t particles, float dt, QWidget* parent)
+ : QGLWidget(parent), m_initial_draw(true), m_particles(particles), m_dt(dt)
+{
+ // create a timer to redraw as fast as possible
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
+ timer->start(1);
+}
+
+NBodyWidget::~NBodyWidget()
+{
+ delete m_velocity;
+
+ // delete the opengl buffer
+ GLuint vbo = m_position.get_opengl_object();
+ glDeleteBuffers(1, &vbo);
+}
+
+void NBodyWidget::initializeGL()
+{
+ // create context, command queue and program
+ m_context = compute::opengl_create_shared_context();
+ m_queue = compute::command_queue(m_context, m_context.get_device());
+ m_program = compute::program::create_with_source(source, m_context);
+ m_program.build();
+
+ // prepare random particle positions that will be transferred to the vbo
+ float4_* temp = new float4_[m_particles];
+ boost::random::uniform_real_distribution<float> dist(-0.5f, 0.5f);
+ boost::random::mt19937_64 gen;
+ for(size_t i = 0; i < m_particles; i++) {
+ temp[i][0] = dist(gen);
+ temp[i][1] = dist(gen);
+ temp[i][2] = dist(gen);
+ temp[i][3] = 1.0f;
+ }
+
+ // create an OpenGL vbo
+ GLuint vbo = 0;
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, m_particles*sizeof(float4_), temp, GL_DYNAMIC_DRAW);
+
+ // create a OpenCL buffer from the vbo
+ m_position = compute::opengl_buffer(m_context, vbo);
+ delete[] temp;
+
+ // create buffer for velocities
+ m_velocity = new compute::vector<float4_>(m_particles, m_context);
+ compute::fill(m_velocity->begin(), m_velocity->end(), float4_(0.0f, 0.0f, 0.0f, 0.0f), m_queue);
+
+ // create compute kernels
+ m_velocity_kernel = m_program.create_kernel("updateVelocity");
+ m_velocity_kernel.set_arg(0, m_position);
+ m_velocity_kernel.set_arg(1, m_velocity->get_buffer());
+ m_velocity_kernel.set_arg(2, m_dt);
+ m_velocity_kernel.set_arg(3, m_particles);
+ m_position_kernel = m_program.create_kernel("updatePosition");
+ m_position_kernel.set_arg(0, m_position);
+ m_position_kernel.set_arg(1, m_velocity->get_buffer());
+ m_position_kernel.set_arg(2, m_dt);
+}
+void NBodyWidget::resizeGL(int width, int height)
+{
+ // update viewport
+ glViewport(0, 0, width, height);
+}
+void NBodyWidget::paintGL()
+{
+ // clear buffer
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // check if this is the first draw
+ if(m_initial_draw) {
+ // do not update particles
+ m_initial_draw = false;
+ } else {
+ // update particles
+ updateParticles();
+ }
+
+ // draw
+ glVertexPointer(4, GL_FLOAT, 0, 0);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glDrawArrays(GL_POINTS, 0, m_particles);
+ glFinish();
+}
+void NBodyWidget::updateParticles()
+{
+ // enqueue kernels to update particles and make sure that the command queue is finished
+ compute::opengl_enqueue_acquire_buffer(m_position, m_queue);
+ m_queue.enqueue_1d_range_kernel(m_velocity_kernel, 0, m_particles, 0).wait();
+ m_queue.enqueue_1d_range_kernel(m_position_kernel, 0, m_particles, 0).wait();
+ m_queue.finish();
+ compute::opengl_enqueue_release_buffer(m_position, m_queue);
+}
+void NBodyWidget::keyPressEvent(QKeyEvent* event)
+{
+ if(event->key() == Qt::Key_Escape) {
+ this->close();
+ }
+}
+
+int main(int argc, char** argv)
+{
+ // parse command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage")
+ ("particles", po::value<uint_>()->default_value(1000), "number of particles")
+ ("dt", po::value<float>()->default_value(0.00001f), "width of each integration step");
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, options), vm);
+ po::notify(vm);
+
+ if(vm.count("help") > 0) {
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ const uint_ particles = vm["particles"].as<uint_>();
+ const float dt = vm["dt"].as<float>();
+
+ QApplication app(argc, argv);
+ NBodyWidget nbody(particles, dt);
+
+ nbody.show();
+
+ return app.exec();
+}
+
+#include "nbody.moc"
diff --git a/src/boost/libs/compute/example/opencl_test.cpp b/src/boost/libs/compute/example/opencl_test.cpp
new file mode 100644
index 00000000..15b85202
--- /dev/null
+++ b/src/boost/libs/compute/example/opencl_test.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.
+//---------------------------------------------------------------------------//
+
+// See boost/compute/detail/diagnostic.hpp
+// GCC
+#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+#define BOOST_COMPUTE_GCC_DIAG_STR(s) #s
+#define BOOST_COMPUTE_GCC_DIAG_JOINSTR(x,y) BOOST_COMPUTE_GCC_DIAG_STR(x ## y)
+# define BOOST_COMPUTE_GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
+# define BOOST_COMPUTE_GCC_DIAG_PRAGMA(x) BOOST_COMPUTE_GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x) BOOST_COMPUTE_GCC_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(ignored BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# define BOOST_COMPUTE_GCC_DIAG_ON(x) BOOST_COMPUTE_GCC_DIAG_PRAGMA(pop)
+# else
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(ignored BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# define BOOST_COMPUTE_GCC_DIAG_ON(x) \
+ BOOST_COMPUTE_GCC_DIAG_PRAGMA(warning BOOST_COMPUTE_GCC_DIAG_JOINSTR(-W,x))
+# endif
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_GCC_DIAG_OFF(x)
+# define BOOST_COMPUTE_GCC_DIAG_ON(x)
+#endif
+
+// Clang
+#ifdef __clang__
+# define BOOST_COMPUTE_CLANG_DIAG_STR(s) # s
+// stringize s to "no-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_JOINSTR(x,y) BOOST_COMPUTE_CLANG_DIAG_STR(x ## y)
+// join -W with no-unused-variable to "-Wno-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_DO_PRAGMA(x) _Pragma (#x)
+// _Pragma is unary operator #pragma ("")
+# define BOOST_COMPUTE_CLANG_DIAG_PRAGMA(x) \
+ BOOST_COMPUTE_CLANG_DIAG_DO_PRAGMA(clang diagnostic x)
+# define BOOST_COMPUTE_CLANG_DIAG_OFF(x) BOOST_COMPUTE_CLANG_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_CLANG_DIAG_PRAGMA(ignored BOOST_COMPUTE_CLANG_DIAG_JOINSTR(-W,x))
+// For example: #pragma clang diagnostic ignored "-Wno-sign-compare"
+# define BOOST_COMPUTE_CLANG_DIAG_ON(x) BOOST_COMPUTE_CLANG_DIAG_PRAGMA(pop)
+// For example: #pragma clang diagnostic warning "-Wno-sign-compare"
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_CLANG_DIAG_OFF(x)
+# define BOOST_COMPUTE_CLANG_DIAG_ON(x)
+# define BOOST_COMPUTE_CLANG_DIAG_PRAGMA(x)
+#endif
+
+// MSVC
+#if defined(_MSC_VER)
+# define BOOST_COMPUTE_MSVC_DIAG_DO_PRAGMA(x) __pragma(x)
+# define BOOST_COMPUTE_MSVC_DIAG_PRAGMA(x) \
+ BOOST_COMPUTE_MSVC_DIAG_DO_PRAGMA(warning(x))
+# define BOOST_COMPUTE_MSVC_DIAG_OFF(x) BOOST_COMPUTE_MSVC_DIAG_PRAGMA(push) \
+ BOOST_COMPUTE_MSVC_DIAG_PRAGMA(disable: x)
+# define BOOST_COMPUTE_MSVC_DIAG_ON(x) BOOST_COMPUTE_MSVC_DIAG_PRAGMA(pop)
+#else // Ensure these macros do nothing for other compilers.
+# define BOOST_COMPUTE_MSVC_DIAG_OFF(x)
+# define BOOST_COMPUTE_MSVC_DIAG_ON(x)
+#endif
+
+#include <iostream>
+
+// include the proper opencl header for the system
+#if defined(__APPLE__)
+#include <OpenCL/cl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+// the opencl_test example displays the opencl platforms and devices found
+// on the system using the opencl api directly. if this test fails to compile
+// and/or run, there is a problem with the opencl implementation found on the
+// system. users should ensure this test runs successfuly before using any of
+// the boost.compute apis (which depend on a working opencl implementation).
+int main()
+{
+ // Suppress deprecated declarations warning
+ BOOST_COMPUTE_MSVC_DIAG_OFF(4996); // MSVC
+ BOOST_COMPUTE_GCC_DIAG_OFF(deprecated-declarations); // GCC
+ BOOST_COMPUTE_CLANG_DIAG_OFF(deprecated-declarations); // Clang
+
+ // query number of opencl platforms
+ cl_uint num_platforms = 0;
+ cl_int ret = clGetPlatformIDs(0, NULL, &num_platforms);
+ if(ret != CL_SUCCESS){
+ std::cerr << "failed to query platforms: " << ret << std::endl;
+ return -1;
+ }
+
+ // check that at least one platform was found
+ if(num_platforms == 0){
+ std::cerr << "found 0 platforms" << std::endl;
+ return 0;
+ }
+
+ // get platform ids
+ cl_platform_id *platforms = new cl_platform_id[num_platforms];
+ clGetPlatformIDs(num_platforms, platforms, NULL);
+
+ // iterate through each platform and query its devices
+ for(cl_uint i = 0; i < num_platforms; i++){
+ cl_platform_id platform = platforms[i];
+
+ // query number of opencl devices
+ cl_uint num_devices = 0;
+ ret = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
+ if(ret != CL_SUCCESS){
+ std::cerr << "failed to lookup devices for platform " << i << std::endl;
+ continue;
+ }
+
+ // print number of devices found
+ std::cout << "platform " << i << " has " << num_devices << " devices:" << std::endl;
+
+ // get device ids for the platform
+ cl_device_id *devices = new cl_device_id[num_devices];
+ ret = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, num_devices, devices, NULL);
+ if(ret != CL_SUCCESS){
+ std::cerr << "failed to query platform devices" << std::endl;
+ delete[] devices;
+ continue;
+ }
+
+ // iterate through each device on the platform and print its name
+ for(cl_uint j = 0; j < num_devices; j++){
+ cl_device_id device = devices[j];
+
+ // get length of the device name string
+ size_t name_length = 0;
+ ret = clGetDeviceInfo(device, CL_DEVICE_NAME, 0, NULL, &name_length);
+ if(ret != CL_SUCCESS){
+ std::cerr << "failed to query device name length for device " << j << std::endl;
+ continue;
+ }
+
+ // get the device name string
+ char *name = new char[name_length];
+ ret = clGetDeviceInfo(device, CL_DEVICE_NAME, name_length, name, NULL);
+ if(ret != CL_SUCCESS){
+ std::cerr << "failed to query device name string for device " << j << std::endl;
+ delete[] name;
+ continue;
+ }
+
+ // print out the device name
+ std::cout << " device: " << name << std::endl;
+
+ delete[] name;
+ }
+ delete[] devices;
+ }
+ delete[] platforms;
+
+ BOOST_COMPUTE_CLANG_DIAG_ON(deprecated-declarations); // Clang
+ BOOST_COMPUTE_GCC_DIAG_ON(deprecated-declarations); // GCC
+ BOOST_COMPUTE_MSVC_DIAG_OFF(4996); // MSVC
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/opencv_convolution.cpp b/src/boost/libs/compute/example/opencv_convolution.cpp
new file mode 100644
index 00000000..7ba53436
--- /dev/null
+++ b/src/boost/libs/compute/example/opencv_convolution.cpp
@@ -0,0 +1,265 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <string>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include <boost/program_options.hpp>
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+// Create convolution program
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE (
+ __kernel void convolution(__read_only image2d_t sourceImage,
+ __write_only image2d_t outputImage,
+ __constant float* filter,
+ int filterWidth)
+ {
+ const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |
+ CLK_ADDRESS_CLAMP_TO_EDGE |
+ CLK_FILTER_NEAREST;
+
+ // Store each work-item's unique row and column
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+
+ // Half the width of the filter is needed for indexing
+ // memory later
+ int halfWidth = (int)(filterWidth/2);
+
+ // All accesses to images return data as four-element vector
+ // (i.e., float4).
+ float4 sum = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ // Iterator for the filter
+ int filterIdx = 0;
+
+ // Each work-item iterates around its local area based on the
+ // size of the filter
+ int2 coords; // Coordinates for accessing the image
+
+ // Iterate the filter rows
+ for(int i = -halfWidth; i <= halfWidth; i++)
+ {
+ coords.y = y + i;
+
+ // Iterate over the filter columns
+ for(int j = -halfWidth; j <= halfWidth; j++)
+ {
+ coords.x = x + j;
+
+ float4 pixel;
+
+ // Read a pixel from the image.
+ // Work on a channel
+ pixel = read_imagef(sourceImage, sampler, coords);
+ sum.x += pixel.x * filter[filterIdx++];
+ //sum.y += pixel.y * filter[filterIdx++];
+ //sum.z += pixel.z * filter[filterIdx++];
+ }
+ }
+
+ barrier(CLK_GLOBAL_MEM_FENCE);
+ // Copy the data to the output image if the
+ // work-item is in bounds
+ if(y < get_image_height(sourceImage) &&
+ x < get_image_width(sourceImage))
+ {
+ coords.x = x;
+ coords.y = y;
+
+ //Same channel is copied in all three channels
+ //write_imagef(outputImage, coords,
+ // (float4)(sum.x,sum.x,sum.x,1.0f));
+
+ write_imagef(outputImage, coords, sum);
+ }
+ }
+);
+
+// This example shows how to read two images or use camera
+// with OpenCV, transfer the frames to the GPU,
+// and apply a convolution written in OpenCL
+int main(int argc, char *argv[])
+{
+ ///////////////////////////////////////////////////////////////////////////
+
+ // setup the command line arguments
+ po::options_description desc;
+ desc.add_options()
+ ("help", "show available options")
+ ("camera", po::value<int>()->default_value(-1),
+ "if not default camera, specify a camera id")
+ ("image", po::value<std::string>(), "path to image file");
+
+ // Parse the command lines
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //check the command line arguments
+ if(vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ //OpenCV variables
+ cv::Mat cv_mat;
+ cv::VideoCapture cap; //OpenCV camera handle.
+
+ //Filter Variables
+ float filter[9] = {
+ -1.0, 0.0, 1.0,
+ -2.0, 0.0, 2.0,
+ -1.0, 0.0, 1.0,
+ };
+
+ // The convolution filter is 3x3
+ int filterWidth = 3;
+
+ //OpenCL variables
+ // Get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ compute::buffer dev_filter(context, sizeof(filter),
+ compute::memory_object::read_only |
+ compute::memory_object::copy_host_ptr,
+ filter);
+
+ compute::program filter_program =
+ compute::program::create_with_source(source, context);
+
+ try
+ {
+ filter_program.build();
+ }
+ catch(compute::opencl_error e)
+ {
+ std::cout<<"Build Error: "<<std::endl
+ <<filter_program.build_log();
+ return -1;
+ }
+
+ // create fliter kernel and set arguments
+ compute::kernel filter_kernel(filter_program, "convolution");
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ //check for image paths
+ if(vm.count("image"))
+ {
+ // Read image with OpenCV
+ cv_mat = cv::imread(vm["image"].as<std::string>(),
+ CV_LOAD_IMAGE_COLOR);
+ if(!cv_mat.data){
+ std::cerr << "Failed to load image" << std::endl;
+ return -1;
+ }
+ }
+ else //by default use camera
+ {
+ //open camera
+ cap.open(vm["camera"].as<int>());
+ // read first frame
+ cap >> cv_mat;
+ if(!cv_mat.data){
+ std::cerr << "failed to capture frame" << std::endl;
+ return -1;
+ }
+ }
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(cv_mat, cv_mat, CV_BGR2BGRA);
+
+ // Transfer image/frame data to gpu
+ compute::image2d dev_input_image =
+ compute::opencv_create_image2d_with_mat(
+ cv_mat, compute::image2d::read_write, queue
+ );
+
+ // Create output image
+ // Be sure what will be your ouput image/frame size
+ compute::image2d dev_output_image(
+ context,
+ dev_input_image.width(),
+ dev_input_image.height(),
+ dev_input_image.format(),
+ compute::image2d::write_only
+ );
+
+ filter_kernel.set_arg(0, dev_input_image);
+ filter_kernel.set_arg(1, dev_output_image);
+ filter_kernel.set_arg(2, dev_filter);
+ filter_kernel.set_arg(3, filterWidth);
+
+ // run flip kernel
+ size_t origin[2] = { 0, 0 };
+ size_t region[2] = { dev_input_image.width(),
+ dev_input_image.height() };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ queue.enqueue_nd_range_kernel(filter_kernel, 2, origin, region, 0);
+
+ //check for image paths
+ if(vm.count("image"))
+ {
+ // show host image
+ cv::imshow("Original Image", cv_mat);
+
+ // show gpu image
+ compute::opencv_imshow("Convoluted Image", dev_output_image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+ }
+ else
+ {
+ char key = '\0';
+ while(key != 27) //check for escape key
+ {
+ cap >> cv_mat;
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(cv_mat, cv_mat, CV_BGR2BGRA);
+
+ // Update the device image memory with current frame data
+ compute::opencv_copy_mat_to_image(cv_mat,
+ dev_input_image,queue);
+
+ // Run the kernel on the device
+ queue.enqueue_nd_range_kernel(filter_kernel, 2, origin, region, 0);
+
+ // Show host image
+ cv::imshow("Camera Frame", cv_mat);
+
+ // Show GPU image
+ compute::opencv_imshow("Convoluted Frame", dev_output_image, queue);
+
+ // wait
+ key = cv::waitKey(10);
+ }
+ }
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/opencv_flip.cpp b/src/boost/libs/compute/example/opencv_flip.cpp
new file mode 100644
index 00000000..8cc26ef2
--- /dev/null
+++ b/src/boost/libs/compute/example/opencv_flip.cpp
@@ -0,0 +1,101 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to read an image with OpenCV, transfer the
+// image to the GPU, and apply a simple flip filter written in OpenCL
+int main(int argc, char *argv[])
+{
+ // check command line
+ if(argc < 2){
+ std::cerr << "usage: " << argv[0] << " FILENAME" << std::endl;
+ return -1;
+ }
+
+ // read image with opencv
+ cv::Mat cv_image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
+ if(!cv_image.data){
+ std::cerr << "failed to load image" << std::endl;
+ return -1;
+ }
+
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ // convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(cv_image, cv_image, CV_BGR2BGRA);
+
+ // transfer image to gpu
+ compute::image2d input_image =
+ compute::opencv_create_image2d_with_mat(
+ cv_image, compute::image2d::read_write, queue
+ );
+
+ // create output image
+ compute::image2d output_image(
+ context,
+ input_image.width(),
+ input_image.height(),
+ input_image.format(),
+ compute::image2d::write_only
+ );
+
+ // create flip program
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void flip_kernel(__read_only image2d_t input,
+ __write_only image2d_t output)
+ {
+ const sampler_t sampler = CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
+ int height = get_image_height(input);
+ int2 input_coord = { get_global_id(0), get_global_id(1) };
+ int2 output_coord = { input_coord.x, height - input_coord.y - 1 };
+ float4 value = read_imagef(input, sampler, input_coord);
+ write_imagef(output, output_coord, value);
+ }
+ );
+
+ compute::program flip_program =
+ compute::program::create_with_source(source, context);
+ flip_program.build();
+
+ // create flip kernel and set arguments
+ compute::kernel flip_kernel(flip_program, "flip_kernel");
+ flip_kernel.set_arg(0, input_image);
+ flip_kernel.set_arg(1, output_image);
+
+ // run flip kernel
+ size_t origin[2] = { 0, 0 };
+ size_t region[2] = { input_image.width(), input_image.height() };
+ queue.enqueue_nd_range_kernel(flip_kernel, 2, origin, region, 0);
+
+ // show host image
+ cv::imshow("opencv image", cv_image);
+
+ // show gpu image
+ compute::opencv_imshow("filtered image", output_image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/opencv_histogram.cpp b/src/boost/libs/compute/example/opencv_histogram.cpp
new file mode 100644
index 00000000..e339030b
--- /dev/null
+++ b/src/boost/libs/compute/example/opencv_histogram.cpp
@@ -0,0 +1,228 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-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.
+//---------------------------------------------------------------------------//
+
+//Code sample for calculating histogram using OpenCL and
+//displaying image histogram in OpenCV.
+
+#include <iostream>
+#include <string>
+
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/highgui/highgui.hpp>
+
+#include <boost/compute/source.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/program_options.hpp>
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+// number of bins
+int histSize = 256;
+
+// Set the ranges ( for B,G,R) )
+// TryOut: consider the range in kernel calculation
+float range[] = { 0, 256 } ;
+const float* histRange = { range };
+
+// Create naive histogram program
+// Needs "cl_khr_local_int32_base_atomics" extension
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE (
+ __kernel void histogram(read_only image2d_t src_image,
+ __global int* b_hist,
+ __global int* g_hist,
+ __global int* r_hist)
+ {
+ sampler_t sampler =( CLK_NORMALIZED_COORDS_FALSE |
+ CLK_FILTER_NEAREST |
+ CLK_ADDRESS_CLAMP_TO_EDGE);
+
+ int image_width = get_image_width(src_image);
+ int image_height = get_image_height(src_image);
+
+ int2 coords = (int2)(get_global_id(0), get_global_id(1));
+ float4 pixel = read_imagef(src_image,sampler, coords);
+
+ //boundary condition
+ if ((coords.x < image_width) && (coords.y < image_height))
+ {
+ uchar indx_x, indx_y, indx_z;
+ indx_x = convert_uchar_sat(pixel.x * 255.0f);
+ indx_y = convert_uchar_sat(pixel.y * 255.0f);
+ indx_z = convert_uchar_sat(pixel.z * 255.0f);
+
+ atomic_inc(&b_hist[(uint)indx_z]);
+ atomic_inc(&g_hist[(uint)indx_y]);
+ atomic_inc(&r_hist[(uint)indx_x]);
+ }
+ }
+);
+
+inline void showHistogramWindow(cv::Mat &b_hist, cv::Mat &g_hist, cv::Mat &r_hist,
+ std::string window_name)
+{
+ // Draw the histograms for B, G and R
+ int hist_w = 1024;
+ int hist_h = 768;
+ int bin_w = cvRound((double)hist_w/histSize);
+
+ cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(0,0,0));
+
+ // Normalize the result to [ 0, histImage.rows ]
+ cv::normalize(b_hist, b_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
+ cv::normalize(g_hist, g_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
+ cv::normalize(r_hist, r_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
+
+ // Draw for each channel
+ for (int i = 1; i < histSize; i++ )
+ {
+ cv::line(histImage,
+ cv::Point(bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1))),
+ cv::Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))),
+ cv::Scalar(255, 0, 0),
+ 2,
+ 8,
+ 0);
+
+ cv::line(histImage,
+ cv::Point(bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1))),
+ cv::Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))),
+ cv::Scalar(0, 255, 0),
+ 2,
+ 8,
+ 0);
+
+ cv::line(histImage,
+ cv::Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1))),
+ cv::Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
+ cv::Scalar( 0, 0, 255),
+ 2,
+ 8,
+ 0);
+ }
+
+ // Display
+ cv::namedWindow(window_name, CV_WINDOW_AUTOSIZE );
+ cv::imshow(window_name, histImage );
+}
+
+//Get the device context
+//Create GPU array/vector
+//Copy the image & set up the kernel
+//Execute the kernel
+//Copy GPU data back to CPU cv::Mat data pointer
+//OpenCV conversion for convienient display
+void calculateHistogramUsingCL(cv::Mat src, compute::command_queue &queue)
+{
+ compute::context context = queue.get_context();
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(src, src, CV_BGR2BGRA);
+
+ //3 channels & 256 bins : alpha channel is ignored
+ compute::vector<int> gpu_b_hist(histSize, context);
+ compute::vector<int> gpu_g_hist(histSize, context);
+ compute::vector<int> gpu_r_hist(histSize, context);
+
+ // Transfer image to gpu
+ compute::image2d gpu_src =
+ compute::opencv_create_image2d_with_mat(
+ src, compute::image2d::read_only,
+ queue
+ );
+
+ compute::program histogram_program =
+ compute::program::create_with_source(source, context);
+ histogram_program.build();
+
+ // create histogram kernel and set arguments
+ compute::kernel histogram_kernel(histogram_program, "histogram");
+ histogram_kernel.set_arg(0, gpu_src);
+ histogram_kernel.set_arg(1, gpu_b_hist.get_buffer());
+ histogram_kernel.set_arg(2, gpu_g_hist.get_buffer());
+ histogram_kernel.set_arg(3, gpu_r_hist.get_buffer());
+
+ // run histogram kernel
+ // each kernel thread updating red, green & blue bins
+ size_t origin[2] = { 0, 0 };
+ size_t region[2] = { gpu_src.width(),
+ gpu_src.height() };
+
+ queue.enqueue_nd_range_kernel(histogram_kernel, 2, origin, region, 0);
+
+ //Make sure kernel get executed and data copied back
+ queue.finish();
+
+ //create Mat and copy GPU bins to CPU memory
+ cv::Mat b_hist(256, 1, CV_32SC1);
+ compute::copy(gpu_b_hist.begin(), gpu_b_hist.end(), b_hist.data, queue);
+ cv::Mat g_hist(256, 1, CV_32SC1);
+ compute::copy(gpu_g_hist.begin(), gpu_g_hist.end(), g_hist.data, queue);
+ cv::Mat r_hist(256, 1, CV_32SC1);
+ compute::copy(gpu_r_hist.begin(), gpu_r_hist.end(), r_hist.data, queue);
+
+ b_hist.convertTo(b_hist, CV_32FC1); //converted for displaying
+ g_hist.convertTo(g_hist, CV_32FC1);
+ r_hist.convertTo(r_hist, CV_32FC1);
+
+ showHistogramWindow(b_hist, g_hist, r_hist, "Histogram");
+}
+
+int main( int argc, char** argv )
+{
+ // Get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ cv::Mat src;
+
+ // setup the command line arguments
+ po::options_description desc;
+ desc.add_options()
+ ("help", "show available options")
+ ("image", po::value<std::string>(), "path to image file");
+
+ // Parse the command lines
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //check the command line arguments
+ if(vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+
+ //check for image paths
+ if(vm.count("image"))
+ {
+ // Read image with OpenCV
+ src = cv::imread(vm["image"].as<std::string>(),
+ CV_LOAD_IMAGE_COLOR);
+ if(!src.data){
+ std::cerr << "Failed to load image" << std::endl;
+ return -1;
+ }
+ calculateHistogramUsingCL(src, queue);
+ cv::imshow("Image", src);
+ cv::waitKey(0);
+ }
+ else
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/opencv_optical_flow.cpp b/src/boost/libs/compute/example/opencv_optical_flow.cpp
new file mode 100644
index 00000000..87f330ae
--- /dev/null
+++ b/src/boost/libs/compute/example/opencv_optical_flow.cpp
@@ -0,0 +1,289 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <string>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include <boost/program_options.hpp>
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+// Create naive optical flow program
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE (
+ const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE;
+
+ __kernel void optical_flow (
+ read_only
+ image2d_t current_image,
+ read_only image2d_t previous_image,
+ write_only image2d_t optical_flow,
+ const float scale,
+ const float offset,
+ const float lambda,
+ const float threshold )
+ {
+ int2 coords = (int2)(get_global_id(0), get_global_id(1));
+ float4 current_pixel = read_imagef(current_image,
+ sampler,
+ coords);
+ float4 previous_pixel = read_imagef(previous_image,
+ sampler,
+ coords);
+ int2 x1 = (int2)(offset, 0.f);
+ int2 y1 = (int2)(0.f, offset);
+
+ //get the difference
+ float4 curdif = previous_pixel - current_pixel;
+
+ //calculate the gradient
+ //Image 2 first
+ float4 gradx = read_imagef(previous_image,
+ sampler,
+ coords+x1) -
+ read_imagef(previous_image,
+ sampler,
+ coords-x1);
+ //Image 1
+ gradx += read_imagef(current_image,
+ sampler,
+ coords+x1) -
+ read_imagef(current_image,
+ sampler,
+ coords-x1);
+ //Image 2 first
+ float4 grady = read_imagef(previous_image,
+ sampler,
+ coords+y1) -
+ read_imagef(previous_image,
+ sampler,
+ coords-y1);
+ //Image 1
+ grady += read_imagef(current_image,
+ sampler,
+ coords+y1) -
+ read_imagef(current_image,
+ sampler,
+ coords-y1);
+
+ float4 sqr = (gradx*gradx) + (grady*grady) +
+ (float4)(lambda,lambda, lambda, lambda);
+ float4 gradmag = sqrt(sqr);
+
+ ///////////////////////////////////////////////////
+ float4 vx = curdif * (gradx / gradmag);
+ float vxd = vx.x;//assumes greyscale
+
+ //format output for flowrepos, out(-x,+x,-y,+y)
+ float2 xout = (float2)(fmax(vxd,0.f),fabs(fmin(vxd,0.f)));
+ xout *= scale;
+ ///////////////////////////////////////////////////
+ float4 vy = curdif*(grady/gradmag);
+ float vyd = vy.x;//assumes greyscale
+
+ //format output for flowrepos, out(-x,+x,-y,+y)
+ float2 yout = (float2)(fmax(vyd,0.f),fabs(fmin(vyd,0.f)));
+ yout *= scale;
+ ///////////////////////////////////////////////////
+
+ float4 out = (float4)(xout, yout);
+ float cond = (float)isgreaterequal(length(out), threshold);
+ out *= cond;
+
+ write_imagef(optical_flow, coords, out);
+ }
+);
+
+// This example shows how to read two images or use camera
+// with OpenCV, transfer the frames to the GPU,
+// and apply a naive optical flow algorithm
+// written in OpenCL
+int main(int argc, char *argv[])
+{
+ // setup the command line arguments
+ po::options_description desc;
+ desc.add_options()
+ ("help", "show available options")
+ ("camera", po::value<int>()->default_value(-1),
+ "if not default camera, specify a camera id")
+ ("image1", po::value<std::string>(), "path to image file 1")
+ ("image2", po::value<std::string>(), "path to image file 2");
+
+ // Parse the command lines
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //check the command line arguments
+ if(vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+
+ //OpenCV variables
+ cv::Mat previous_cv_image;
+ cv::Mat current_cv_image;
+ cv::VideoCapture cap; //OpenCV camera handle
+
+ //check for image paths
+ if(vm.count("image1") && vm.count("image2"))
+ {
+ // Read image 1 with OpenCV
+ previous_cv_image = cv::imread(vm["image1"].as<std::string>(),
+ CV_LOAD_IMAGE_COLOR);
+ if(!previous_cv_image.data){
+ std::cerr << "Failed to load image" << std::endl;
+ return -1;
+ }
+
+ // Read image 2 with opencv
+ current_cv_image = cv::imread(vm["image2"].as<std::string>(),
+ CV_LOAD_IMAGE_COLOR);
+ if(!current_cv_image.data){
+ std::cerr << "Failed to load image" << std::endl;
+ return -1;
+ }
+ }
+ else //by default use camera
+ {
+ //open camera
+ cap.open(vm["camera"].as<int>());
+ // read first frame
+ cap >> previous_cv_image;
+ if(!previous_cv_image.data){
+ std::cerr << "failed to capture frame" << std::endl;
+ return -1;
+ }
+
+ // read second frame
+ cap >> current_cv_image;
+ if(!current_cv_image.data){
+ std::cerr << "failed to capture frame" << std::endl;
+ return -1;
+ }
+
+ }
+
+ // Get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(previous_cv_image, previous_cv_image, CV_BGR2BGRA);
+ cv::cvtColor(current_cv_image, current_cv_image, CV_BGR2BGRA);
+
+ // Transfer image to gpu
+ compute::image2d dev_previous_image =
+ compute::opencv_create_image2d_with_mat(
+ previous_cv_image, compute::image2d::read_write, queue
+ );
+ // Transfer image to gpu
+ compute::image2d dev_current_image =
+ compute::opencv_create_image2d_with_mat(
+ current_cv_image, compute::image2d::read_write, queue
+ );
+
+ // Create output image
+ compute::image2d dev_output_image(
+ context,
+ dev_previous_image.width(),
+ dev_previous_image.height(),
+ dev_previous_image.format(),
+ compute::image2d::write_only
+ );
+
+ compute::program optical_program =
+ compute::program::create_with_source(source, context);
+ optical_program.build();
+
+ // create flip kernel and set arguments
+ compute::kernel optical_kernel(optical_program, "optical_flow");
+ float scale = 10;
+ float offset = 1;
+ float lambda = 0.0025;
+ float threshold = 1.0;
+
+ optical_kernel.set_arg(0, dev_previous_image);
+ optical_kernel.set_arg(1, dev_current_image);
+ optical_kernel.set_arg(2, dev_output_image);
+ optical_kernel.set_arg(3, scale);
+ optical_kernel.set_arg(4, offset);
+ optical_kernel.set_arg(5, lambda);
+ optical_kernel.set_arg(6, threshold);
+
+ // run flip kernel
+ size_t origin[2] = { 0, 0 };
+ size_t region[2] = { dev_previous_image.width(),
+ dev_previous_image.height() };
+ queue.enqueue_nd_range_kernel(optical_kernel, 2, origin, region, 0);
+
+ //check for image paths
+ if(vm.count("image1") && vm.count("image2"))
+ {
+ // show host image
+ cv::imshow("Previous Frame", previous_cv_image);
+ cv::imshow("Current Frame", current_cv_image);
+
+ // show gpu image
+ compute::opencv_imshow("filtered image", dev_output_image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+ }
+ else
+ {
+ char key = '\0';
+ while(key != 27) //check for escape key
+ {
+ cap >> current_cv_image;
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(current_cv_image, current_cv_image, CV_BGR2BGRA);
+
+ // Update the device image memory with current frame data
+ compute::opencv_copy_mat_to_image(previous_cv_image,
+ dev_previous_image,
+ queue);
+ compute::opencv_copy_mat_to_image(current_cv_image,
+ dev_current_image,
+ queue);
+
+ // Run the kernel on the device
+ queue.enqueue_nd_range_kernel(optical_kernel, 2, origin, region, 0);
+
+ // Show host image
+ cv::imshow("Previous Frame", previous_cv_image);
+ cv::imshow("Current Frame", current_cv_image);
+
+ // Show GPU image
+ compute::opencv_imshow("filtered image", dev_output_image, queue);
+
+ // Copy current frame container to previous frame container
+ current_cv_image.copyTo(previous_cv_image);
+
+ // wait
+ key = cv::waitKey(10);
+ }
+
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/compute/example/opencv_sobel_filter.cpp b/src/boost/libs/compute/example/opencv_sobel_filter.cpp
new file mode 100644
index 00000000..4fcfa206
--- /dev/null
+++ b/src/boost/libs/compute/example/opencv_sobel_filter.cpp
@@ -0,0 +1,254 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Mageswaran.D <mageswaran1989@gmail.com>
+//
+// Book Refered: OpenCL Programming Guide
+// 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.
+//---------------------------------------------------------------------------//
+
+//---------------------------------------------------------------------------//
+// About Sobel Filter:
+// * Edge Filter - distinguishes the differrent color region
+// * Finds the gradient in x and y-axes
+// * Three step process
+// -> Find x-axis gradient with kernel/matrix
+// Gx = [-1 0 +1]
+// [-2 0 +2]
+// [-1 0 +1]
+// -> Find y-axis gradient with kernel/matrix
+// Gy = [-1 -2 -1]
+// [ 0 0 0]
+// [+1 +2 +1]
+// * Gradient magnitude G = sqrt(Gx^2 + Gy^2)
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <string>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/utility/source.hpp>
+
+#include <boost/program_options.hpp>
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+// Create sobel filter program
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE (
+ //For out of boundary pixels, edge pixel
+ // value is returned
+ const sampler_t sampler = CLK_ADDRESS_CLAMP_TO_EDGE |
+ CLK_FILTER_NEAREST;
+ kernel void sobel_rgb(read_only image2d_t src, write_only image2d_t dst)
+ {
+ int x = (int)get_global_id(0);
+ int y = (int)get_global_id(1);
+
+ if (x >= get_image_width(src) || y >= get_image_height(src))
+ return;
+
+ // [(x-1, y+1), (x, y+1), (x+1, y+1)]
+ // [(x-1, y ), (x, y ), (x+1, y )]
+ // [(x-1, y-1), (x, y-1), (x+1, y-1)]
+
+ // [p02, p12, p22]
+ // [p01, pixel, p21]
+ // [p00, p10, p20]
+
+ //Basically finding influence of neighbour pixels on current pixel
+ float4 p00 = read_imagef(src, sampler, (int2)(x - 1, y - 1));
+ float4 p10 = read_imagef(src, sampler, (int2)(x, y - 1));
+ float4 p20 = read_imagef(src, sampler, (int2)(x + 1, y - 1));
+
+ float4 p01 = read_imagef(src, sampler, (int2)(x - 1, y));
+ //pixel that we are working on
+ float4 p21 = read_imagef(src, sampler, (int2)(x + 1, y));
+
+ float4 p02 = read_imagef(src, sampler, (int2)(x - 1, y + 1));
+ float4 p12 = read_imagef(src, sampler, (int2)(x, y + 1));
+ float4 p22 = read_imagef(src, sampler, (int2)(x + 1, y + 1));
+
+ //Find Gx = kernel + 3x3 around current pixel
+ // Gx = [-1 0 +1] [p02, p12, p22]
+ // [-2 0 +2] + [p01, pixel, p21]
+ // [-1 0 +1] [p00, p10, p20]
+ float3 gx = -p00.xyz + p20.xyz +
+ 2.0f * (p21.xyz - p01.xyz)
+ -p02.xyz + p22.xyz;
+
+ //Find Gy = kernel + 3x3 around current pixel
+ // Gy = [-1 -2 -1] [p02, p12, p22]
+ // [ 0 0 0] + [p01, pixel, p21]
+ // [+1 +2 +1] [p00, p10, p20]
+ float3 gy = p00.xyz + p20.xyz +
+ 2.0f * (- p12.xyz + p10.xyz) -
+ p02.xyz - p22.xyz;
+ //Find G
+ float3 g = native_sqrt(gx * gx + gy * gy);
+
+ // we could also approximate this as g = fabs(gx) + fabs(gy)
+ write_imagef(dst, (int2)(x, y), (float4)(g.x, g.y, g.z, 1.0f));
+ }
+);
+
+// This example shows how to apply sobel filter on images or on camera frames
+// with OpenCV, transfer the frames to the GPU, and apply a sobel filter
+// written in OpenCL
+int main(int argc, char *argv[])
+{
+ ///////////////////////////////////////////////////////////////////////////
+
+ // setup the command line arguments
+ po::options_description desc;
+ desc.add_options()
+ ("help", "show available options")
+ ("camera", po::value<int>()->default_value(-1),
+ "if not default camera, specify a camera id")
+ ("image", po::value<std::string>(), "path to image file");
+
+ // Parse the command lines
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //check the command line arguments
+ if(vm.count("help"))
+ {
+ std::cout << desc << std::endl;
+ return 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ //OpenCV variables
+ cv::Mat cv_mat;
+ cv::VideoCapture cap; //OpenCV camera handle.
+
+ //OpenCL variables
+ // Get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ compute::program filter_program =
+ compute::program::create_with_source(source, context);
+
+ try
+ {
+ filter_program.build();
+ }
+ catch(compute::opencl_error e)
+ {
+ std::cout<<"Build Error: "<<std::endl
+ <<filter_program.build_log();
+ }
+
+ // create fliter kernel and set arguments
+ compute::kernel filter_kernel(filter_program, "sobel_rgb");
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ //check for image paths
+ if(vm.count("image"))
+ {
+ // Read image with OpenCV
+ cv_mat = cv::imread(vm["image"].as<std::string>(),
+ CV_LOAD_IMAGE_COLOR);
+ if(!cv_mat.data){
+ std::cerr << "Failed to load image" << std::endl;
+ return -1;
+ }
+ }
+ else //by default use camera
+ {
+ //open camera
+ cap.open(vm["camera"].as<int>());
+ // read first frame
+ cap >> cv_mat;
+ if(!cv_mat.data){
+ std::cerr << "failed to capture frame" << std::endl;
+ return -1;
+ }
+ }
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(cv_mat, cv_mat, CV_BGR2BGRA);
+
+ // Transfer image/frame data to gpu
+ compute::image2d dev_input_image =
+ compute::opencv_create_image2d_with_mat(
+ cv_mat, compute::image2d::read_write, queue
+ );
+
+ // Create output image
+ // Be sure what will be your ouput image/frame size
+ compute::image2d dev_output_image(
+ context,
+ dev_input_image.width(),
+ dev_input_image.height(),
+ dev_input_image.format(),
+ compute::image2d::write_only
+ );
+
+ filter_kernel.set_arg(0, dev_input_image);
+ filter_kernel.set_arg(1, dev_output_image);
+
+
+ // run flip kernel
+ size_t origin[2] = { 0, 0 };
+ size_t region[2] = { dev_input_image.width(),
+ dev_input_image.height() };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ queue.enqueue_nd_range_kernel(filter_kernel, 2, origin, region, 0);
+
+ //check for image paths
+ if(vm.count("image"))
+ {
+ // show host image
+ cv::imshow("Original Image", cv_mat);
+
+ // show gpu image
+ compute::opencv_imshow("Filtered Image", dev_output_image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+ }
+ else
+ {
+ char key = '\0';
+ while(key != 27) //check for escape key
+ {
+ cap >> cv_mat;
+
+ // Convert image to BGRA (OpenCL requires 16-byte aligned data)
+ cv::cvtColor(cv_mat, cv_mat, CV_BGR2BGRA);
+
+ // Update the device image memory with current frame data
+ compute::opencv_copy_mat_to_image(cv_mat,
+ dev_input_image,queue);
+
+ // Run the kernel on the device
+ queue.enqueue_nd_range_kernel(filter_kernel, 2, origin, region, 0);
+
+ // Show host image
+ cv::imshow("Camera Frame", cv_mat);
+
+ // Show GPU image
+ compute::opencv_imshow("Filtered RGB Frame", dev_output_image, queue);
+
+ // wait
+ key = cv::waitKey(10);
+ }
+ }
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/opengl_sphere.cpp b/src/boost/libs/compute/example/opengl_sphere.cpp
new file mode 100644
index 00000000..38999f34
--- /dev/null
+++ b/src/boost/libs/compute/example/opengl_sphere.cpp
@@ -0,0 +1,242 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <algorithm>
+
+#include <GL/gl.h>
+
+#include <vtkActor.h>
+#include <vtkCamera.h>
+#include <vtkgl.h>
+#include <vtkInteractorStyleSwitch.h>
+#include <vtkMapper.h>
+#include <vtkObjectFactory.h>
+#include <vtkOpenGLExtensionManager.h>
+#include <vtkOpenGLRenderWindow.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkSmartPointer.h>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/interop/opengl.hpp>
+#include <boost/compute/interop/vtk.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// tesselates a sphere with radius, phi_slices, and theta_slices. returns
+// a shared opencl/opengl buffer containing the vertex data.
+compute::opengl_buffer tesselate_sphere(float radius,
+ size_t phi_slices,
+ size_t theta_slices,
+ compute::command_queue &queue)
+{
+ using compute::dim;
+
+ const compute::context &context = queue.get_context();
+
+ const size_t vertex_count = phi_slices * theta_slices;
+
+ // create opengl buffer
+ GLuint vbo;
+ vtkgl::GenBuffersARB(1, &vbo);
+ vtkgl::BindBufferARB(vtkgl::ARRAY_BUFFER, vbo);
+ vtkgl::BufferDataARB(vtkgl::ARRAY_BUFFER,
+ sizeof(float) * 4 * vertex_count,
+ NULL,
+ vtkgl::STREAM_DRAW);
+ vtkgl::BindBufferARB(vtkgl::ARRAY_BUFFER, 0);
+
+ // create shared opengl/opencl buffer
+ compute::opengl_buffer vertex_buffer(context, vbo);
+
+ // tesselate_sphere kernel source
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void tesselate_sphere(float radius,
+ uint phi_slices,
+ uint theta_slices,
+ __global float4 *vertex_buffer)
+ {
+ const uint phi_i = get_global_id(0);
+ const uint theta_i = get_global_id(1);
+
+ const float phi = phi_i * 2.f * M_PI_F / phi_slices;
+ const float theta = theta_i * 2.f * M_PI_F / theta_slices;
+
+ float4 v;
+ v.x = radius * cos(theta) * cos(phi);
+ v.y = radius * cos(theta) * sin(phi);
+ v.z = radius * sin(theta);
+ v.w = 1.f;
+
+ vertex_buffer[phi_i*phi_slices+theta_i] = v;
+ }
+ );
+
+ // build tesselate_sphere program
+ compute::program program =
+ compute::program::create_with_source(source, context);
+ program.build();
+
+ // setup tesselate_sphere kernel
+ compute::kernel kernel(program, "tesselate_sphere");
+ kernel.set_arg<compute::float_>(0, radius);
+ kernel.set_arg<compute::uint_>(1, phi_slices);
+ kernel.set_arg<compute::uint_>(2, theta_slices);
+ kernel.set_arg(3, vertex_buffer);
+
+ // acqurire buffer so that it is accessible to OpenCL
+ compute::opengl_enqueue_acquire_buffer(vertex_buffer, queue);
+
+ // execute tesselate_sphere kernel
+ queue.enqueue_nd_range_kernel(
+ kernel, dim(0, 0), dim(phi_slices, theta_slices), dim(1, 1)
+ );
+
+ // release buffer so that it is accessible to OpenGL
+ compute::opengl_enqueue_release_buffer(vertex_buffer, queue);
+
+ return vertex_buffer;
+}
+
+// simple vtkMapper subclass to render the tesselated sphere on the gpu.
+class gpu_sphere_mapper : public vtkMapper
+{
+public:
+ vtkTypeMacro(gpu_sphere_mapper, vtkMapper)
+
+ static gpu_sphere_mapper* New()
+ {
+ return new gpu_sphere_mapper;
+ }
+
+ void Render(vtkRenderer *renderer, vtkActor *actor)
+ {
+ if(!m_initialized){
+ Initialize(renderer, actor);
+ m_initialized = true;
+ }
+
+ if(!m_tesselated){
+ m_vertex_count = m_phi_slices * m_theta_slices;
+
+ // tesselate sphere
+ m_vertex_buffer = tesselate_sphere(
+ m_radius, m_phi_slices, m_theta_slices, m_command_queue
+ );
+
+ // ensure tesselation is finished (seems to be required on AMD)
+ m_command_queue.finish();
+
+ // set tesselated flag to true
+ m_tesselated = true;
+ }
+
+ // draw sphere
+ glEnableClientState(GL_VERTEX_ARRAY);
+ vtkgl::BindBufferARB(vtkgl::ARRAY_BUFFER, m_vertex_buffer.get_opengl_object());
+ glVertexPointer(4, GL_FLOAT, sizeof(float)*4, 0);
+ glDrawArrays(GL_POINTS, 0, m_vertex_count);
+ }
+
+ void Initialize(vtkRenderer *renderer, vtkActor *actor)
+ {
+ // initialize opengl extensions
+ vtkOpenGLExtensionManager *extensions =
+ static_cast<vtkOpenGLRenderWindow *>(renderer->GetRenderWindow())
+ ->GetExtensionManager();
+ extensions->LoadExtension("GL_ARB_vertex_buffer_object");
+
+ // initialize opencl/opengl shared context
+ m_context = compute::opengl_create_shared_context();
+ compute::device device = m_context.get_device();
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create command queue for the gpu device
+ m_command_queue = compute::command_queue(m_context, device);
+ }
+
+ double* GetBounds()
+ {
+ static double bounds[6];
+ bounds[0] = -m_radius; bounds[1] = m_radius;
+ bounds[2] = -m_radius; bounds[3] = m_radius;
+ bounds[4] = -m_radius; bounds[5] = m_radius;
+ return bounds;
+ }
+
+protected:
+ gpu_sphere_mapper()
+ {
+ m_radius = 5.0f;
+ m_phi_slices = 100;
+ m_theta_slices = 100;
+ m_initialized = false;
+ m_tesselated = false;
+ }
+
+private:
+ float m_radius;
+ int m_phi_slices;
+ int m_theta_slices;
+ int m_vertex_count;
+ bool m_initialized;
+ bool m_tesselated;
+ compute::context m_context;
+ compute::command_queue m_command_queue;
+ compute::opengl_buffer m_vertex_buffer;
+};
+
+int main(int argc, char *argv[])
+{
+ // create gpu sphere mapper
+ vtkSmartPointer<gpu_sphere_mapper> mapper =
+ vtkSmartPointer<gpu_sphere_mapper>::New();
+
+ // create actor for gpu sphere mapper
+ vtkSmartPointer<vtkActor> actor =
+ vtkSmartPointer<vtkActor>::New();
+ actor->GetProperty()->LightingOff();
+ actor->GetProperty()->SetInterpolationToFlat();
+ actor->SetMapper(mapper);
+
+ // create render window
+ vtkSmartPointer<vtkRenderer> renderer =
+ vtkSmartPointer<vtkRenderer>::New();
+ renderer->SetBackground(.1, .2, .31);
+ vtkSmartPointer<vtkRenderWindow> renderWindow =
+ vtkSmartPointer<vtkRenderWindow>::New();
+ renderWindow->SetSize(800, 600);
+ renderWindow->AddRenderer(renderer);
+ vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
+ vtkSmartPointer<vtkRenderWindowInteractor>::New();
+ vtkInteractorStyleSwitch *interactorStyle =
+ vtkInteractorStyleSwitch::SafeDownCast(
+ renderWindowInteractor->GetInteractorStyle()
+ );
+ interactorStyle->SetCurrentStyleToTrackballCamera();
+ renderWindowInteractor->SetRenderWindow(renderWindow);
+ renderer->AddActor(actor);
+
+ // render
+ renderer->ResetCamera();
+ vtkCamera *camera = renderer->GetActiveCamera();
+ camera->Elevation(-90.0);
+ renderWindowInteractor->Initialize();
+ renderWindow->Render();
+ renderWindowInteractor->Start();
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/point_centroid.cpp b/src/boost/libs/compute/example/point_centroid.cpp
new file mode 100644
index 00000000..e5691f7c
--- /dev/null
+++ b/src/boost/libs/compute/example/point_centroid.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.
+//---------------------------------------------------------------------------//
+
+//[point_centroid_example
+
+#include <iostream>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/types/fundamental.hpp>
+
+namespace compute = boost::compute;
+
+// the point centroid example calculates and displays the
+// centroid of a set of 3D points stored as float4's
+int main()
+{
+ using compute::float4_;
+
+ // get default device and setup context
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ // point coordinates
+ float points[] = { 1.0f, 2.0f, 3.0f, 0.0f,
+ -2.0f, -3.0f, 4.0f, 0.0f,
+ 1.0f, -2.0f, 2.5f, 0.0f,
+ -7.0f, -3.0f, -2.0f, 0.0f,
+ 3.0f, 4.0f, -5.0f, 0.0f };
+
+ // create vector for five points
+ compute::vector<float4_> vector(5, context);
+
+ // copy point data to the device
+ compute::copy(
+ reinterpret_cast<float4_ *>(points),
+ reinterpret_cast<float4_ *>(points) + 5,
+ vector.begin(),
+ queue
+ );
+
+ // calculate sum
+ float4_ sum = compute::accumulate(
+ vector.begin(), vector.end(), float4_(0, 0, 0, 0), queue
+ );
+
+ // calculate centroid
+ float4_ centroid;
+ for(size_t i = 0; i < 3; i++){
+ centroid[i] = sum[i] / 5.0f;
+ }
+
+ // print centroid
+ std::cout << "centroid: " << centroid << std::endl;
+
+ return 0;
+}
+
+//]
diff --git a/src/boost/libs/compute/example/price_cross.cpp b/src/boost/libs/compute/example/price_cross.cpp
new file mode 100644
index 00000000..95196494
--- /dev/null
+++ b/src/boost/libs/compute/example/price_cross.cpp
@@ -0,0 +1,87 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 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 <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/find_if.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/iterator/zip_iterator.hpp>
+
+namespace compute = boost::compute;
+
+// this example shows how to use the find_if() algorithm to detect the
+// point at which two vectors of prices (such as stock prices) cross.
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ // prices #1 (from 10.0 to 11.0)
+ std::vector<float> prices1;
+ for(float i = 10.0; i <= 11.0; i += 0.1){
+ prices1.push_back(i);
+ }
+
+ // prices #2 (from 11.0 to 10.0)
+ std::vector<float> prices2;
+ for(float i = 11.0; i >= 10.0; i -= 0.1){
+ prices2.push_back(i);
+ }
+
+ // create gpu vectors
+ compute::vector<float> gpu_prices1(prices1.size(), context);
+ compute::vector<float> gpu_prices2(prices2.size(), context);
+
+ // copy prices to gpu
+ compute::copy(prices1.begin(), prices1.end(), gpu_prices1.begin(), queue);
+ compute::copy(prices2.begin(), prices2.end(), gpu_prices2.begin(), queue);
+
+ // function returning true if the second price is less than the first price
+ BOOST_COMPUTE_FUNCTION(bool, check_price_cross, (boost::tuple<float, float> prices),
+ {
+ // first price
+ const float first = boost_tuple_get(prices, 0);
+
+ // second price
+ const float second = boost_tuple_get(prices, 1);
+
+ // return true if second price is less than first
+ return second < first;
+ });
+
+ // find cross point (should be 10.5)
+ compute::vector<float>::iterator iter = boost::get<0>(
+ compute::find_if(
+ compute::make_zip_iterator(
+ boost::make_tuple(gpu_prices1.begin(), gpu_prices2.begin())
+ ),
+ compute::make_zip_iterator(
+ boost::make_tuple(gpu_prices1.end(), gpu_prices2.end())
+ ),
+ check_price_cross,
+ queue
+ ).get_iterator_tuple()
+ );
+
+ // print out result
+ int index = std::distance(gpu_prices1.begin(), iter);
+ std::cout << "price cross at index: " << index << std::endl;
+
+ float value;
+ compute::copy_n(iter, 1, &value, queue);
+ std::cout << "value: " << value << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/print_vector.cpp b/src/boost/libs/compute/example/print_vector.cpp
new file mode 100644
index 00000000..9ec5c6c7
--- /dev/null
+++ b/src/boost/libs/compute/example/print_vector.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/iota.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace compute = boost::compute;
+
+// this example demonstrates how to print the values in a vector
+int main()
+{
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // create vector on the device and fill with the sequence 1..10
+ compute::vector<int> vector(10, context);
+ compute::iota(vector.begin(), vector.end(), 1, queue);
+
+//[print_vector_example
+ std::cout << "vector: [ ";
+ boost::compute::copy(
+ vector.begin(), vector.end(),
+ std::ostream_iterator<int>(std::cout, ", "),
+ queue
+ );
+ std::cout << "]" << std::endl;
+//]
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/qimage_blur.cpp b/src/boost/libs/compute/example/qimage_blur.cpp
new file mode 100644
index 00000000..cbfa3145
--- /dev/null
+++ b/src/boost/libs/compute/example/qimage_blur.cpp
@@ -0,0 +1,145 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 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 <iostream>
+#include <algorithm>
+
+#include <QtGlobal>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+
+#ifndef Q_MOC_RUN
+#include <boost/compute/system.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/interop/qt.hpp>
+#include <boost/compute/utility/dim.hpp>
+#include <boost/compute/utility/source.hpp>
+#endif // Q_MOC_RUN
+
+namespace compute = boost::compute;
+
+inline void box_filter_image(const compute::image2d &input,
+ compute::image2d &output,
+ compute::uint_ box_height,
+ compute::uint_ box_width,
+ compute::command_queue &queue)
+{
+ using compute::dim;
+
+ const compute::context &context = queue.get_context();
+
+ // simple box filter kernel source
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void box_filter(__read_only image2d_t input,
+ __write_only image2d_t output,
+ uint box_height,
+ uint box_width)
+ {
+ int x = get_global_id(0);
+ int y = get_global_id(1);
+ int h = get_image_height(input);
+ int w = get_image_width(input);
+ int k = box_width;
+ int l = box_height;
+
+ if(x < k/2 || y < l/2 || x >= w-(k/2) || y >= h-(l/2)){
+ write_imagef(output, (int2)(x, y), (float4)(0, 0, 0, 1));
+ }
+ else {
+ const sampler_t sampler = CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
+
+ float4 sum = { 0, 0, 0, 0 };
+ for(int i = 0; i < k; i++){
+ for(int j = 0; j < l; j++){
+ sum += read_imagef(input, sampler, (int2)(x+i-k, y+j-l));
+ }
+ }
+ sum /= (float) k * l;
+ float4 value = (float4)( sum.x, sum.y, sum.z, 1.f );
+ write_imagef(output, (int2)(x, y), value);
+ }
+ }
+ );
+
+ // build box filter program
+ compute::program program =
+ compute::program::create_with_source(source, context);
+ program.build();
+
+ // setup box filter kernel
+ compute::kernel kernel(program, "box_filter");
+ kernel.set_arg(0, input);
+ kernel.set_arg(1, output);
+ kernel.set_arg(2, box_height);
+ kernel.set_arg(3, box_width);
+
+ // execute the box filter kernel
+ queue.enqueue_nd_range_kernel(kernel, dim(0, 0), input.size(), dim(1, 1));
+}
+
+// this example shows how to load an image using Qt, apply a simple
+// box blur filter, and then display it in a Qt window.
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ // check command line
+ if(argc < 2){
+ std::cout << "usage: qimage_blur [FILENAME]" << std::endl;
+ return -1;
+ }
+
+ // load image using Qt
+ QString fileName = argv[1];
+ QImage qimage(fileName);
+
+ size_t height = qimage.height();
+ size_t width = qimage.width();
+ size_t bytes_per_line = qimage.bytesPerLine();
+
+ qDebug() << "height:" << height
+ << "width:" << width
+ << "bytes per line:" << bytes_per_line
+ << "depth:" << qimage.depth()
+ << "format:" << qimage.format();
+
+ // create compute context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // get the opencl image format for the qimage
+ compute::image_format format =
+ compute::qt_qimage_format_to_image_format(qimage.format());
+
+ // create input and output images on the gpu
+ compute::image2d input_image(context, width, height, format);
+ compute::image2d output_image(context, width, height, format);
+
+ // copy host qimage to gpu image
+ compute::qt_copy_qimage_to_image2d(qimage, input_image, queue);
+
+ // apply box filter
+ box_filter_image(input_image, output_image, 7, 7, queue);
+
+ // copy gpu blurred image from to host qimage
+ compute::qt_copy_image2d_to_qimage(output_image, qimage, queue);
+
+ // show image as a pixmap
+ QLabel label;
+ label.setPixmap(QPixmap::fromImage(qimage));
+ label.show();
+
+ return app.exec();
+}
diff --git a/src/boost/libs/compute/example/random_walk.cpp b/src/boost/libs/compute/example/random_walk.cpp
new file mode 100644
index 00000000..13106d96
--- /dev/null
+++ b/src/boost/libs/compute/example/random_walk.cpp
@@ -0,0 +1,153 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/interop/opencv/core.hpp>
+#include <boost/compute/interop/opencv/highgui.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_real_distribution.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+// this example uses the random-number generation functions in Boost.Compute
+// to calculate a large number of random "steps" and then plots the final
+// random "walk" in a 2D image on the GPU and displays it with OpenCV
+int main()
+{
+ // number of random steps to take
+ size_t steps = 250000;
+
+ // height and width of image
+ size_t height = 800;
+ size_t width = 800;
+
+ // get default device and setup context
+ compute::device gpu = compute::system::default_device();
+ compute::context context(gpu);
+ compute::command_queue queue(context, gpu);
+
+ using compute::int2_;
+
+ // calaculate random values for each step
+ compute::vector<float> random_values(steps, context);
+ compute::default_random_engine random_engine(queue);
+ compute::uniform_real_distribution<float> random_distribution(0.f, 4.f);
+
+ random_distribution.generate(
+ random_values.begin(), random_values.end(), random_engine, queue
+ );
+
+ // calaculate coordinates for each step
+ compute::vector<int2_> coordinates(steps, context);
+
+ // function to convert random values to random directions (in 2D)
+ BOOST_COMPUTE_FUNCTION(int2_, take_step, (const float x),
+ {
+ if(x < 1.f){
+ // move right
+ return (int2)(1, 0);
+ }
+ if(x < 2.f){
+ // move up
+ return (int2)(0, 1);
+ }
+ if(x < 3.f){
+ // move left
+ return (int2)(-1, 0);
+ }
+ else {
+ // move down
+ return (int2)(0, -1);
+ }
+ });
+
+ // transform the random values into random steps
+ compute::transform(
+ random_values.begin(), random_values.end(), coordinates.begin(), take_step, queue
+ );
+
+ // set staring position
+ int2_ starting_position(width / 2, height / 2);
+ compute::copy_n(&starting_position, 1, coordinates.begin(), queue);
+
+ // scan steps to calculate position after each step
+ compute::inclusive_scan(
+ coordinates.begin(), coordinates.end(), coordinates.begin(), queue
+ );
+
+ // create output image
+ compute::image2d image(
+ context, width, height, compute::image_format(CL_RGBA, CL_UNSIGNED_INT8)
+ );
+
+ // program with two kernels, one to fill the image with white, and then
+ // one the draw to points calculated in coordinates on the image
+ const char draw_walk_source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void draw_walk(__global const int2 *coordinates,
+ __write_only image2d_t image)
+ {
+ const uint i = get_global_id(0);
+ const int2 coord = coordinates[i];
+
+ if(coord.x > 0 && coord.x < get_image_width(image) &&
+ coord.y > 0 && coord.y < get_image_height(image)){
+ uint4 black = { 0, 0, 0, 0 };
+ write_imageui(image, coord, black);
+ }
+ }
+
+ __kernel void fill_white(__write_only image2d_t image)
+ {
+ const int2 coord = { get_global_id(0), get_global_id(1) };
+
+ if(coord.x < get_image_width(image) &&
+ coord.y < get_image_height(image)){
+ uint4 white = { 255, 255, 255, 255 };
+ write_imageui(image, coord, white);
+ }
+ }
+ );
+
+ // build the program
+ compute::program draw_program =
+ compute::program::build_with_source(draw_walk_source, context);
+
+ // fill image with white
+ compute::kernel fill_kernel(draw_program, "fill_white");
+ fill_kernel.set_arg(0, image);
+
+ const size_t offset[] = { 0, 0 };
+ const size_t bounds[] = { width, height };
+
+ queue.enqueue_nd_range_kernel(fill_kernel, 2, offset, bounds, 0);
+
+ // draw random walk
+ compute::kernel draw_kernel(draw_program, "draw_walk");
+ draw_kernel.set_arg(0, coordinates);
+ draw_kernel.set_arg(1, image);
+ queue.enqueue_1d_range_kernel(draw_kernel, 0, coordinates.size(), 0);
+
+ // show image
+ compute::opencv_imshow("random walk", image, queue);
+
+ // wait and return
+ cv::waitKey(0);
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/resize_image.cpp b/src/boost/libs/compute/example/resize_image.cpp
new file mode 100644
index 00000000..d9e29edd
--- /dev/null
+++ b/src/boost/libs/compute/example/resize_image.cpp
@@ -0,0 +1,253 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <algorithm>
+
+#include <QtGlobal>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#else
+#include <QtGui>
+#endif
+#include <QtOpenGL>
+
+#include <boost/program_options.hpp>
+
+#ifndef Q_MOC_RUN
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/kernel.hpp>
+#include <boost/compute/program.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/image/image2d.hpp>
+#include <boost/compute/image/image_sampler.hpp>
+#include <boost/compute/interop/qt.hpp>
+#include <boost/compute/interop/opengl.hpp>
+#include <boost/compute/utility/source.hpp>
+#endif // Q_MOC_RUN
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+// opencl source code
+const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void resize_image(__read_only image2d_t input,
+ const sampler_t sampler,
+ __write_only image2d_t output)
+ {
+ const uint x = get_global_id(0);
+ const uint y = get_global_id(1);
+
+ const float w = get_image_width(output);
+ const float h = get_image_height(output);
+
+ float2 coord = { ((float) x / w) * get_image_width(input),
+ ((float) y / h) * get_image_height(input) };
+
+ float4 pixel = read_imagef(input, sampler, coord);
+ write_imagef(output, (int2)(x, h - y - 1), pixel);
+ };
+);
+
+class ImageWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ ImageWidget(QString fileName, QWidget *parent = 0);
+ ~ImageWidget();
+
+ void initializeGL();
+ void resizeGL(int width, int height);
+ void paintGL();
+
+private:
+ QImage qt_image_;
+ compute::context context_;
+ compute::command_queue queue_;
+ compute::program program_;
+ compute::image2d image_;
+ compute::image_sampler sampler_;
+ GLuint gl_texture_;
+ compute::opengl_texture cl_texture_;
+};
+
+ImageWidget::ImageWidget(QString fileName, QWidget *parent)
+ : QGLWidget(parent),
+ qt_image_(fileName)
+{
+ gl_texture_ = 0;
+}
+
+ImageWidget::~ImageWidget()
+{
+}
+
+void ImageWidget::initializeGL()
+{
+ // setup opengl
+ glDisable(GL_LIGHTING);
+
+ // create the OpenGL/OpenCL shared context
+ context_ = compute::opengl_create_shared_context();
+
+ // get gpu device
+ compute::device gpu = context_.get_device();
+ std::cout << "device: " << gpu.name() << std::endl;
+
+ // setup command queue
+ queue_ = compute::command_queue(context_, gpu);
+
+ // allocate image on the device
+ compute::image_format format =
+ compute::qt_qimage_format_to_image_format(qt_image_.format());
+
+ image_ = compute::image2d(
+ context_, qt_image_.width(), qt_image_.height(), format, CL_MEM_READ_ONLY
+ );
+
+ // transfer image to the device
+ compute::qt_copy_qimage_to_image2d(qt_image_, image_, queue_);
+
+ // setup image sampler (use CL_FILTER_NEAREST to disable linear interpolation)
+ sampler_ = compute::image_sampler(
+ context_, false, CL_ADDRESS_NONE, CL_FILTER_LINEAR
+ );
+
+ // build resize program
+ program_ = compute::program::build_with_source(source, context_);
+}
+
+void ImageWidget::resizeGL(int width, int height)
+{
+#if QT_VERSION >= 0x050000
+ // scale height/width based on device pixel ratio
+ width /= windowHandle()->devicePixelRatio();
+ height /= windowHandle()->devicePixelRatio();
+#endif
+
+ // resize viewport
+ glViewport(0, 0, width, height);
+
+ // delete old texture
+ if(gl_texture_){
+ glDeleteTextures(1, &gl_texture_);
+ gl_texture_ = 0;
+ }
+
+ // generate new texture
+ glGenTextures(1, &gl_texture_);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0
+ );
+
+ // create opencl object for the texture
+ cl_texture_ = compute::opengl_texture(
+ context_, GL_TEXTURE_2D, 0, gl_texture_, CL_MEM_WRITE_ONLY
+ );
+}
+
+void ImageWidget::paintGL()
+{
+ float w = width();
+ float h = height();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, w, 0.0, h, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // setup the resize kernel
+ compute::kernel kernel(program_, "resize_image");
+ kernel.set_arg(0, image_);
+ kernel.set_arg(1, sampler_);
+ kernel.set_arg(2, cl_texture_);
+
+ // acquire the opengl texture so it can be used in opencl
+ compute::opengl_enqueue_acquire_gl_objects(1, &cl_texture_.get(), queue_);
+
+ // execute the resize kernel
+ const size_t global_work_offset[] = { 0, 0 };
+ const size_t global_work_size[] = { size_t(width()), size_t(height()) };
+
+ queue_.enqueue_nd_range_kernel(
+ kernel, 2, global_work_offset, global_work_size, 0
+ );
+
+ // release the opengl texture so it can be used by opengl
+ compute::opengl_enqueue_release_gl_objects(1, &cl_texture_.get(), queue_);
+
+ // ensure opencl is finished before rendering in opengl
+ queue_.finish();
+
+ // draw a single quad with the resized image texture
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(0, 0);
+ glTexCoord2f(0, 1); glVertex2f(0, h);
+ glTexCoord2f(1, 1); glVertex2f(w, h);
+ glTexCoord2f(1, 0); glVertex2f(w, 0);
+ glEnd();
+}
+
+// the resize image example demonstrates how to interactively resize a
+// 2D image and display it using OpenGL. a image sampler is used to perform
+// hardware-accelerated linear interpolation for the resized image.
+int main(int argc, char *argv[])
+{
+ // setup command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("file", po::value<std::string>(), "image file name (e.g. /path/to/image.png)")
+ ;
+ po::positional_options_description positional_options;
+ positional_options.add("file", 1);
+
+ // parse command line
+ po::variables_map vm;
+ po::store(
+ po::command_line_parser(argc, argv)
+ .options(options)
+ .positional(positional_options)
+ .run(),
+ vm
+ );
+ po::notify(vm);
+
+ // check for file argument
+ if(vm.count("help") || !vm.count("file")){
+ std::cout << options << std::endl;
+ return -1;
+ }
+
+ // get file name
+ std::string file_name = vm["file"].as<std::string>();
+
+ // setup qt application
+ QApplication app(argc, argv);
+
+ // setup image widget
+ ImageWidget widget(QString::fromStdString(file_name));
+ widget.show();
+
+ // run qt application
+ return app.exec();
+}
+
+#include "resize_image.moc"
diff --git a/src/boost/libs/compute/example/simple_kernel.cpp b/src/boost/libs/compute/example/simple_kernel.cpp
new file mode 100644
index 00000000..4aa1872f
--- /dev/null
+++ b/src/boost/libs/compute/example/simple_kernel.cpp
@@ -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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+
+#include <boost/compute/core.hpp>
+
+namespace compute = boost::compute;
+
+// this example demonstrates how to use the Boost.Compute classes to
+// setup and run a simple vector addition kernel on the GPU
+int main()
+{
+ // get the default device
+ compute::device device = compute::system::default_device();
+
+ // create a context for the device
+ compute::context context(device);
+
+ // setup input arrays
+ float a[] = { 1, 2, 3, 4 };
+ float b[] = { 5, 6, 7, 8 };
+
+ // make space for the output
+ float c[] = { 0, 0, 0, 0 };
+
+ // create memory buffers for the input and output
+ compute::buffer buffer_a(context, 4 * sizeof(float));
+ compute::buffer buffer_b(context, 4 * sizeof(float));
+ compute::buffer buffer_c(context, 4 * sizeof(float));
+
+ // source code for the add kernel
+ const char source[] =
+ "__kernel void add(__global const float *a,"
+ " __global const float *b,"
+ " __global float *c)"
+ "{"
+ " const uint i = get_global_id(0);"
+ " c[i] = a[i] + b[i];"
+ "}";
+
+ // create the program with the source
+ compute::program program =
+ compute::program::create_with_source(source, context);
+
+ // compile the program
+ program.build();
+
+ // create the kernel
+ compute::kernel kernel(program, "add");
+
+ // set the kernel arguments
+ kernel.set_arg(0, buffer_a);
+ kernel.set_arg(1, buffer_b);
+ kernel.set_arg(2, buffer_c);
+
+ // create a command queue
+ compute::command_queue queue(context, device);
+
+ // write the data from 'a' and 'b' to the device
+ queue.enqueue_write_buffer(buffer_a, 0, 4 * sizeof(float), a);
+ queue.enqueue_write_buffer(buffer_b, 0, 4 * sizeof(float), b);
+
+ // run the add kernel
+ queue.enqueue_1d_range_kernel(kernel, 0, 4, 0);
+
+ // transfer results back to the host array 'c'
+ queue.enqueue_read_buffer(buffer_c, 0, 4 * sizeof(float), c);
+
+ // print out results in 'c'
+ std::cout << "c: [" << c[0] << ", "
+ << c[1] << ", "
+ << c[2] << ", "
+ << c[3] << "]" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/simple_moving_average.cpp b/src/boost/libs/compute/example/simple_moving_average.cpp
new file mode 100644
index 00000000..968db393
--- /dev/null
+++ b/src/boost/libs/compute/example/simple_moving_average.cpp
@@ -0,0 +1,139 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Benoit Dequidt <benoit.dequidt@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 <iostream>
+#include <cstdlib>
+
+#include <boost/compute/core.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/type_traits/type_name.hpp>
+#include <boost/compute/utility/source.hpp>
+
+namespace compute = boost::compute;
+
+/// warning precision is not precise due
+/// to the float error accumulation when size is large enough
+/// for more precision use double
+/// or a kahan sum else results can diverge
+/// from the CPU implementation
+compute::program make_sma_program(const compute::context& context)
+{
+ const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
+ __kernel void SMA(__global const float *scannedValues, int size, __global float *output, int wSize)
+ {
+ const int gid = get_global_id(0);
+
+ float cumValues = 0.f;
+ int endIdx = gid + wSize/2;
+ int startIdx = gid -1 - wSize/2;
+
+ if(endIdx > size -1)
+ endIdx = size -1;
+
+ cumValues += scannedValues[endIdx];
+ if(startIdx < 0)
+ startIdx = -1;
+ else
+ cumValues -= scannedValues[startIdx];
+
+ output[gid] =(float)( cumValues / ( float )(endIdx - startIdx));
+ }
+ );
+
+ // create sma program
+ return compute::program::build_with_source(source,context);
+}
+
+bool check_results(const std::vector<float>& values, const std::vector<float>& smoothValues, unsigned int wSize)
+{
+ int size = values.size();
+ if(size != (int)smoothValues.size()) return false;
+
+ int semiWidth = wSize/2;
+
+ bool ret = true;
+ for(int idx = 0 ; idx < size ; ++idx)
+ {
+ int start = (std::max)(idx - semiWidth,0);
+ int end = (std::min)(idx + semiWidth,size-1);
+ float res = 0;
+ for(int j = start ; j <= end ; ++j)
+ {
+ res+= values[j];
+ }
+
+ res /= float(end - start +1);
+
+ if(std::abs(res-smoothValues[idx]) > 1e-3)
+ {
+ std::cout << "idx = " << idx << " -- expected = " << res << " -- result = " << smoothValues[idx] << std::endl;
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+// generate a uniform law over [0,10]
+float myRand()
+{
+ static const double divisor = double(RAND_MAX)+1.;
+ return double(rand())/divisor * 10.;
+}
+
+int main()
+{
+ unsigned int size = 1024;
+ // wSize must be odd
+ unsigned int wSize = 21;
+ // get the default device
+ compute::device device = compute::system::default_device();
+ // create a context for the device
+ compute::context context(device);
+ // get the program
+ compute::program program = make_sma_program(context);
+
+ // create vector of random numbers on the host
+ std::vector<float> host_vector(size);
+ std::vector<float> host_result(size);
+ std::generate(host_vector.begin(), host_vector.end(), myRand);
+
+ compute::vector<float> a(size,context);
+ compute::vector<float> b(size,context);
+ compute::vector<float> c(size,context);
+ compute::command_queue queue(context, device);
+
+ compute::copy(host_vector.begin(),host_vector.end(),a.begin(),queue);
+
+ // scan values
+ compute::inclusive_scan(a.begin(),a.end(),b.begin(),queue);
+ // sma kernel
+ compute::kernel kernel(program, "SMA");
+ kernel.set_arg(0,b.get_buffer());
+ kernel.set_arg(1,(int)b.size());
+ kernel.set_arg(2,c.get_buffer());
+ kernel.set_arg(3,(int)wSize);
+
+ using compute::uint_;
+ uint_ tpb = 128;
+ uint_ workSize = size;
+ queue.enqueue_1d_range_kernel(kernel,0,workSize,tpb);
+
+ compute::copy(c.begin(),c.end(),host_result.begin(),queue);
+
+ bool res = check_results(host_vector,host_result,wSize);
+ std::string status = res ? "results are equivalent" : "GPU results differs from CPU one's";
+ std::cout << status << std::endl;
+
+ return 0;
+}
+
diff --git a/src/boost/libs/compute/example/sort_vector.cpp b/src/boost/libs/compute/example/sort_vector.cpp
new file mode 100644
index 00000000..39ec8ea7
--- /dev/null
+++ b/src/boost/libs/compute/example/sort_vector.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace compute = boost::compute;
+
+int rand_int()
+{
+ return rand() % 100;
+}
+
+// this example demonstrates how to sort a vector of ints on the GPU
+int main()
+{
+ // create vector of random values on the host
+ std::vector<int> host_vector(10);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // print out input vector
+ std::cout << "input: [ ";
+ for(size_t i = 0; i < host_vector.size(); i++){
+ std::cout << host_vector[i];
+
+ if(i != host_vector.size() - 1){
+ std::cout << ", ";
+ }
+ }
+ std::cout << " ]" << std::endl;
+
+ // transfer the values to the device
+ compute::vector<int> device_vector = host_vector;
+
+ // sort the values on the device
+ compute::sort(device_vector.begin(), device_vector.end());
+
+ // transfer the values back to the host
+ compute::copy(device_vector.begin(),
+ device_vector.end(),
+ host_vector.begin());
+
+ // print out the sorted vector
+ std::cout << "output: [ ";
+ for(size_t i = 0; i < host_vector.size(); i++){
+ std::cout << host_vector[i];
+
+ if(i != host_vector.size() - 1){
+ std::cout << ", ";
+ }
+ }
+ std::cout << " ]" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/example/threefry_engine.cpp b/src/boost/libs/compute/example/threefry_engine.cpp
new file mode 100644
index 00000000..5cbf6c8e
--- /dev/null
+++ b/src/boost/libs/compute/example/threefry_engine.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+
+#include <boost/compute/random/threefry_engine.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/context.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/system.hpp>
+#include <iostream>
+
+int main()
+{
+ using boost::compute::uint_;
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ boost::compute::threefry_engine<> rng(queue);
+ boost::compute::vector<uint_> vector_ctr(20, context);
+
+ uint32_t ctr[20];
+ for(int i = 0; i < 10; i++) {
+ ctr[i*2] = i;
+ ctr[i*2+1] = 0;
+ }
+ boost::compute::copy(ctr, ctr+20, vector_ctr.begin(), queue);
+ rng.generate(vector_ctr.begin(), vector_ctr.end(), queue);
+ boost::compute::copy(vector_ctr.begin(), vector_ctr.end(), ctr, queue);
+
+ for(int i = 0; i < 10; i++) {
+ std::cout << std::hex << ctr[i*2] << " " << ctr[i*2+1] << std::endl;
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/compute/example/time_copy.cpp b/src/boost/libs/compute/example/time_copy.cpp
new file mode 100644
index 00000000..35168770
--- /dev/null
+++ b/src/boost/libs/compute/example/time_copy.cpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+//[time_copy_example
+
+#include <vector>
+#include <cstdlib>
+#include <iostream>
+
+#include <boost/compute/event.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/async/future.hpp>
+#include <boost/compute/container/vector.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get the default device
+ compute::device gpu = compute::system::default_device();
+
+ // create context for default device
+ compute::context context(gpu);
+
+ // create command queue with profiling enabled
+ compute::command_queue queue(
+ context, gpu, compute::command_queue::enable_profiling
+ );
+
+ // generate random data on the host
+ std::vector<int> host_vector(16000000);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ // create a vector on the device
+ compute::vector<int> device_vector(host_vector.size(), context);
+
+ // copy data from the host to the device
+ compute::future<void> future = compute::copy_async(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // wait for copy to finish
+ future.wait();
+
+ // get elapsed time from event profiling information
+ boost::chrono::milliseconds duration =
+ future.get_event().duration<boost::chrono::milliseconds>();
+
+ // print elapsed time in milliseconds
+ std::cout << "time: " << duration.count() << " ms" << std::endl;
+
+ return 0;
+}
+
+//]
diff --git a/src/boost/libs/compute/example/transform_sqrt.cpp b/src/boost/libs/compute/example/transform_sqrt.cpp
new file mode 100644
index 00000000..860063fc
--- /dev/null
+++ b/src/boost/libs/compute/example/transform_sqrt.cpp
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+//[transform_sqrt_example
+
+#include <vector>
+#include <algorithm>
+
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/math.hpp>
+
+namespace compute = boost::compute;
+
+int main()
+{
+ // get default device and setup context
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ // generate random data on the host
+ std::vector<float> host_vector(10000);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ // create a vector on the device
+ compute::vector<float> device_vector(host_vector.size(), context);
+
+ // transfer data from the host to the device
+ compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // calculate the square-root of each element in-place
+ compute::transform(
+ device_vector.begin(),
+ device_vector.end(),
+ device_vector.begin(),
+ compute::sqrt<float>(),
+ queue
+ );
+
+ // copy values back to the host
+ compute::copy(
+ device_vector.begin(), device_vector.end(), host_vector.begin(), queue
+ );
+
+ return 0;
+}
+
+//]
diff --git a/src/boost/libs/compute/example/vector_addition.cpp b/src/boost/libs/compute/example/vector_addition.cpp
new file mode 100644
index 00000000..1f3aa92d
--- /dev/null
+++ b/src/boost/libs/compute/example/vector_addition.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/functional/operator.hpp>
+
+namespace compute = boost::compute;
+
+// this example demonstrates how to use Boost.Compute's STL
+// implementation to add two vectors on the GPU
+int main()
+{
+ // setup input arrays
+ float a[] = { 1, 2, 3, 4 };
+ float b[] = { 5, 6, 7, 8 };
+
+ // make space for the output
+ float c[] = { 0, 0, 0, 0 };
+
+ // create vectors and transfer data for the input arrays 'a' and 'b'
+ compute::vector<float> vector_a(a, a + 4);
+ compute::vector<float> vector_b(b, b + 4);
+
+ // create vector for the output array
+ compute::vector<float> vector_c(4);
+
+ // add the vectors together
+ compute::transform(
+ vector_a.begin(),
+ vector_a.end(),
+ vector_b.begin(),
+ vector_c.begin(),
+ compute::plus<float>()
+ );
+
+ // transfer results back to the host array 'c'
+ compute::copy(vector_c.begin(), vector_c.end(), c);
+
+ // print out results in 'c'
+ std::cout << "c: [" << c[0] << ", "
+ << c[1] << ", "
+ << c[2] << ", "
+ << c[3] << "]" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/index.html b/src/boost/libs/compute/index.html
new file mode 100644
index 00000000..a5accd49
--- /dev/null
+++ b/src/boost/libs/compute/index.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="doc/html/index.html">doc/html/index.html</a>
+<hr>
+<tt>
+Boost.Compute<br>
+<br>
+Copyright (C) 2013-2015 Kyle Lutz<br>
+<br>
+Distributed under the Boost Software License, Version 1.0. (See
+accompanying file LICENSE_1_0.txt or copy at
+<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
+<br>
+</tt>
+</body>
+</html>
diff --git a/src/boost/libs/compute/meta/libraries.json b/src/boost/libs/compute/meta/libraries.json
new file mode 100644
index 00000000..9e70fdd4
--- /dev/null
+++ b/src/boost/libs/compute/meta/libraries.json
@@ -0,0 +1,14 @@
+{
+ "key": "compute",
+ "name": "Compute",
+ "authors": [
+ "Kyle Lutz"
+ ],
+ "description": "Parallel/GPU-computing library",
+ "category": [
+ "Concurrent"
+ ],
+ "maintainers": [
+ "Kyle Lutz <kyle.r.lutz -at- gmail.com>"
+ ]
+}
diff --git a/src/boost/libs/compute/perf/CMakeLists.txt b/src/boost/libs/compute/perf/CMakeLists.txt
new file mode 100644
index 00000000..b04429e9
--- /dev/null
+++ b/src/boost/libs/compute/perf/CMakeLists.txt
@@ -0,0 +1,210 @@
+# ---------------------------------------------------------------------------
+# 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(PERF_BOOST_COMPONENTS system timer chrono program_options)
+
+if (${BOOST_COMPUTE_USE_OFFLINE_CACHE})
+ set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} filesystem)
+endif()
+
+if(${BOOST_COMPUTE_THREAD_SAFE} AND NOT ${BOOST_COMPUTE_USE_CPP11})
+ set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} thread)
+elseif(${BOOST_COMPUTE_HAVE_BOLT} AND ${BOOST_COMPUTE_USE_CPP11})
+ set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} thread)
+endif()
+
+if(${BOOST_COMPUTE_HAVE_BOLT} AND ${BOOST_COMPUTE_USE_CPP11})
+ set(PERF_BOOST_COMPONENTS ${PERF_BOOST_COMPONENTS} date_time)
+endif()
+
+if(PERF_BOOST_COMPONENTS)
+ list(REMOVE_DUPLICATES PERF_BOOST_COMPONENTS)
+endif()
+find_package(Boost 1.54 REQUIRED COMPONENTS ${PERF_BOOST_COMPONENTS})
+include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
+
+set(BENCHMARKS
+ accumulate
+ bernoulli_distribution
+ binary_find
+ cart_to_polar
+ comparison_sort
+ copy_if
+ copy_to_device
+ count
+ discrete_distribution
+ erase_remove
+ exclusive_scan
+ fill
+ find
+ find_end
+ includes
+ inner_product
+ is_permutation
+ is_sorted
+ max_element
+ merge
+ next_permutation
+ nth_element
+ partial_sum
+ partition
+ partition_point
+ prev_permutation
+ reverse
+ reverse_copy
+ rotate
+ rotate_copy
+ host_sort
+ random_number_engine
+ reduce_by_key
+ saxpy
+ search
+ search_n
+ set_difference
+ set_intersection
+ set_symmetric_difference
+ set_union
+ sort
+ sort_by_key
+ sort_float
+ stable_partition
+ uniform_int_distribution
+ unique
+ unique_copy
+)
+
+foreach(BENCHMARK ${BENCHMARKS})
+ set(PERF_TARGET perf_${BENCHMARK})
+ add_executable(${PERF_TARGET} perf_${BENCHMARK}.cpp)
+ target_link_libraries(${PERF_TARGET} ${OpenCL_LIBRARIES} ${Boost_LIBRARIES})
+endforeach()
+
+# stl benchmarks (for comparison)
+set(STL_BENCHMARKS
+ stl_accumulate
+ stl_count
+ stl_find
+ stl_find_end
+ stl_includes
+ stl_inner_product
+ stl_max_element
+ stl_merge
+ stl_next_permutation
+ stl_partial_sum
+ stl_partition
+ stl_prev_permutation
+ stl_reverse
+ stl_reverse_copy
+ stl_rotate
+ stl_rotate_copy
+ stl_saxpy
+ stl_search
+ stl_search_n
+ stl_set_difference
+ stl_set_intersection
+ stl_set_symmetric_difference
+ stl_set_union
+ stl_sort
+ stl_stable_partition
+ stl_unique
+ stl_unique_copy
+)
+
+# stl benchmarks which require c++11
+if(${BOOST_COMPUTE_USE_CPP11})
+ list(APPEND
+ STL_BENCHMARKS
+ stl_is_permutation
+ stl_partition_point
+ )
+endif()
+
+foreach(BENCHMARK ${STL_BENCHMARKS})
+ set(PERF_TARGET perf_${BENCHMARK})
+ add_executable(${PERF_TARGET} perf_${BENCHMARK}.cpp)
+ target_link_libraries(${PERF_TARGET} ${Boost_LIBRARIES})
+endforeach()
+
+# cuda/thrust benchmarks (for comparison)
+if(${BOOST_COMPUTE_HAVE_CUDA})
+ find_package(CUDA 5.0 REQUIRED)
+
+ set(CUDA_BENCHMARKS
+ thrust_accumulate
+ thrust_count
+ thrust_exclusive_scan
+ thrust_find
+ thrust_inner_product
+ thrust_merge
+ thrust_partial_sum
+ thrust_partition
+ thrust_reduce_by_key
+ thrust_reverse
+ thrust_reverse_copy
+ thrust_rotate
+ thrust_saxpy
+ thrust_set_difference
+ thrust_sort
+ thrust_unique
+ )
+
+ foreach(BENCHMARK ${CUDA_BENCHMARKS})
+ set(PERF_TARGET perf_${BENCHMARK})
+ cuda_add_executable(${PERF_TARGET} perf_${BENCHMARK}.cu)
+ target_link_libraries(${PERF_TARGET} ${CUDA_LIBRARIES} ${Boost_LIBRARIES})
+ endforeach()
+endif()
+
+# intel tbb benchmarks (for comparison)
+if(${BOOST_COMPUTE_HAVE_TBB})
+ find_package(TBB REQUIRED)
+ include_directories(SYSTEM ${TBB_INCLUDE_DIRS})
+
+ set(TBB_BENCHMARKS
+ tbb_accumulate
+ tbb_merge
+ tbb_sort
+ )
+
+ foreach(BENCHMARK ${TBB_BENCHMARKS})
+ set(PERF_TARGET perf_${BENCHMARK})
+ add_executable(${PERF_TARGET} perf_${BENCHMARK}.cpp)
+ target_link_libraries(${PERF_TARGET} ${TBB_LIBRARIES} ${Boost_LIBRARIES})
+ endforeach()
+endif()
+
+# bolt c++ template lib benchmarks (for comparison)
+if(${BOOST_COMPUTE_HAVE_BOLT} AND ${BOOST_COMPUTE_USE_CPP11})
+ find_package(Bolt REQUIRED)
+ include_directories(SYSTEM ${BOLT_INCLUDE_DIRS})
+
+ set(BOLT_BENCHMARKS
+ bolt_accumulate
+ bolt_count
+ bolt_exclusive_scan
+ bolt_fill
+ bolt_inner_product
+ bolt_max_element
+ bolt_merge
+ bolt_partial_sum
+ bolt_reduce_by_key
+ bolt_saxpy
+ bolt_sort
+ )
+
+ foreach(BENCHMARK ${BOLT_BENCHMARKS})
+ set(PERF_TARGET perf_${BENCHMARK})
+ add_executable(${PERF_TARGET} perf_${BENCHMARK}.cpp)
+ target_link_libraries(${PERF_TARGET} ${OpenCL_LIBRARIES} ${BOLT_LIBRARIES} ${Boost_LIBRARIES})
+ endforeach()
+elseif(${BOOST_COMPUTE_HAVE_BOLT} AND NOT ${BOOST_COMPUTE_USE_CPP11})
+ message(WARNING "BOOST_COMPUTE_USE_CPP11 must be ON for building Bolt C++ Template Library performance tests.")
+endif()
diff --git a/src/boost/libs/compute/perf/perf.hpp b/src/boost/libs/compute/perf/perf.hpp
new file mode 100644
index 00000000..cce0328c
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf.hpp
@@ -0,0 +1,109 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#ifndef PERF_HPP
+#define PERF_HPP
+
+// this header contains general purpose functions and variables used by
+// the boost.compute performance benchmarks.
+
+#include <vector>
+#include <cstdlib>
+#include <algorithm>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/timer/timer.hpp>
+
+static size_t PERF_N = 1024;
+static size_t PERF_TRIALS = 3;
+
+// parses command line arguments and sets the corresponding perf variables
+inline void perf_parse_args(int argc, char *argv[])
+{
+ if(argc >= 2){
+ PERF_N = boost::lexical_cast<size_t>(argv[1]);
+ }
+
+ if(argc >= 3){
+ PERF_TRIALS = boost::lexical_cast<size_t>(argv[2]);
+ }
+}
+
+// generates a vector of random numbers
+template<class T>
+std::vector<T> generate_random_vector(const size_t size)
+{
+ std::vector<T> vector(size);
+ std::generate(vector.begin(), vector.end(), rand);
+ return vector;
+}
+
+// a simple timer wrapper which records multiple time entries
+class perf_timer
+{
+public:
+ typedef boost::timer::nanosecond_type nanosecond_type;
+
+ perf_timer()
+ {
+ timer.stop();
+ }
+
+ void start()
+ {
+ timer.start();
+ }
+
+ void stop()
+ {
+ timer.stop();
+ times.push_back(timer.elapsed().wall);
+ }
+
+ size_t trials() const
+ {
+ return times.size();
+ }
+
+ void clear()
+ {
+ times.clear();
+ }
+
+ nanosecond_type last_time() const
+ {
+ return times.back();
+ }
+
+ nanosecond_type min_time() const
+ {
+ return *std::min_element(times.begin(), times.end());
+ }
+
+ nanosecond_type max_time() const
+ {
+ return *std::max_element(times.begin(), times.end());
+ }
+
+ boost::timer::cpu_timer timer;
+ std::vector<boost::timer::nanosecond_type> times;
+};
+
+// returns the rate (in MB/s) for processing 'count' items of type 'T'
+// in 'time' nanoseconds
+template<class T>
+double perf_rate(const size_t count, perf_timer::nanosecond_type time)
+{
+ const size_t byte_count = count * sizeof(T);
+
+ return (double(byte_count) / 1024 / 1024) / (time / 1e9);
+}
+
+#endif // PERF_HPP
diff --git a/src/boost/libs/compute/perf/perf.py b/src/boost/libs/compute/perf/perf.py
new file mode 100755
index 00000000..c7b33f63
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf.py
@@ -0,0 +1,238 @@
+#!/usr/bin/python
+
+# Copyright (c) 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.
+
+# driver script for boost.compute benchmarking. will run a
+# benchmark for a given function (e.g. accumulate, sort).
+
+import os
+import sys
+import subprocess
+
+try:
+ import pylab
+except:
+ print('pylab not found, no ploting...')
+ pass
+
+def run_perf_process(name, size, backend = ""):
+ if not backend:
+ proc = "perf_%s" % name
+ else:
+ proc = "perf_%s_%s" % (backend, name)
+
+ filename = "./perf/" + proc
+
+ if not os.path.isfile(filename):
+ print("Error: failed to find ", filename, " for running")
+ return 0
+ try:
+ output = subprocess.check_output([filename, str(int(size))])
+ except:
+ return 0
+
+ t = 0
+ for line in output.decode('utf8').split("\n"):
+ if line.startswith("time:"):
+ t = float(line.split(":")[1].split()[0])
+
+ return t
+
+class Report:
+ def __init__(self, name):
+ self.name = name
+ self.samples = {}
+
+ def add_sample(self, name, size, time):
+ if not name in self.samples:
+ self.samples[name] = []
+
+ self.samples[name].append((size, time))
+
+ def display(self):
+ for name in self.samples.keys():
+ print('=== %s with %s ===' % (self.name, name))
+ print('size,time (ms)')
+
+ for sample in self.samples[name]:
+ print('%d,%f' % sample)
+
+ def plot_time(self, name):
+ if not name in self.samples:
+ return
+
+ x = []
+ y = []
+
+ any_valid_samples = False
+
+ for sample in self.samples[name]:
+ if sample[1] == 0:
+ continue
+
+ x.append(sample[0])
+ y.append(sample[1])
+ any_valid_samples = True
+
+ if not any_valid_samples:
+ return
+
+ pylab.loglog(x, y, marker='o', label=name)
+ pylab.xlabel("Size")
+ pylab.ylabel("Time (ms)")
+ pylab.title(self.name)
+
+ def plot_rate(self, name):
+ if not name in self.samples:
+ return
+
+ x = []
+ y = []
+
+ any_valid_samples = False
+
+ for sample in self.samples[name]:
+ if sample[1] == 0:
+ continue
+
+ x.append(sample[0])
+ y.append(float(sample[0]) / (float(sample[1]) * 1e-3))
+ any_valid_samples = True
+
+ if not any_valid_samples:
+ return
+
+ pylab.loglog(x, y, marker='o', label=name)
+ pylab.xlabel("Size")
+ pylab.ylabel("Rate (values/s)")
+ pylab.title(self.name)
+
+def run_benchmark(name, sizes, vs=[]):
+ report = Report(name)
+
+ for size in sizes:
+ time = run_perf_process(name, size)
+
+ report.add_sample("compute", size, time)
+
+ competitors = {
+ "thrust" : [
+ "accumulate",
+ "count",
+ "exclusive_scan",
+ "find",
+ "inner_product",
+ "merge",
+ "partial_sum",
+ "partition",
+ "reduce_by_key",
+ "reverse",
+ "reverse_copy",
+ "rotate",
+ "saxpy",
+ "sort",
+ "unique"
+ ],
+ "bolt" : [
+ "accumulate",
+ "count",
+ "exclusive_scan",
+ "fill",
+ "inner_product",
+ "max_element",
+ "merge",
+ "partial_sum",
+ "reduce_by_key",
+ "saxpy",
+ "sort"
+ ],
+ "tbb": [
+ "accumulate",
+ "merge",
+ "sort"
+ ],
+ "stl": [
+ "accumulate",
+ "count",
+ "find",
+ "find_end",
+ "includes",
+ "inner_product",
+ "is_permutation",
+ "max_element",
+ "merge",
+ "next_permutation",
+ "nth_element",
+ "partial_sum",
+ "partition",
+ "partition_point",
+ "prev_permutation",
+ "reverse",
+ "reverse_copy",
+ "rotate",
+ "rotate_copy",
+ "saxpy",
+ "search",
+ "search_n",
+ "set_difference",
+ "set_intersection",
+ "set_symmetric_difference",
+ "set_union",
+ "sort",
+ "stable_partition",
+ "unique",
+ "unique_copy"
+ ]
+ }
+
+ for other in vs:
+ if not other in competitors:
+ continue
+ if not name in competitors[other]:
+ continue
+
+ for size in sizes:
+ time = run_perf_process(name, size, other)
+ report.add_sample(other, size, time)
+
+ return report
+
+if __name__ == '__main__':
+ test = "sort"
+ if len(sys.argv) >= 2:
+ test = sys.argv[1]
+ print('running %s perf test' % test)
+
+ sizes = [ pow(2, x) for x in range(1, 26) ]
+
+ sizes = sorted(sizes)
+
+ competitors = ["bolt", "tbb", "thrust", "stl"]
+
+ report = run_benchmark(test, sizes, competitors)
+
+ plot = None
+ if "--plot-time" in sys.argv:
+ plot = "time"
+ elif "--plot-rate" in sys.argv:
+ plot = "rate"
+
+ if plot == "time":
+ report.plot_time("compute")
+ for competitor in competitors:
+ report.plot_time(competitor)
+ elif plot == "rate":
+ report.plot_rate("compute")
+ for competitor in competitors:
+ report.plot_rate(competitor)
+
+ if plot:
+ pylab.legend(loc='upper left')
+ pylab.show()
+ else:
+ report.display()
diff --git a/src/boost/libs/compute/perf/perf_accumulate.cpp b/src/boost/libs/compute/perf/perf_accumulate.cpp
new file mode 100644
index 00000000..bd4276e6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_accumulate.cpp
@@ -0,0 +1,140 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/accumulate.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+namespace po = boost::program_options;
+namespace compute = boost::compute;
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+template<class T>
+double perf_accumulate(const compute::vector<T>& data,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ perf_timer t;
+ for(size_t trial = 0; trial < trials; trial++){
+ t.start();
+ compute::accumulate(data.begin(), data.end(), T(0), queue);
+ queue.finish();
+ t.stop();
+ }
+ return t.min_time();
+}
+
+template<class T>
+void tune_accumulate(const compute::vector<T>& data,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ boost::shared_ptr<compute::detail::parameter_cache>
+ params = compute::detail::parameter_cache::get_global_cache(queue.get_device());
+
+ const std::string cache_key =
+ std::string("__boost_reduce_on_gpu_") + compute::type_name<T>();
+
+ const compute::uint_ tpbs[] = { 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
+ const compute::uint_ vpts[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+ double min_time = (std::numeric_limits<double>::max)();
+ compute::uint_ best_tpb = 0;
+ compute::uint_ best_vpt = 0;
+
+ for(size_t i = 0; i < sizeof(tpbs) / sizeof(*tpbs); i++){
+ params->set(cache_key, "tpb", tpbs[i]);
+ for(size_t j = 0; j < sizeof(vpts) / sizeof(*vpts); j++){
+ params->set(cache_key, "vpt", vpts[j]);
+
+ try {
+ const double t = perf_accumulate(data, trials, queue);
+ if(t < min_time){
+ best_tpb = tpbs[i];
+ best_vpt = vpts[j];
+ min_time = t;
+ }
+ }
+ catch(compute::opencl_error&){
+ // invalid parameters for this device, skip
+ }
+ }
+ }
+
+ // store optimal parameters
+ params->set(cache_key, "tpb", best_tpb);
+ params->set(cache_key, "vpt", best_vpt);
+}
+
+int main(int argc, char *argv[])
+{
+ // setup command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("size", po::value<size_t>()->default_value(8192), "input size")
+ ("trials", po::value<size_t>()->default_value(3), "number of trials to run")
+ ("tune", "run tuning procedure")
+ ;
+ po::positional_options_description positional_options;
+ positional_options.add("size", 1);
+
+ // parse command line
+ po::variables_map vm;
+ po::store(
+ po::command_line_parser(argc, argv)
+ .options(options).positional(positional_options).run(),
+ vm
+ );
+ po::notify(vm);
+
+ const size_t size = vm["size"].as<size_t>();
+ const size_t trials = vm["trials"].as<size_t>();
+ std::cout << "size: " << size << std::endl;
+
+ // setup context and queue for the default device
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_data(size);
+ std::generate(host_data.begin(), host_data.end(), rand_int);
+
+ // create vector on the device and copy the data
+ compute::vector<int> device_data(
+ host_data.begin(), host_data.end(), queue
+ );
+
+ // run tuning proceure (if requested)
+ if(vm.count("tune")){
+ tune_accumulate(device_data, trials, queue);
+ }
+
+ // run benchmark
+ double t = perf_accumulate(device_data, trials, queue);
+ std::cout << "time: " << t / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bernoulli_distribution.cpp b/src/boost/libs/compute/perf/perf_bernoulli_distribution.cpp
new file mode 100644
index 00000000..bffbe58f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bernoulli_distribution.cpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/bernoulli_distribution.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ compute::vector<bool> vector(PERF_N, context);
+
+ compute::default_random_engine rng(queue);
+ compute::bernoulli_distribution<float> dist(0.5);
+
+ perf_timer t;
+ t.start();
+ dist.generate(vector.begin(), vector.end(), rng, queue);
+ queue.finish();
+ t.stop();
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_binary_find.cpp b/src/boost/libs/compute/perf/perf_binary_find.cpp
new file mode 100644
index 00000000..ee7c4631
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_binary_find.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/detail/binary_find.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ using boost::compute::_1;
+ boost::compute::partition(
+ device_vector.begin(), device_vector.end(), _1 < 20, queue
+ );
+
+ // just to be sure everything is finished before measuring execution time
+ // of binary_find algorithm
+ queue.finish();
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::detail::binary_find(
+ device_vector.begin(), device_vector.end(), _1 >= 20, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_accumulate.cpp b/src/boost/libs/compute/perf/perf_bolt_accumulate.cpp
new file mode 100644
index 00000000..5a6b9b9c
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_accumulate.cpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+#include <bolt/cl/reduce.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create host vector
+ std::vector<int> host_vec = generate_random_vector<int>(PERF_N);
+
+ // create device vectors
+ bolt::cl::device_vector<int> device_vec(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_vec.begin(), host_vec.end(), device_vec.begin());
+
+ int sum = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ sum = bolt::cl::reduce(device_vec.begin(), device_vec.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "sum: " << sum << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_count.cpp b/src/boost/libs/compute/perf/perf_bolt_count.cpp
new file mode 100644
index 00000000..a23c5ac3
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_count.cpp
@@ -0,0 +1,57 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/count.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> h_vec(PERF_N);
+ std::generate(h_vec.begin(), h_vec.end(), rand_int);
+
+ // create device vector
+ bolt::cl::device_vector<int> d_vec(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(h_vec.begin(), h_vec.end(), d_vec.begin());
+
+ size_t count = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ count = bolt::cl::count(ctrl, d_vec.begin(), d_vec.end(), 4);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "count: " << count << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_exclusive_scan.cpp b/src/boost/libs/compute/perf/perf_bolt_exclusive_scan.cpp
new file mode 100644
index 00000000..a60e4655
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_exclusive_scan.cpp
@@ -0,0 +1,52 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/scan.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // create device vector
+ bolt::cl::device_vector<int> d_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ // transfer data to the device
+ bolt::cl::copy(h_vec.begin(), h_vec.end(), d_vec.begin());
+
+ t.start();
+ bolt::cl::exclusive_scan(d_vec.begin(), d_vec.end(), d_vec.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ bolt::cl::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_fill.cpp b/src/boost/libs/compute/perf/perf_bolt_fill.cpp
new file mode 100644
index 00000000..50b6e85e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_fill.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/fill.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create device vector (filled with zeros)
+ bolt::cl::device_vector<int> d_vec(PERF_N, 0);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ bolt::cl::fill(d_vec.begin(), d_vec.end(), int(trial));
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_inner_product.cpp b/src/boost/libs/compute/perf/perf_bolt_inner_product.cpp
new file mode 100644
index 00000000..4c9652e6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_inner_product.cpp
@@ -0,0 +1,56 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/inner_product.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create host vectors
+ std::vector<int> host_x = generate_random_vector<int>(PERF_N);
+ std::vector<int> host_y = generate_random_vector<int>(PERF_N);
+
+ // create device vectors
+ bolt::cl::device_vector<int> device_x(PERF_N);
+ bolt::cl::device_vector<int> device_y(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_x.begin(), host_x.end(), device_x.begin());
+ bolt::cl::copy(host_y.begin(), host_y.end(), device_y.begin());
+
+ int product = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ product = bolt::cl::inner_product(
+ device_x.begin(), device_x.end(), device_y.begin(), 0
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "product: " << product << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_max_element.cpp b/src/boost/libs/compute/perf/perf_bolt_max_element.cpp
new file mode 100644
index 00000000..238b1ba2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_max_element.cpp
@@ -0,0 +1,69 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+#include <bolt/cl/max_element.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>(rand() % 10000000);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create host vector
+ std::vector<int> host_vec = generate_random_vector<int>(PERF_N);
+
+ // create device vectors
+ bolt::cl::device_vector<int> device_vec(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_vec.begin(), host_vec.end(), device_vec.begin());
+
+ bolt::cl::device_vector<int>::iterator max_iter = device_vec.begin();
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ max_iter = bolt::cl::max_element(device_vec.begin(), device_vec.end());
+ t.stop();
+ }
+
+ int device_max = *max_iter;
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "max: " << device_max << std::endl;
+
+ // verify max is correct
+ int host_max = *std::max_element(host_vec.begin(), host_vec.end());
+ if(device_max != host_max){
+ std::cout << "ERROR: "
+ << "device_max (" << device_max << ") "
+ << "!= "
+ << "host_max (" << host_max << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_merge.cpp b/src/boost/libs/compute/perf/perf_bolt_merge.cpp
new file mode 100644
index 00000000..c5ee12ac
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_merge.cpp
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/merge.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vec1 = generate_random_vector<int>(std::floor(PERF_N / 2.0));
+ std::vector<int> host_vec2 = generate_random_vector<int>(std::ceil(PERF_N / 2.0));
+ // sort them
+ std::sort(host_vec1.begin(), host_vec1.end());
+ std::sort(host_vec2.begin(), host_vec2.end());
+
+ // create device vectors
+ bolt::cl::device_vector<int> device_vec1(PERF_N);
+ bolt::cl::device_vector<int> device_vec2(PERF_N);
+ bolt::cl::device_vector<int> device_vec3(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_vec1.begin(), host_vec1.end(), device_vec1.begin());
+ bolt::cl::copy(host_vec2.begin(), host_vec2.end(), device_vec2.begin());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ bolt::cl::merge(
+ device_vec1.begin(), device_vec1.end(),
+ device_vec2.begin(), device_vec2.end(),
+ device_vec3.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_partial_sum.cpp b/src/boost/libs/compute/perf/perf_bolt_partial_sum.cpp
new file mode 100644
index 00000000..2f9c830e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_partial_sum.cpp
@@ -0,0 +1,53 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/scan.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // create device vector
+ bolt::cl::device_vector<int> d_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ // transfer data to the device
+ bolt::cl::copy(h_vec.begin(), h_vec.end(), d_vec.begin());
+
+ t.start();
+ bolt::cl::inclusive_scan(d_vec.begin(), d_vec.end(), d_vec.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ bolt::cl::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
+
diff --git a/src/boost/libs/compute/perf/perf_bolt_reduce_by_key.cpp b/src/boost/libs/compute/perf/perf_bolt_reduce_by_key.cpp
new file mode 100644
index 00000000..e7668498
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_reduce_by_key.cpp
@@ -0,0 +1,100 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+#include <bolt/cl/reduce_by_key.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+struct unique_key {
+ int current;
+ int avgValuesNoPerKey;
+
+ unique_key()
+ {
+ current = 0;
+ avgValuesNoPerKey = 512;
+ }
+
+ int operator()()
+ {
+ double p = double(1.0) / static_cast<double>(avgValuesNoPerKey);
+ if((rand() / double(RAND_MAX)) <= p)
+ return ++current;
+ return current;
+ }
+} UniqueKey;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create vector of keys and random values
+ std::vector<int> host_keys(PERF_N);
+ std::vector<int> host_values(PERF_N);
+ std::generate(host_keys.begin(), host_keys.end(), UniqueKey);
+ std::generate(host_values.begin(), host_values.end(), rand_int);
+
+ // create device vectors for data
+ bolt::cl::device_vector<int> device_keys(PERF_N);
+ bolt::cl::device_vector<int> device_values(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_keys.begin(), host_keys.end(), device_keys.begin());
+ bolt::cl::copy(host_values.begin(), host_values.end(), device_values.begin());
+
+ // create device vectors for the results
+ bolt::cl::device_vector<int> device_keys_results(PERF_N);
+ bolt::cl::device_vector<int> device_values_results(PERF_N);
+
+ typedef bolt::cl::device_vector<int>::iterator iterType;
+ bolt::cl::pair<iterType, iterType> result = {
+ device_keys_results.begin(),
+ device_values_results.begin()
+ };
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ result = bolt::cl::reduce_by_key(device_keys.begin(),
+ device_keys.end(),
+ device_values.begin(),
+ device_keys_results.begin(),
+ device_values_results.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ size_t result_size = bolt::cl::distance(device_keys_results.begin(), result.first);
+ if(result_size != static_cast<size_t>(host_keys[PERF_N-1] + 1)){
+ std::cout << "ERROR: "
+ << "wrong number of keys"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_saxpy.cpp b/src/boost/libs/compute/perf/perf_bolt_saxpy.cpp
new file mode 100644
index 00000000..201f683a
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_saxpy.cpp
@@ -0,0 +1,76 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+#include <bolt/cl/transform.h>
+
+#include "perf.hpp"
+
+BOLT_FUNCTOR(saxpy_functor,
+ struct saxpy_functor
+ {
+ float _a;
+ saxpy_functor(float a) : _a(a) {};
+
+ float operator() (const float &x, const float &y) const
+ {
+ return _a * x + y;
+ };
+ };
+)
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ bolt::cl::control ctrl = bolt::cl::control::getDefault();
+ ::cl::Device device = ctrl.getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create host vectors
+ std::vector<float> host_x(PERF_N);
+ std::vector<float> host_y(PERF_N);
+ std::generate(host_x.begin(), host_x.end(), rand);
+ std::generate(host_y.begin(), host_y.end(), rand);
+
+ // create device vectors
+ bolt::cl::device_vector<float> device_x(PERF_N);
+ bolt::cl::device_vector<float> device_y(PERF_N);
+
+ // transfer data to the device
+ bolt::cl::copy(host_x.begin(), host_x.end(), device_x.begin());
+ bolt::cl::copy(host_y.begin(), host_y.end(), device_y.begin());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ bolt::cl::transform(
+ device_x.begin(), device_x.end(),
+ device_y.begin(),
+ device_y.begin(),
+ saxpy_functor(2.5f)
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ bolt::cl::copy(device_x.begin(), device_x.end(), host_x.begin());
+ bolt::cl::copy(device_y.begin(), device_y.end(), host_y.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_bolt_sort.cpp b/src/boost/libs/compute/perf/perf_bolt_sort.cpp
new file mode 100644
index 00000000..2508ec06
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_bolt_sort.cpp
@@ -0,0 +1,50 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <cstdlib>
+#include <vector>
+
+#include <bolt/cl/sort.h>
+#include <bolt/cl/copy.h>
+#include <bolt/cl/device_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ ::cl::Device device = bolt::cl::control::getDefault().getDevice();
+ std::cout << "device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
+
+ // create host vector
+ std::vector<int> h_vec = generate_random_vector<int>(PERF_N);
+ // create device vector
+ bolt::cl::device_vector<int> d_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ // transfer data to the device
+ bolt::cl::copy(h_vec.begin(), h_vec.end(), d_vec.begin());
+
+ t.start();
+ bolt::cl::sort(d_vec.begin(), d_vec.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ bolt::cl::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_cart_to_polar.cpp b/src/boost/libs/compute/perf/perf_cart_to_polar.cpp
new file mode 100644
index 00000000..e0d333eb
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_cart_to_polar.cpp
@@ -0,0 +1,158 @@
+//---------------------------------------------------------------------------//
+// 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 _USE_MATH_DEFINES
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/copy_n.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+
+using compute::float2_;
+
+float rand_float()
+{
+ return (float(rand()) / float(RAND_MAX)) * 1000.f;
+}
+
+void serial_cartesian_to_polar(const float *input, size_t n, float *output)
+{
+ for(size_t i = 0; i < n; i++){
+ float x = input[i*2+0];
+ float y = input[i*2+1];
+
+ float magnitude = std::sqrt(x*x + y*y);
+ float angle = std::atan2(y, x) * 180.f / M_PI;
+
+ output[i*2+0] = magnitude;
+ output[i*2+1] = angle;
+ }
+}
+
+void serial_polar_to_cartesian(const float *input, size_t n, float *output)
+{
+ for(size_t i = 0; i < n; i++){
+ float magnitude = input[i*2+0];
+ float angle = input[i*2+1];
+
+ float x = magnitude * cos(angle);
+ float y = magnitude * sin(angle);
+
+ output[i*2+0] = x;
+ output[i*2+1] = y;
+ }
+}
+
+// converts from cartesian coordinates (x, y) to polar coordinates (magnitude, angle)
+BOOST_COMPUTE_FUNCTION(float2_, cartesian_to_polar, (float2_ p),
+{
+ float x = p.x;
+ float y = p.y;
+
+ float magnitude = sqrt(x*x + y*y);
+ float angle = atan2(y, x) * 180.f / M_PI;
+
+ return (float2)(magnitude, angle);
+});
+
+// converts from polar coordinates (magnitude, angle) to cartesian coordinates (x, y)
+BOOST_COMPUTE_FUNCTION(float2_, polar_to_cartesian, (float2_ p),
+{
+ float magnitude = p.x;
+ float angle = p.y;
+
+ float x = magnitude * cos(angle);
+ float y = magnitude * sin(angle);
+
+ return (float2)(x, y)
+});
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<float> host_vector(PERF_N*2);
+ std::generate(host_vector.begin(), host_vector.end(), rand_float);
+
+ // create vector on the device and copy the data
+ compute::vector<float2_> device_vector(PERF_N, context);
+ compute::copy_n(
+ reinterpret_cast<float2_ *>(&host_vector[0]),
+ PERF_N,
+ device_vector.begin(),
+ queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ compute::transform(
+ device_vector.begin(),
+ device_vector.end(),
+ device_vector.begin(),
+ cartesian_to_polar,
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // perform saxpy on host
+ t.clear();
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ serial_cartesian_to_polar(&host_vector[0], PERF_N, &host_vector[0]);
+ t.stop();
+ }
+ std::cout << "host time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ std::vector<float> device_data(PERF_N*2);
+ compute::copy(
+ device_vector.begin(),
+ device_vector.end(),
+ reinterpret_cast<float2_ *>(&device_data[0]),
+ queue
+ );
+
+ for(size_t i = 0; i < PERF_N; i++){
+ float host_value = host_vector[i];
+ float device_value = device_data[i];
+
+ if(std::abs(device_value - host_value) > 1e-3){
+ std::cout << "ERROR: "
+ << "value at " << i << " "
+ << "device_value (" << device_value << ") "
+ << "!= "
+ << "host_value (" << host_value << ")"
+ << std::endl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_comparison_sort.cpp b/src/boost/libs/compute/perf/perf_comparison_sort.cpp
new file mode 100644
index 00000000..fa63303f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_comparison_sort.cpp
@@ -0,0 +1,86 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/program_options.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 "perf.hpp"
+
+namespace po = boost::program_options;
+namespace compute = boost::compute;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ using boost::compute::int_;
+
+ // create vector of random numbers on the host
+ std::vector<int_> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int_> device_vector(PERF_N, context);
+
+ // less function for float
+ BOOST_COMPUTE_FUNCTION(bool, comp, (int_ a, int_ b),
+ {
+ return a < b;
+ });
+
+ // sort vector
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+ queue.finish();
+
+ t.start();
+ boost::compute::sort(
+ device_vector.begin(),
+ device_vector.end(),
+ comp,
+ queue
+ );
+ queue.finish();
+ t.stop();
+ };
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify vector is sorted
+ if(!boost::compute::is_sorted(device_vector.begin(),
+ device_vector.end(),
+ comp,
+ queue)){
+ std::cout << "ERROR: is_sorted() returned false" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_copy_if.cpp b/src/boost/libs/compute/perf/perf_copy_if.cpp
new file mode 100644
index 00000000..b2c162f6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_copy_if.cpp
@@ -0,0 +1,122 @@
+//---------------------------------------------------------------------------//
+// 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/core.hpp>
+#include <boost/compute/closure.hpp>
+#include <boost/compute/algorithm/copy_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/random/uniform_real_distribution.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+
+void test_copy_if_odd(compute::command_queue &queue)
+{
+ // create input and output vectors on the device
+ const compute::context &context = queue.get_context();
+ compute::vector<int> input(PERF_N, context);
+ compute::vector<int> output(PERF_N, 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_COMPUTE_FUNCTION(bool, is_odd, (int x),
+ {
+ return x & 1;
+ });
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ compute::vector<int>::iterator i = compute::copy_if(
+ input.begin(), input.end(), output.begin(), is_odd, queue
+ );
+ queue.finish();
+ t.stop();
+
+ float ratio = float(std::distance(output.begin(), i)) / PERF_N;
+ if(PERF_N > 1000 && (ratio < 0.45f || ratio > 0.55f)){
+ std::cerr << "error: ratio is " << ratio << std::endl;
+ std::cerr << "error: ratio should be around 45-55%" << std::endl;
+ }
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+}
+
+void test_copy_if_in_sphere(compute::command_queue &queue)
+{
+ using boost::compute::float4_;
+
+ // create input and output vectors on the device
+ const compute::context &context = queue.get_context();
+ compute::vector<float4_> input_points(PERF_N, context);
+ compute::vector<float4_> output_points(PERF_N, context);
+
+ // generate random numbers in a cube
+ float radius = 5.0f;
+ compute::default_random_engine rng(queue);
+ compute::uniform_real_distribution<float> d(-radius, +radius);
+ d.generate(
+ compute::make_buffer_iterator<float>(input_points.get_buffer(), 0),
+ compute::make_buffer_iterator<float>(input_points.get_buffer(), PERF_N * 4),
+ rng,
+ queue
+ );
+
+ // predicate which returns true if the point lies within the sphere
+ BOOST_COMPUTE_CLOSURE(bool, is_in_sphere, (float4_ point), (radius),
+ {
+ // ignore fourth component
+ point.w = 0;
+
+ return length(point) < radius;
+ });
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ compute::vector<float4_>::iterator i = compute::copy_if(
+ input_points.begin(),
+ input_points.end(),
+ output_points.begin(),
+ is_in_sphere,
+ queue
+ );
+ queue.finish();
+ t.stop();
+
+ float ratio = float(std::distance(output_points.begin(), i)) / PERF_N;
+ if(PERF_N > 1000 && (ratio < 0.5f || ratio > 0.6f)){
+ std::cerr << "error: ratio is " << ratio << std::endl;
+ std::cerr << "error: ratio should be around 50-60%" << std::endl;
+ }
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ test_copy_if_odd(queue);
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_copy_to_device.cpp b/src/boost/libs/compute/perf/perf_copy_to_device.cpp
new file mode 100644
index 00000000..0cda3d0f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_copy_to_device.cpp
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------//
+// 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 <vector>
+#include <cstdlib>
+#include <iostream>
+
+#include <boost/compute.hpp>
+
+int main(int argc, char *argv[])
+{
+ size_t size = 1000;
+ if(argc >= 2){
+ size = boost::lexical_cast<size_t>(argv[1]);
+ }
+
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+
+ boost::compute::command_queue::properties
+ properties = boost::compute::command_queue::enable_profiling;
+ boost::compute::command_queue queue(context, device, properties);
+
+ std::vector<int> host_vector(size);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ boost::compute::vector<int> device_vector(host_vector.size(), context);
+
+ boost::compute::future<void> future =
+ boost::compute::copy_async(host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue);
+
+ // wait for copy to finish
+ future.wait();
+
+ // get elapsed time in nanoseconds
+ size_t elapsed =
+ future.get_event().duration<boost::chrono::nanoseconds>().count();
+
+ std::cout << "time: " << elapsed / 1e6 << " ms" << std::endl;
+
+ float rate = (float(size * sizeof(int)) / elapsed) * 1000.f;
+ std::cout << "rate: " << rate << " MB/s" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_count.cpp b/src/boost/libs/compute/perf/perf_count.cpp
new file mode 100644
index 00000000..a47eb615
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_count.cpp
@@ -0,0 +1,77 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/count.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ size_t count = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ count = boost::compute::count(
+ device_vector.begin(), device_vector.end(), 4, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "count: " << count << std::endl;
+
+ // verify count is correct
+ size_t host_count = std::count(host_vector.begin(),
+ host_vector.end(),
+ 4);
+ if(count != host_count){
+ std::cout << "ERROR: "
+ << "device_count (" << count << ") "
+ << "!= "
+ << "host_count (" << host_count << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_discrete_distribution.cpp b/src/boost/libs/compute/perf/perf_discrete_distribution.cpp
new file mode 100644
index 00000000..f6679eb1
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_discrete_distribution.cpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/discrete_distribution.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ compute::vector<compute::uint_> vector(PERF_N, context);
+
+ int weights[] = {1, 1};
+
+ compute::default_random_engine rng(queue);
+ compute::discrete_distribution<compute::uint_> dist(weights, weights+2);
+
+ perf_timer t;
+ t.start();
+ dist.generate(vector.begin(), vector.end(), rng, queue);
+ queue.finish();
+ t.stop();
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_erase_remove.cpp b/src/boost/libs/compute/perf/perf_erase_remove.cpp
new file mode 100644
index 00000000..f567247f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_erase_remove.cpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/remove.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 10.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::vector<int> device_vector(
+ host_vector.begin(), host_vector.end(), queue
+ );
+
+ t.start();
+ device_vector.erase(
+ boost::compute::remove(
+ device_vector.begin(), device_vector.end(), 4, queue
+ ),
+ device_vector.end(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_exclusive_scan.cpp b/src/boost/libs/compute/perf/perf_exclusive_scan.cpp
new file mode 100644
index 00000000..e6c65135
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_exclusive_scan.cpp
@@ -0,0 +1,97 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Benoit
+//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/exclusive_scan.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::vector<int> device_res(PERF_N,context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ // sum vector
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ t.start();
+ boost::compute::exclusive_scan(
+ device_vector.begin(),
+ device_vector.end(),
+ device_res.begin(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify sum is correct
+ std::partial_sum(
+ host_vector.begin(),
+ host_vector.end(),
+ host_vector.begin()
+ );
+
+ int device_sum = device_res.back();
+ // when scan is exclusive values are shifted by one on the left
+ // compared to a inclusive scan
+ int host_sum = host_vector[host_vector.size()-2];
+
+ if(device_sum != host_sum){
+ std::cout << "ERROR: "
+ << "device_sum (" << device_sum << ") "
+ << "!= "
+ << "host_sum (" << host_sum << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_fill.cpp b/src/boost/libs/compute/perf/perf_fill.cpp
new file mode 100644
index 00000000..9f35b6b0
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_fill.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector on the device (filled with zeros)
+ boost::compute::vector<int> vec(PERF_N, 0, queue);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::fill(vec.begin(), vec.end(), int(trial), queue);
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_find.cpp b/src/boost/libs/compute/perf/perf_find.cpp
new file mode 100644
index 00000000..3cfb75ad
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_find.cpp
@@ -0,0 +1,88 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/find.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+// Max integer that can be generated by rand_int() function.
+int rand_int_max = 25;
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * rand_int_max);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ // trying to find element that isn't in vector (worst-case scenario)
+ int wanted = rand_int_max + 1;
+
+ // device iterator
+ boost::compute::vector<int>::iterator device_result_it;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ device_result_it = boost::compute::find(device_vector.begin(),
+ device_vector.end(),
+ wanted,
+ queue);
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify if found index is correct by comparing it with std::find() result
+ size_t host_result_index = std::distance(host_vector.begin(),
+ std::find(host_vector.begin(),
+ host_vector.end(),
+ wanted));
+ size_t device_result_index = device_result_it.get_index();
+
+ if(device_result_index != host_result_index){
+ std::cout << "ERROR: "
+ << "device_result_index (" << device_result_index << ") "
+ << "!= "
+ << "host_result_index (" << host_result_index << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_find_end.cpp b/src/boost/libs/compute/perf/perf_find_end.cpp
new file mode 100644
index 00000000..e20a7e8d
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_find_end.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/find_end.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int pattern[] = {2, 6, 6, 7, 8, 4};
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ boost::compute::vector<int> pattern_vector(pattern, pattern + 6, queue);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::find_end(
+ device_vector.begin(), device_vector.end(),
+ pattern_vector.begin(), pattern_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_host_sort.cpp b/src/boost/libs/compute/perf/perf_host_sort.cpp
new file mode 100644
index 00000000..d34b1c52
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_host_sort.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/timer/timer.hpp>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> random_vector(PERF_N);
+ std::generate(random_vector.begin(), random_vector.end(), rand);
+
+ // create input vector for gpu
+ std::vector<int> gpu_vector = random_vector;
+
+ // sort vector on gpu
+ boost::timer::cpu_timer t;
+ boost::compute::sort(
+ gpu_vector.begin(), gpu_vector.end(), queue
+ );
+ queue.finish();
+ std::cout << "time: " << t.elapsed().wall / 1e6 << " ms" << std::endl;
+
+ // create input vector for host
+ std::vector<int> host_vector = random_vector;
+
+ // sort vector on host
+ t.start();
+ std::sort(host_vector.begin(), host_vector.end());
+ std::cout << "host time: " << t.elapsed().wall / 1e6 << " ms" << std::endl;
+
+ // ensure that both sorted vectors are equal
+ if(!std::equal(gpu_vector.begin(), gpu_vector.end(), host_vector.begin())){
+ std::cerr << "ERROR: sorted vectors not the same" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_includes.cpp b/src/boost/libs/compute/perf/perf_includes.cpp
new file mode 100644
index 00000000..0418a5d7
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_includes.cpp
@@ -0,0 +1,68 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/includes.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vectors of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::sort(host_vector.begin(), host_vector.end());
+
+ // create vectors on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ boost::compute::vector<int> device_vector2(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector2.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::includes(
+ device_vector.begin(), device_vector.end(),
+ device_vector2.begin(), device_vector2.end(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_inner_product.cpp b/src/boost/libs/compute/perf/perf_inner_product.cpp
new file mode 100644
index 00000000..112a4bc6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_inner_product.cpp
@@ -0,0 +1,74 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/inner_product.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ std::vector<int> h1(PERF_N);
+ std::vector<int> h2(PERF_N);
+ std::generate(h1.begin(), h1.end(), rand_int);
+ std::generate(h2.begin(), h2.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> d1(PERF_N, context);
+ boost::compute::vector<int> d2(PERF_N, context);
+ boost::compute::copy(h1.begin(), h1.end(), d1.begin(), queue);
+ boost::compute::copy(h2.begin(), h2.end(), d2.begin(), queue);
+
+ int product = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ product = boost::compute::inner_product(
+ d1.begin(), d1.end(), d2.begin(), int(0), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify product is correct
+ int host_product = std::inner_product(
+ h1.begin(), h1.end(), h2.begin(), int(0)
+ );
+ if(product != host_product){
+ std::cout << "ERROR: "
+ << "device_product (" << product << ") "
+ << "!= "
+ << "host_product (" << host_product << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_is_permutation.cpp b/src/boost/libs/compute/perf/perf_is_permutation.cpp
new file mode 100644
index 00000000..39c72bf1
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_is_permutation.cpp
@@ -0,0 +1,66 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ boost::compute::vector<int> device_vector2(PERF_N, context);
+ boost::compute::copy(
+ host_vector.rbegin(), host_vector.rend(), device_vector2.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::is_permutation(
+ device_vector.begin(), device_vector.end(),
+ device_vector2.begin(), device_vector2.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_is_sorted.cpp b/src/boost/libs/compute/perf/perf_is_sorted.cpp
new file mode 100644
index 00000000..f16a3172
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_is_sorted.cpp
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // sort and then reverse the random vector
+ boost::compute::sort(device_vector.begin(), device_vector.end(), queue);
+ boost::compute::reverse(device_vector.begin(), device_vector.end(), queue);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ bool sorted = boost::compute::is_sorted(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ if(sorted){
+ std::cerr << "ERROR: is_sorted() returned true" << std::endl;
+ }
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_max_element.cpp b/src/boost/libs/compute/perf/perf_max_element.cpp
new file mode 100644
index 00000000..0e47c67e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_max_element.cpp
@@ -0,0 +1,93 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Rastko Anicic <anicic.rastko@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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/max_element.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>(rand() % 10000000);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ boost::compute::vector<int>::iterator device_max_iter
+ = device_vector.begin();
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ device_max_iter = boost::compute::max_element(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+
+ int device_max = device_max_iter.read(queue);
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "max: " << device_max << std::endl;
+
+ // verify max is correct
+ std::vector<int>::iterator host_max_iter
+ = std::max_element(host_vector.begin(), host_vector.end());
+
+ int host_max = *host_max_iter;
+ if(device_max != host_max){
+ std::cout << "ERROR: "
+ << "device_max (" << device_max << ") "
+ << "!= "
+ << "host_max (" << host_max << ")"
+ << std::endl;
+ return -1;
+ }
+
+ size_t host_max_idx = std::distance(host_vector.begin(), host_max_iter);
+ size_t device_max_idx = std::distance(device_vector.begin(), device_max_iter);
+ if(device_max_idx != host_max_idx){
+ std::cout << "ERROR: "
+ << "device_max index (" << device_max_idx << ") "
+ << "!= "
+ << "host_max index (" << host_max_idx << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_merge.cpp b/src/boost/libs/compute/perf/perf_merge.cpp
new file mode 100644
index 00000000..58ea836f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_merge.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.
+//---------------------------------------------------------------------------//
+
+#include <cmath>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/merge.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ std::vector<int> v1 = generate_random_vector<int>(std::floor(PERF_N / 2.0));
+ std::vector<int> v2 = generate_random_vector<int>(std::ceil(PERF_N / 2.0));
+ std::vector<int> v3(PERF_N);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ boost::compute::vector<int> gpu_v1(v1.begin(), v1.end(), queue);
+ boost::compute::vector<int> gpu_v2(v2.begin(), v2.end(), queue);
+ boost::compute::vector<int> gpu_v3(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::merge(gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ std::vector<int> check_v3(PERF_N);
+ boost::compute::copy(gpu_v3.begin(), gpu_v3.end(), check_v3.begin(), queue);
+ queue.finish();
+
+ std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
+ bool ok = std::equal(check_v3.begin(), check_v3.end(), v3.begin());
+ if(!ok){
+ std::cerr << "ERROR: merged ranges different" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_next_permutation.cpp b/src/boost/libs/compute/perf/perf_next_permutation.cpp
new file mode 100644
index 00000000..62f0bbb0
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_next_permutation.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/next_permutation.hpp>
+#include <boost/compute/algorithm/prev_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::sort(host_vector.begin(), host_vector.end(), std::greater<int>());
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::next_permutation(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ boost::compute::prev_permutation(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_nth_element.cpp b/src/boost/libs/compute/perf/perf_nth_element.cpp
new file mode 100644
index 00000000..07627cb4
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_nth_element.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/nth_element.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::nth_element(
+ device_vector.begin(), device_vector.begin()+(PERF_N/2), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_partial_sum.cpp b/src/boost/libs/compute/perf/perf_partial_sum.cpp
new file mode 100644
index 00000000..1c02b4c4
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_partial_sum.cpp
@@ -0,0 +1,97 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/partial_sum.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ using boost::compute::int_;
+
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int_> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int_> device_vector(PERF_N, context);
+ boost::compute::vector<int_> device_res(PERF_N,context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ // sum vector
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ t.start();
+ boost::compute::partial_sum(
+ device_vector.begin(),
+ device_vector.end(),
+ device_res.begin(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify sum is correct
+ std::partial_sum(
+ host_vector.begin(),
+ host_vector.end(),
+ host_vector.begin()
+ );
+
+ int device_sum = device_res.back();
+ int host_sum = host_vector.back();
+
+ if(device_sum != host_sum){
+ std::cout << "ERROR: "
+ << "device_sum (" << device_sum << ") "
+ << "!= "
+ << "host_sum (" << host_sum << ")"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_partition.cpp b/src/boost/libs/compute/perf/perf_partition.cpp
new file mode 100644
index 00000000..b765d736
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_partition.cpp
@@ -0,0 +1,66 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ using boost::compute::_1;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ t.start();
+ boost::compute::partition(
+ device_vector.begin(), device_vector.end(), _1 < 10, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_partition_point.cpp b/src/boost/libs/compute/perf/perf_partition_point.cpp
new file mode 100644
index 00000000..91261aa1
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_partition_point.cpp
@@ -0,0 +1,68 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/algorithm/partition.hpp>
+#include <boost/compute/algorithm/partition_point.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ using boost::compute::_1;
+ boost::compute::partition(
+ device_vector.begin(), device_vector.end(), _1 < 20, queue
+ );
+
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::partition_point(
+ device_vector.begin(), device_vector.end(), _1 < 20, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_prev_permutation.cpp b/src/boost/libs/compute/perf/perf_prev_permutation.cpp
new file mode 100644
index 00000000..bb7d76d2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_prev_permutation.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/next_permutation.hpp>
+#include <boost/compute/algorithm/prev_permutation.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::sort(host_vector.begin(), host_vector.end());
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::prev_permutation(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ boost::compute::next_permutation(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_random_number_engine.cpp b/src/boost/libs/compute/perf/perf_random_number_engine.cpp
new file mode 100644
index 00000000..db25d437
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_random_number_engine.cpp
@@ -0,0 +1,101 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/core.hpp>
+#include <boost/compute/random.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+namespace po = boost::program_options;
+
+template<class Engine>
+void perf_random_number_engine(const size_t size,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ typedef typename Engine::result_type T;
+
+ // create random number engine
+ Engine engine(queue);
+
+ // create vector on the device
+ std::cout << "size = " << size << std::endl;
+ compute::vector<T> vector(size, queue.get_context());
+
+ // generate random numbers
+ perf_timer t;
+ for(size_t i = 0; i < trials; i++){
+ t.start();
+ engine.generate(vector.begin(), vector.end(), queue);
+ queue.finish();
+ t.stop();
+ }
+
+ // print result
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "rate: " << perf_rate<T>(size, t.min_time()) << " MB/s" << std::endl;
+}
+
+int main(int argc, char *argv[])
+{
+ // setup and parse command line options
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("size", po::value<size_t>()->default_value(8192), "number of values")
+ ("trials", po::value<size_t>()->default_value(3), "number of trials")
+ ("engine", po::value<std::string>()->default_value("default_random_engine"), "random number engine")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, options), vm);
+ po::notify(vm);
+
+ if(vm.count("help")) {
+ std::cout << options << std::endl;
+ return 0;
+ }
+
+ // setup context and queue for the default device
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ // get command line options
+ const size_t size = vm["size"].as<size_t>();
+ const size_t trials = vm["trials"].as<size_t>();
+ const std::string& engine = vm["engine"].as<std::string>();
+
+ // run benchmark
+ if(engine == "default_random_engine"){
+ perf_random_number_engine<compute::default_random_engine>(size, trials, queue);
+ }
+ else if(engine == "mersenne_twister_engine"){
+ perf_random_number_engine<compute::mt19937>(size, trials, queue);
+ }
+ else if(engine == "linear_congruential_engine"){
+ perf_random_number_engine<compute::linear_congruential_engine<> >(size, trials, queue);
+ }
+ else if(engine == "threefry_engine"){
+ perf_random_number_engine<compute::threefry_engine<> >(size, trials, queue);
+ }
+ else {
+ std::cerr << "error: unknown random number engine '" << engine << "'" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_reduce_by_key.cpp b/src/boost/libs/compute/perf/perf_reduce_by_key.cpp
new file mode 100644
index 00000000..c88d450e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_reduce_by_key.cpp
@@ -0,0 +1,114 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/fill.hpp>
+#include <boost/compute/algorithm/reduce_by_key.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+struct unique_key {
+ int current;
+ int avgValuesNoPerKey;
+
+ unique_key()
+ {
+ current = 0;
+ avgValuesNoPerKey = 512;
+ }
+
+ int operator()()
+ {
+ double p = double(1.0) / static_cast<double>(avgValuesNoPerKey);
+ if((rand() / double(RAND_MAX)) <= p)
+ return ++current;
+ return current;
+ }
+} UniqueKey;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of keys and random values
+ std::vector<int> host_keys(PERF_N);
+ std::vector<int> host_values(PERF_N);
+ std::generate(host_keys.begin(), host_keys.end(), UniqueKey);
+ std::generate(host_values.begin(), host_values.end(), rand_int);
+
+ // create vectors for keys and values on the device and copy the data
+ boost::compute::vector<int> device_keys(PERF_N, context);
+ boost::compute::vector<int> device_values(PERF_N,context);
+ boost::compute::copy(
+ host_keys.begin(),
+ host_keys.end(),
+ device_keys.begin(),
+ queue
+ );
+ boost::compute::copy(
+ host_values.begin(),
+ host_values.end(),
+ device_values.begin(),
+ queue
+ );
+
+ // vectors for the results
+ boost::compute::vector<int> device_keys_results(PERF_N, context);
+ boost::compute::vector<int> device_values_results(PERF_N,context);
+
+ typedef boost::compute::vector<int>::iterator iterType;
+ std::pair<iterType, iterType> result(
+ device_keys_results.begin(),
+ device_values_results.begin()
+ );
+
+ // reduce by key
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ result = boost::compute::reduce_by_key(device_keys.begin(),
+ device_keys.end(),
+ device_values.begin(),
+ device_keys_results.begin(),
+ device_values_results.begin(),
+ queue);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ size_t result_size = std::distance(device_keys_results.begin(), result.first);
+ if(result_size != static_cast<size_t>(host_keys[PERF_N-1] + 1)){
+ std::cout << "ERROR: "
+ << "wrong number of keys" << result_size << "\n" << (host_keys[PERF_N-1] + 1)
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_reverse.cpp b/src/boost/libs/compute/perf/perf_reverse.cpp
new file mode 100644
index 00000000..64369a78
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_reverse.cpp
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/reverse.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::reverse(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_reverse_copy.cpp b/src/boost/libs/compute/perf/perf_reverse_copy.cpp
new file mode 100644
index 00000000..5ce01c9b
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_reverse_copy.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/reverse_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ // create vector on the device for reversed data
+ boost::compute::vector<int> device_reversed_vector(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::reverse_copy(
+ device_vector.begin(), device_vector.end(),
+ device_reversed_vector.begin(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_rotate.cpp b/src/boost/libs/compute/perf/perf_rotate.cpp
new file mode 100644
index 00000000..49f85d57
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_rotate.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/rotate.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::rotate(
+ device_vector.begin(), device_vector.begin()+(PERF_N/2), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_rotate_copy.cpp b/src/boost/libs/compute/perf/perf_rotate_copy.cpp
new file mode 100644
index 00000000..97111ef5
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_rotate_copy.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/rotate_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ boost::compute::vector<int> device_vector2(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::rotate_copy(
+ device_vector.begin(), device_vector.begin()+(PERF_N/2), device_vector.end(), device_vector2.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_saxpy.cpp b/src/boost/libs/compute/perf/perf_saxpy.cpp
new file mode 100644
index 00000000..99ffc55d
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_saxpy.cpp
@@ -0,0 +1,162 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/program_options.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/copy.hpp>
+#include <boost/compute/algorithm/transform.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+namespace po = boost::program_options;
+namespace compute = boost::compute;
+
+float rand_float()
+{
+ return (float(rand()) / float(RAND_MAX)) * 1000.f;
+}
+
+template<class T>
+double perf_saxpy(const compute::vector<T>& x,
+ const compute::vector<T>& y,
+ const T alpha,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ // create vector on the device to store the result
+ compute::vector<T> result(x.size(), queue.get_context());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < trials; trial++){
+ compute::fill(result.begin(), result.end(), T(0), queue);
+ queue.finish();
+
+ t.start();
+
+ using compute::lambda::_1;
+ using compute::lambda::_2;
+
+ compute::transform(
+ x.begin(), x.end(), y.begin(), result.begin(), alpha * _1 + _2, queue
+ );
+
+ queue.finish();
+ t.stop();
+ }
+
+ return t.min_time();
+}
+
+template<class T>
+void tune_saxpy(const compute::vector<T>& x,
+ const compute::vector<T>& y,
+ const T alpha,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ boost::shared_ptr<compute::detail::parameter_cache>
+ params = compute::detail::parameter_cache::get_global_cache(queue.get_device());
+
+ const std::string cache_key =
+ std::string("__boost_copy_kernel_") + boost::lexical_cast<std::string>(sizeof(T));
+
+ const compute::uint_ tpbs[] = { 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
+ const compute::uint_ vpts[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+ double min_time = (std::numeric_limits<double>::max)();
+ compute::uint_ best_tpb = 0;
+ compute::uint_ best_vpt = 0;
+
+ for(size_t i = 0; i < sizeof(tpbs) / sizeof(*tpbs); i++){
+ params->set(cache_key, "tpb", tpbs[i]);
+ for(size_t j = 0; j < sizeof(vpts) / sizeof(*vpts); j++){
+ params->set(cache_key, "vpt", vpts[j]);
+
+ try {
+ const double t = perf_saxpy(x, y, alpha, trials, queue);
+ if(t < min_time){
+ best_tpb = tpbs[i];
+ best_vpt = vpts[j];
+ min_time = t;
+ }
+ }
+ catch(compute::opencl_error&){
+ // invalid parameters for this device, skip
+ }
+ }
+ }
+
+ // store optimal parameters
+ params->set(cache_key, "tpb", best_tpb);
+ params->set(cache_key, "vpt", best_vpt);
+}
+
+int main(int argc, char *argv[])
+{
+ // setup command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("size", po::value<size_t>()->default_value(8192), "input size")
+ ("trials", po::value<size_t>()->default_value(3), "number of trials to run")
+ ("tune", "run tuning procedure")
+ ("alpha", po::value<double>()->default_value(2.5), "saxpy alpha value")
+ ;
+ po::positional_options_description positional_options;
+ positional_options.add("size", 1);
+
+ // parse command line
+ po::variables_map vm;
+ po::store(
+ po::command_line_parser(argc, argv)
+ .options(options).positional(positional_options).run(),
+ vm
+ );
+ po::notify(vm);
+
+ const size_t size = vm["size"].as<size_t>();
+ const size_t trials = vm["trials"].as<size_t>();
+ const float alpha = vm["alpha"].as<double>();
+ std::cout << "size: " << size << std::endl;
+
+ // setup context and queue for the default device
+ compute::device device = boost::compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<float> host_x(size);
+ std::vector<float> host_y(size);
+ std::generate(host_x.begin(), host_x.end(), rand_float);
+ std::generate(host_y.begin(), host_y.end(), rand_float);
+
+ // create vector on the device and copy the data
+ compute::vector<float> x(host_x.begin(), host_x.end(), queue);
+ compute::vector<float> y(host_y.begin(), host_y.end(), queue);
+
+ // run tuning proceure (if requested)
+ if(vm.count("tune")){
+ tune_saxpy(x, y, alpha, trials, queue);
+ }
+
+ // run benchmark
+ double t = perf_saxpy(x, y, alpha, trials, queue);
+ std::cout << "time: " << t / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_search.cpp b/src/boost/libs/compute/perf/perf_search.cpp
new file mode 100644
index 00000000..b76e9755
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_search.cpp
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/search.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int pattern[] = {2, 6, 6, 7, 8, 4};
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ boost::compute::vector<int> pattern_vector(pattern, pattern + 6, queue);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::search(
+ device_vector.begin(), device_vector.end(),
+ pattern_vector.begin(), pattern_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_search_n.cpp b/src/boost/libs/compute/perf/perf_search_n.cpp
new file mode 100644
index 00000000..31fa0adb
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_search_n.cpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/search_n.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::search_n(
+ device_vector.begin(), device_vector.end(),
+ 5, 2, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_set_difference.cpp b/src/boost/libs/compute/perf/perf_set_difference.cpp
new file mode 100644
index 00000000..b1b28573
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_set_difference.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/set_difference.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vectors of random numbers on the host
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // create vectors on the device and copy the data
+ boost::compute::vector<int> gpu_v1(std::floor(PERF_N / 2.0), context);
+ boost::compute::vector<int> gpu_v2(std::ceil(PERF_N / 2.0), context);
+
+ boost::compute::copy(
+ v1.begin(), v1.end(), gpu_v1.begin(), queue
+ );
+ boost::compute::copy(
+ v2.begin(), v2.end(), gpu_v2.begin(), queue
+ );
+
+ boost::compute::vector<int> gpu_v3(PERF_N, context);
+ boost::compute::vector<int>::iterator gpu_v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ gpu_v3_end = boost::compute::set_difference(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_set_intersection.cpp b/src/boost/libs/compute/perf/perf_set_intersection.cpp
new file mode 100644
index 00000000..dbfeb42f
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_set_intersection.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/set_intersection.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vectors of random numbers on the host
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // create vectors on the device and copy the data
+ boost::compute::vector<int> gpu_v1(std::floor(PERF_N / 2.0), context);
+ boost::compute::vector<int> gpu_v2(std::ceil(PERF_N / 2.0), context);
+
+ boost::compute::copy(
+ v1.begin(), v1.end(), gpu_v1.begin(), queue
+ );
+ boost::compute::copy(
+ v2.begin(), v2.end(), gpu_v2.begin(), queue
+ );
+
+ boost::compute::vector<int> gpu_v3(PERF_N, context);
+ boost::compute::vector<int>::iterator gpu_v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ gpu_v3_end = boost::compute::set_intersection(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_set_symmetric_difference.cpp b/src/boost/libs/compute/perf/perf_set_symmetric_difference.cpp
new file mode 100644
index 00000000..9449c585
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_set_symmetric_difference.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/set_symmetric_difference.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vectors of random numbers on the host
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // create vectors on the device and copy the data
+ boost::compute::vector<int> gpu_v1(std::floor(PERF_N / 2.0), context);
+ boost::compute::vector<int> gpu_v2(std::ceil(PERF_N / 2.0), context);
+
+ boost::compute::copy(
+ v1.begin(), v1.end(), gpu_v1.begin(), queue
+ );
+ boost::compute::copy(
+ v2.begin(), v2.end(), gpu_v2.begin(), queue
+ );
+
+ boost::compute::vector<int> gpu_v3(PERF_N, context);
+ boost::compute::vector<int>::iterator gpu_v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ gpu_v3_end = boost::compute::set_symmetric_difference(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_set_union.cpp b/src/boost/libs/compute/perf/perf_set_union.cpp
new file mode 100644
index 00000000..3a336cb6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_set_union.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/set_union.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vectors of random numbers on the host
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // create vectors on the device and copy the data
+ boost::compute::vector<int> gpu_v1(std::floor(PERF_N / 2.0), context);
+ boost::compute::vector<int> gpu_v2(std::ceil(PERF_N / 2.0), context);
+
+ boost::compute::copy(
+ v1.begin(), v1.end(), gpu_v1.begin(), queue
+ );
+ boost::compute::copy(
+ v2.begin(), v2.end(), gpu_v2.begin(), queue
+ );
+
+ boost::compute::vector<int> gpu_v3(PERF_N, context);
+ boost::compute::vector<int>::iterator gpu_v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ gpu_v3_end = boost::compute::set_union(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_sort.cpp b/src/boost/libs/compute/perf/perf_sort.cpp
new file mode 100644
index 00000000..458203ed
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_sort.cpp
@@ -0,0 +1,130 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/program_options.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 "perf.hpp"
+
+namespace po = boost::program_options;
+namespace compute = boost::compute;
+
+template<class T>
+double perf_sort(const std::vector<T>& data,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ compute::vector<T> vec(data.size(), queue.get_context());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < trials; trial++){
+ compute::copy(data.begin(), data.end(), vec.begin(), queue);
+ t.start();
+ compute::sort(vec.begin(), vec.end(), queue);
+ queue.finish();
+ t.stop();
+
+ if(!compute::is_sorted(vec.begin(), vec.end(), queue)){
+ std::cerr << "ERROR: is_sorted() returned false" << std::endl;
+ }
+ }
+ return t.min_time();
+}
+
+template<class T>
+void tune_sort(const std::vector<T>& data,
+ const size_t trials,
+ compute::command_queue& queue)
+{
+ boost::shared_ptr<compute::detail::parameter_cache>
+ params = compute::detail::parameter_cache::get_global_cache(queue.get_device());
+
+ const std::string cache_key =
+ std::string("__boost_radix_sort_") + compute::type_name<T>();
+
+ const compute::uint_ tpbs[] = { 32, 64, 128, 256, 512, 1024 };
+
+ double min_time = (std::numeric_limits<double>::max)();
+ compute::uint_ best_tpb = 0;
+
+ for(size_t i = 0; i < sizeof(tpbs) / sizeof(*tpbs); i++){
+ params->set(cache_key, "tpb", tpbs[i]);
+
+ try {
+ const double t = perf_sort(data, trials, queue);
+ if(t < min_time){
+ best_tpb = tpbs[i];
+ min_time = t;
+ }
+ }
+ catch(compute::opencl_error&){
+ // invalid work group size for this device, skip
+ }
+ }
+
+ // store optimal parameters
+ params->set(cache_key, "tpb", best_tpb);
+}
+
+int main(int argc, char *argv[])
+{
+ // setup command line arguments
+ po::options_description options("options");
+ options.add_options()
+ ("help", "show usage instructions")
+ ("size", po::value<size_t>()->default_value(8192), "input size")
+ ("trials", po::value<size_t>()->default_value(3), "number of trials to run")
+ ("tune", "run tuning procedure")
+ ;
+ po::positional_options_description positional_options;
+ positional_options.add("size", 1);
+
+ // parse command line
+ po::variables_map vm;
+ po::store(
+ po::command_line_parser(argc, argv)
+ .options(options).positional(positional_options).run(),
+ vm
+ );
+ po::notify(vm);
+
+ const size_t size = vm["size"].as<size_t>();
+ const size_t trials = vm["trials"].as<size_t>();
+ std::cout << "size: " << size << std::endl;
+
+ // setup context and queue for the default device
+ compute::device device = boost::compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<unsigned int> data(size);
+ std::generate(data.begin(), data.end(), rand);
+
+ // run tuning proceure (if requested)
+ if(vm.count("tune")){
+ tune_sort(data, trials, queue);
+ }
+
+ // run sort benchmark
+ double t = perf_sort(data, trials, queue);
+ std::cout << "time: " << t / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_sort_by_key.cpp b/src/boost/libs/compute/perf/perf_sort_by_key.cpp
new file mode 100644
index 00000000..57c3fc83
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_sort_by_key.cpp
@@ -0,0 +1,79 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#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/fundamental.hpp>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ using boost::compute::int_;
+ using boost::compute::long_;
+
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int_> host_keys(PERF_N);
+ std::generate(host_keys.begin(), host_keys.end(), rand);
+ std::vector<long_> host_values(PERF_N);
+ std::copy(host_keys.begin(), host_keys.end(), host_values.begin());
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int_> device_keys(PERF_N, context);
+ boost::compute::vector<long_> device_values(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_keys.begin(), host_keys.end(), device_keys.begin(), queue
+ );
+ boost::compute::copy(
+ host_values.begin(), host_values.end(), device_values.begin(), queue
+ );
+
+ t.start();
+ // sort vector
+ boost::compute::sort_by_key(
+ device_keys.begin(), device_keys.end(), device_values.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify keys are sorted
+ if(!boost::compute::is_sorted(device_keys.begin(), device_keys.end(), queue)){
+ std::cout << "ERROR: is_sorted() returned false for the keys" << std::endl;
+ return -1;
+ }
+ // verify values are sorted
+ if(!boost::compute::is_sorted(device_values.begin(), device_values.end(), queue)){
+ std::cout << "ERROR: is_sorted() returned false for the values" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_sort_float.cpp b/src/boost/libs/compute/perf/perf_sort_float.cpp
new file mode 100644
index 00000000..1b2d5f5e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_sort_float.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/is_sorted.hpp>
+#include <boost/compute/algorithm/sort.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+float rand_float()
+{
+ return ((rand() / float(RAND_MAX)) - 0.5f) * 100000.0f;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<float> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_float);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<float> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(),
+ host_vector.end(),
+ device_vector.begin(),
+ queue
+ );
+
+ // sort vector
+ perf_timer t;
+ t.start();
+ boost::compute::sort(
+ device_vector.begin(),
+ device_vector.end(),
+ queue
+ );
+ queue.finish();
+ t.stop();
+ std::cout << "time: " << t.last_time() / 1e6 << " ms" << std::endl;
+
+ // verify vector is sorted
+ if(!boost::compute::is_sorted(device_vector.begin(),
+ device_vector.end(),
+ queue)){
+ std::cout << "ERROR: is_sorted() returned false" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stable_partition.cpp b/src/boost/libs/compute/perf/perf_stable_partition.cpp
new file mode 100644
index 00000000..f7ef1063
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stable_partition.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/stable_partition.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+
+ using boost::compute::_1;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ boost::compute::stable_partition(
+ device_vector.begin(), device_vector.end(), _1 < 10, queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_accumulate.cpp b/src/boost/libs/compute/perf/perf_stl_accumulate.cpp
new file mode 100644
index 00000000..c28d2d03
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_accumulate.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int sum = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ sum = std::accumulate(host_vector.begin(), host_vector.end(), int(0));
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "sum: " << sum << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_count.cpp b/src/boost/libs/compute/perf/perf_stl_count.cpp
new file mode 100644
index 00000000..9df13f86
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_count.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // count values equal to four in the vector
+ size_t count = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ count = std::count(
+ host_vector.begin(), host_vector.end(), 4
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "count: " << count << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_find.cpp b/src/boost/libs/compute/perf/perf_stl_find.cpp
new file mode 100644
index 00000000..b5d3eed2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_find.cpp
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "perf.hpp"
+
+// Max integer that can be generated by rand_int() function.
+int rand_int_max = 25;
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * rand_int_max);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // trying to find element that isn't in vector (worst-case scenario)
+ int wanted = rand_int_max + 1;
+
+ // result
+ std::vector<int>::iterator host_result_it;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ host_result_it = std::find(host_vector.begin(), host_vector.end(), wanted);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify
+ if(host_result_it != host_vector.end()){
+ std::cout << "ERROR: "
+ << "host_result_iterator != "
+ << "host_vector.end()"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_find_end.cpp b/src/boost/libs/compute/perf/perf_stl_find_end.cpp
new file mode 100644
index 00000000..cb1233b1
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_find_end.cpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int pattern[] = {2, 6, 6, 7, 8, 4};
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::find_end(host_vector.begin(), host_vector.end(),
+ pattern, pattern + 6);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_includes.cpp b/src/boost/libs/compute/perf/perf_stl_includes.cpp
new file mode 100644
index 00000000..b71dbf3c
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_includes.cpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v1(PERF_N);
+ std::generate(v1.begin(), v1.end(), rand_int);
+
+ std::vector<int> v2(v1);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::includes(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_inner_product.cpp b/src/boost/libs/compute/perf/perf_stl_inner_product.cpp
new file mode 100644
index 00000000..884f06c9
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_inner_product.cpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> h1(PERF_N);
+ std::vector<int> h2(PERF_N);
+ std::generate(h1.begin(), h1.end(), rand_int);
+ std::generate(h2.begin(), h2.end(), rand_int);
+
+ int product = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ product = std::inner_product(
+ h1.begin(), h1.end(), h2.begin(), int(0)
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "product: " << product << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_is_permutation.cpp b/src/boost/libs/compute/perf/perf_stl_is_permutation.cpp
new file mode 100644
index 00000000..1384e8e9
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_is_permutation.cpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ std::vector<int> host_vector2(PERF_N);
+ std::copy(host_vector.rbegin(), host_vector.rend(), host_vector2.begin());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::is_permutation(host_vector.begin(), host_vector.end(),
+ host_vector2.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_max_element.cpp b/src/boost/libs/compute/perf/perf_stl_max_element.cpp
new file mode 100644
index 00000000..3fa61267
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_max_element.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2013-2014 Rastko Anicic <anicic.rastko@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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>(rand() % 10000000);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int max = 0;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ max = *(std::max_element(host_vector.begin(), host_vector.end()));
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "max: " << max << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_merge.cpp b/src/boost/libs/compute/perf/perf_stl_merge.cpp
new file mode 100644
index 00000000..0a842a04
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_merge.cpp
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------------//
+// 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 <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ std::vector<int> v1 = generate_random_vector<int>(std::floor(PERF_N / 2.0));
+ std::vector<int> v2 = generate_random_vector<int>(std::ceil(PERF_N / 2.0));
+ std::vector<int> v3(PERF_N);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_next_permutation.cpp b/src/boost/libs/compute/perf/perf_stl_next_permutation.cpp
new file mode 100644
index 00000000..22148975
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_next_permutation.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::sort(host_vector.begin(), host_vector.end(), std::greater<int>());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::next_permutation(host_vector.begin(), host_vector.end());
+ t.stop();
+ std::prev_permutation(host_vector.begin(), host_vector.end());
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_partial_sum.cpp b/src/boost/libs/compute/perf/perf_stl_partial_sum.cpp
new file mode 100644
index 00000000..533defb2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_partial_sum.cpp
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ using boost::compute::int_;
+
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int_> v(PERF_N);
+ std::vector<int_> r(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ std::generate(v.begin(), v.end(), rand_int);
+ t.start();
+ std::partial_sum(
+ v.begin(),
+ v.end(),
+ r.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_partition.cpp b/src/boost/libs/compute/perf/perf_stl_partition.cpp
new file mode 100644
index 00000000..56aadd0d
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_partition.cpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+bool less_than_10(int value)
+{
+ return value < 10;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::partition(host_vector.begin(), host_vector.end(), less_than_10);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_partition_point.cpp b/src/boost/libs/compute/perf/perf_stl_partition_point.cpp
new file mode 100644
index 00000000..94b1c263
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_partition_point.cpp
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+bool less_than_20(int value)
+{
+ return value < 20;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::partition(host_vector.begin(), host_vector.end(),
+ less_than_20);
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::partition_point(host_vector.begin(), host_vector.end(),
+ less_than_20);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_prev_permutation.cpp b/src/boost/libs/compute/perf/perf_stl_prev_permutation.cpp
new file mode 100644
index 00000000..f246ba2a
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_prev_permutation.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ std::sort(host_vector.begin(), host_vector.end());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::prev_permutation(host_vector.begin(), host_vector.end());
+ t.stop();
+ std::next_permutation(host_vector.begin(), host_vector.end());
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_reverse.cpp b/src/boost/libs/compute/perf/perf_stl_reverse.cpp
new file mode 100644
index 00000000..b2ee2ef6
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_reverse.cpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::reverse(host_vector.begin(), host_vector.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_reverse_copy.cpp b/src/boost/libs/compute/perf/perf_stl_reverse_copy.cpp
new file mode 100644
index 00000000..1397e9a7
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_reverse_copy.cpp
@@ -0,0 +1,45 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector for reversed data
+ std::vector<int> host_reversed_vector(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::reverse_copy(host_vector.begin(), host_vector.end(),
+ host_reversed_vector.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_rotate.cpp b/src/boost/libs/compute/perf/perf_stl_rotate.cpp
new file mode 100644
index 00000000..f90acef2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_rotate.cpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::rotate(host_vector.begin(), host_vector.begin()+(PERF_N/2), host_vector.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_rotate_copy.cpp b/src/boost/libs/compute/perf/perf_stl_rotate_copy.cpp
new file mode 100644
index 00000000..516d11c2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_rotate_copy.cpp
@@ -0,0 +1,43 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ std::vector<int> host_vector2(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::rotate_copy(host_vector.begin(), host_vector.begin()+(PERF_N/2), host_vector.end(), host_vector2.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_saxpy.cpp b/src/boost/libs/compute/perf/perf_stl_saxpy.cpp
new file mode 100644
index 00000000..8ab33535
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_saxpy.cpp
@@ -0,0 +1,52 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "perf.hpp"
+
+float rand_float()
+{
+ return (float(rand()) / float(RAND_MAX)) * 1000.f;
+}
+
+// y <- alpha * x + y
+void serial_saxpy(size_t n, float alpha, const float *x, float *y)
+{
+ for(size_t i = 0; i < n; i++){
+ y[i] = alpha * x[i] + y[i];
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ float alpha = 2.5f;
+
+ std::vector<float> host_x(PERF_N);
+ std::vector<float> host_y(PERF_N);
+ std::generate(host_x.begin(), host_x.end(), rand_float);
+ std::generate(host_y.begin(), host_y.end(), rand_float);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ serial_saxpy(PERF_N, alpha, &host_x[0], &host_y[0]);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_search.cpp b/src/boost/libs/compute/perf/perf_stl_search.cpp
new file mode 100644
index 00000000..8166d35e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_search.cpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int pattern[] = {2, 6, 6, 7, 8, 4};
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::search(host_vector.begin(), host_vector.end(),
+ pattern, pattern + 6);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_search_n.cpp b/src/boost/libs/compute/perf/perf_stl_search_n.cpp
new file mode 100644
index 00000000..76a6bb07
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_search_n.cpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::search_n(host_vector.begin(), host_vector.end(), 5, 2);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_set_difference.cpp b/src/boost/libs/compute/perf/perf_stl_set_difference.cpp
new file mode 100644
index 00000000..c5d0802d
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_set_difference.cpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ std::vector<int> v3(PERF_N);
+ std::vector<int>::iterator v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ v3_end = std::set_difference(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(v3.begin(), v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_set_intersection.cpp b/src/boost/libs/compute/perf/perf_stl_set_intersection.cpp
new file mode 100644
index 00000000..6aa3493b
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_set_intersection.cpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ std::vector<int> v3(PERF_N);
+ std::vector<int>::iterator v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ v3_end = std::set_intersection(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(v3.begin(), v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_set_symmetric_difference.cpp b/src/boost/libs/compute/perf/perf_stl_set_symmetric_difference.cpp
new file mode 100644
index 00000000..c22c70a7
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_set_symmetric_difference.cpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ std::vector<int> v3(PERF_N);
+ std::vector<int>::iterator v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ v3_end = std::set_symmetric_difference(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(v3.begin(), v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_set_union.cpp b/src/boost/libs/compute/perf/perf_stl_set_union.cpp
new file mode 100644
index 00000000..9d4fe3a8
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_set_union.cpp
@@ -0,0 +1,54 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v1(std::floor(PERF_N / 2.0));
+ std::vector<int> v2(std::ceil(PERF_N / 2.0));
+
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ std::vector<int> v3(PERF_N);
+ std::vector<int>::iterator v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ v3_end = std::set_union(
+ v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ v3.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << std::distance(v3.begin(), v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_sort.cpp b/src/boost/libs/compute/perf/perf_stl_sort.cpp
new file mode 100644
index 00000000..c9d4294b
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_sort.cpp
@@ -0,0 +1,33 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ std::vector<int> v;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ v = generate_random_vector<int>(PERF_N);
+ t.start();
+ std::sort(v.begin(), v.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_stable_partition.cpp b/src/boost/libs/compute/perf/perf_stl_stable_partition.cpp
new file mode 100644
index 00000000..ee4993cc
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_stable_partition.cpp
@@ -0,0 +1,47 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+bool less_than_10(int value)
+{
+ return value < 10;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ std::stable_partition(host_vector.begin(), host_vector.end(),
+ less_than_10);
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_unique.cpp b/src/boost/libs/compute/perf/perf_stl_unique.cpp
new file mode 100644
index 00000000..f4f97b4b
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_unique.cpp
@@ -0,0 +1,41 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ t.start();
+ std::unique(host_vector.begin(), host_vector.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_stl_unique_copy.cpp b/src/boost/libs/compute/perf/perf_stl_unique_copy.cpp
new file mode 100644
index 00000000..77705fa2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_stl_unique_copy.cpp
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::vector<int> host_vector2(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+ t.start();
+ std::unique_copy(
+ host_vector.begin(), host_vector.end(), host_vector2.begin()
+ );
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_tbb_accumulate.cpp b/src/boost/libs/compute/perf/perf_tbb_accumulate.cpp
new file mode 100644
index 00000000..319ad8af
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_tbb_accumulate.cpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <tbb/blocked_range.h>
+#include <tbb/parallel_reduce.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+template<class T>
+struct Sum {
+ T value;
+ Sum() : value(0) {}
+ Sum( Sum& s, tbb::split ) {value = 0;}
+ void operator()( const tbb::blocked_range<T*>& r ) {
+ T temp = value;
+ for( T* a=r.begin(); a!=r.end(); ++a ) {
+ temp += *a;
+ }
+ value = temp;
+ }
+ void join( Sum& rhs ) {value += rhs.value;}
+};
+
+template<class T>
+T ParallelSum( T array[], size_t n ) {
+ Sum<T> total;
+ tbb::parallel_reduce( tbb::blocked_range<T*>( array, array+n ),
+ total );
+ return total.value;
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ int sum = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ sum = ParallelSum<int>(&host_vector[0], host_vector.size());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "sum: " << sum << std::endl;
+
+ int host_sum = std::accumulate(host_vector.begin(), host_vector.end(), int(0));
+ if(sum != host_sum){
+ std::cerr << "ERROR: sum (" << sum << ") != (" << host_sum << ")" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_tbb_merge.cpp b/src/boost/libs/compute/perf/perf_tbb_merge.cpp
new file mode 100644
index 00000000..a7aa814e
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_tbb_merge.cpp
@@ -0,0 +1,95 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <tbb/parallel_for.h>
+
+#include "perf.hpp"
+
+// example from: http://www.threadingbuildingblocks.org/docs/help/reference/algorithms/parallel_for_func.htm
+using namespace tbb;
+
+template<typename Iterator>
+struct ParallelMergeRange {
+ static size_t grainsize;
+ Iterator begin1, end1; // [begin1,end1) is 1st sequence to be merged
+ Iterator begin2, end2; // [begin2,end2) is 2nd sequence to be merged
+ Iterator out; // where to put merged sequence
+ bool empty() const {return (end1-begin1)+(end2-begin2)==0;}
+ bool is_divisible() const {
+ return (std::min)( end1-begin1, end2-begin2 ) > grainsize;
+ }
+ ParallelMergeRange( ParallelMergeRange& r, split ) {
+ if( r.end1-r.begin1 < r.end2-r.begin2 ) {
+ std::swap(r.begin1,r.begin2);
+ std::swap(r.end1,r.end2);
+ }
+ Iterator m1 = r.begin1 + (r.end1-r.begin1)/2;
+ Iterator m2 = std::lower_bound( r.begin2, r.end2, *m1 );
+ begin1 = m1;
+ begin2 = m2;
+ end1 = r.end1;
+ end2 = r.end2;
+ out = r.out + (m1-r.begin1) + (m2-r.begin2);
+ r.end1 = m1;
+ r.end2 = m2;
+ }
+ ParallelMergeRange( Iterator begin1_, Iterator end1_,
+ Iterator begin2_, Iterator end2_,
+ Iterator out_ ) :
+ begin1(begin1_), end1(end1_),
+ begin2(begin2_), end2(end2_), out(out_)
+ {}
+};
+
+template<typename Iterator>
+size_t ParallelMergeRange<Iterator>::grainsize = 1000;
+
+template<typename Iterator>
+struct ParallelMergeBody {
+ void operator()( ParallelMergeRange<Iterator>& r ) const {
+ std::merge( r.begin1, r.end1, r.begin2, r.end2, r.out );
+ }
+};
+
+template<typename Iterator>
+void ParallelMerge( Iterator begin1, Iterator end1, Iterator begin2, Iterator end2, Iterator out ) {
+ parallel_for(
+ ParallelMergeRange<Iterator>(begin1,end1,begin2,end2,out),
+ ParallelMergeBody<Iterator>(),
+ simple_partitioner()
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ std::vector<int> v1 = generate_random_vector<int>(PERF_N / 2);
+ std::vector<int> v2 = generate_random_vector<int>(PERF_N / 2);
+ std::vector<int> v3(PERF_N);
+
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ ParallelMerge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_tbb_sort.cpp b/src/boost/libs/compute/perf/perf_tbb_sort.cpp
new file mode 100644
index 00000000..2f79b5b2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_tbb_sort.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.
+//---------------------------------------------------------------------------//
+
+#include <iostream>
+#include <vector>
+
+#include <tbb/parallel_sort.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ std::vector<int> v(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ v = generate_random_vector<int>(PERF_N);
+ t.start();
+ tbb::parallel_sort(v.begin(), v.end());
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_accumulate.cu b/src/boost/libs/compute/perf/perf_thrust_accumulate.cu
new file mode 100644
index 00000000..76b72321
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_accumulate.cu
@@ -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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/reduce.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec = h_vec;
+
+ int sum = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ sum = thrust::reduce(d_vec.begin(), d_vec.end());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "sum: " << sum << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_count.cu b/src/boost/libs/compute/perf/perf_thrust_count.cu
new file mode 100644
index 00000000..d69df901
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_count.cu
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <thrust/count.h>
+#include <thrust/host_vector.h>
+#include <thrust/device_vector.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ thrust::host_vector<int> host_vector(PERF_N);
+ thrust::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ thrust::device_vector<int> v = host_vector;
+
+ size_t count = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ count = thrust::count(v.begin(), v.end(), 4);
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "count: " << count << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_exclusive_scan.cu b/src/boost/libs/compute/perf/perf_thrust_exclusive_scan.cu
new file mode 100644
index 00000000..df1367a2
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_exclusive_scan.cu
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2014 Benoit
+//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/scan.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec = h_vec;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::exclusive_scan(d_vec.begin(), d_vec.end(), d_vec.begin());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_find.cu b/src/boost/libs/compute/perf/perf_thrust_find.cu
new file mode 100644
index 00000000..e1482604
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_find.cu
@@ -0,0 +1,65 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <thrust/find.h>
+#include <thrust/host_vector.h>
+#include <thrust/device_vector.h>
+
+#include "perf.hpp"
+
+// Max integer that can be generated by rand_int() function.
+int rand_int_max = 25;
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * rand_int_max);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of random numbers on the host
+ thrust::host_vector<int> host_vector(PERF_N);
+ thrust::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ thrust::device_vector<int> v = host_vector;
+
+ // trying to find element that isn't in vector (worst-case scenario)
+ int wanted = rand_int_max + 1;
+
+ // result
+ thrust::device_vector<int>::iterator device_result_it;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ device_result_it = thrust::find(v.begin(), v.end(), wanted);
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // verify
+ if(device_result_it != v.end()){
+ std::cout << "ERROR: "
+ << "device_result_iterator != "
+ << "v.end()"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_inner_product.cu b/src/boost/libs/compute/perf/perf_thrust_inner_product.cu
new file mode 100644
index 00000000..6d01fc53
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_inner_product.cu
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <iterator>
+#include <algorithm>
+
+#include <thrust/device_vector.h>
+#include <thrust/host_vector.h>
+#include <thrust/inner_product.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> host_x(PERF_N);
+ thrust::host_vector<int> host_y(PERF_N);
+ std::generate(host_x.begin(), host_x.end(), rand);
+ std::generate(host_y.begin(), host_y.end(), rand);
+
+ // transfer data to the device
+ thrust::device_vector<int> device_x = host_x;
+ thrust::device_vector<int> device_y = host_y;
+
+ int product = 0;
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ product = thrust::inner_product(
+ device_x.begin(), device_x.end(), device_y.begin(), 0
+ );
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "product: " << product << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_merge.cu b/src/boost/libs/compute/perf/perf_thrust_merge.cu
new file mode 100644
index 00000000..f269c939
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_merge.cu
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <iterator>
+#include <algorithm>
+
+#include <thrust/device_vector.h>
+#include <thrust/host_vector.h>
+#include <thrust/merge.h>
+#include <thrust/sort.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> v1(std::floor(PERF_N / 2.0));
+ thrust::host_vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand);
+ std::generate(v2.begin(), v2.end(), rand);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // transfer data to the device
+ thrust::device_vector<int> gpu_v1 = v1;
+ thrust::device_vector<int> gpu_v2 = v2;
+ thrust::device_vector<int> gpu_v3(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ thrust::merge(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin()
+ );
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ thrust::host_vector<int> check_v3 = gpu_v3;
+
+ thrust::host_vector<int> v3(PERF_N);
+ std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
+ bool ok = std::equal(check_v3.begin(), check_v3.end(), v3.begin());
+ if(!ok){
+ std::cerr << "ERROR: merged ranges different" << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_partial_sum.cu b/src/boost/libs/compute/perf/perf_thrust_partial_sum.cu
new file mode 100644
index 00000000..e30e80b5
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_partial_sum.cu
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/scan.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec = h_vec;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::inclusive_scan(d_vec.begin(), d_vec.end(), d_vec.begin());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_partition.cu b/src/boost/libs/compute/perf/perf_thrust_partition.cu
new file mode 100644
index 00000000..5c89014c
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_partition.cu
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/partition.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+struct less_than_ten : public thrust::unary_function<bool, int>
+{
+ __device__ bool operator()(int x) const
+ {
+ return x < 10;
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec(PERF_N);
+ std::generate(h_vec.begin(), h_vec.end(), rand_int);
+
+ thrust::device_vector<int> d_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::partition(
+ d_vec.begin(), d_vec.end(), less_than_ten()
+ );
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_reduce_by_key.cu b/src/boost/libs/compute/perf/perf_thrust_reduce_by_key.cu
new file mode 100644
index 00000000..a445c137
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_reduce_by_key.cu
@@ -0,0 +1,92 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/reduce.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+struct unique_key {
+ int current;
+ int avgValuesNoPerKey;
+
+ unique_key()
+ {
+ current = 0;
+ avgValuesNoPerKey = 512;
+ }
+
+ int operator()()
+ {
+ double p = double(1.0) / static_cast<double>(avgValuesNoPerKey);
+ if((rand() / double(RAND_MAX)) <= p)
+ return ++current;
+ return current;
+ }
+} UniqueKey;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // create vector of keys and random values
+ thrust::host_vector<int> host_keys(PERF_N);
+ thrust::host_vector<int> host_values(PERF_N);
+ std::generate(host_keys.begin(), host_keys.end(), UniqueKey);
+ std::generate(host_values.begin(), host_values.end(), rand_int);
+
+ // transfer data to the device
+ thrust::device_vector<int> device_keys = host_keys;
+ thrust::device_vector<int> device_values = host_values;
+
+ // create device vectors for the results
+ thrust::device_vector<int> device_keys_results(PERF_N);
+ thrust::device_vector<int> device_values_results(PERF_N);
+
+ typedef typename thrust::device_vector<int>::iterator iterType;
+ thrust::pair<iterType, iterType> result;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ result = thrust::reduce_by_key(device_keys.begin(),
+ device_keys.end(),
+ device_values.begin(),
+ device_keys_results.begin(),
+ device_values_results.begin());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ size_t result_size = thrust::distance(device_keys_results.begin(), result.first);
+ if(result_size != static_cast<size_t>(host_keys[PERF_N-1] + 1)){
+ std::cout << "ERROR: "
+ << "wrong number of keys"
+ << std::endl;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_reverse.cu b/src/boost/libs/compute/perf/perf_thrust_reverse.cu
new file mode 100644
index 00000000..1927ca6a
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_reverse.cu
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/reverse.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::reverse(d_vec.begin(), d_vec.end());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_reverse_copy.cu b/src/boost/libs/compute/perf/perf_thrust_reverse_copy.cu
new file mode 100644
index 00000000..af1a044d
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_reverse_copy.cu
@@ -0,0 +1,47 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/reverse.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec;
+ d_vec = h_vec;
+
+ // device vector for reversed data
+ thrust::device_vector<int> d_reversed_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ thrust::reverse_copy(d_vec.begin(), d_vec.end(), d_reversed_vec.begin());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_rotate.cu b/src/boost/libs/compute/perf/perf_thrust_rotate.cu
new file mode 100644
index 00000000..108bb99b
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_rotate.cu
@@ -0,0 +1,51 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/host_vector.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec;
+
+ size_t rotate_distance = PERF_N / 2;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ // there is no thrust::rotate() so we implement it manually with copy()
+ thrust::device_vector<int> tmp(d_vec.begin(), d_vec.begin() + rotate_distance);
+ thrust::copy(d_vec.begin() + rotate_distance, d_vec.end(), d_vec.begin());
+ thrust::copy(tmp.begin(), tmp.end(), d_vec.begin() + rotate_distance);
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_saxpy.cu b/src/boost/libs/compute/perf/perf_thrust_saxpy.cu
new file mode 100644
index 00000000..aa35a191
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_saxpy.cu
@@ -0,0 +1,63 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <iterator>
+#include <algorithm>
+
+#include <thrust/device_vector.h>
+#include <thrust/functional.h>
+#include <thrust/host_vector.h>
+#include <thrust/transform.h>
+
+#include "perf.hpp"
+
+struct saxpy_functor : public thrust::binary_function<float,float,float>
+{
+ const float a;
+
+ saxpy_functor(float _a) : a(_a) {}
+
+ __host__ __device__
+ float operator()(const float& x, const float& y) const
+ {
+ return a * x + y;
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> host_x(PERF_N);
+ thrust::host_vector<int> host_y(PERF_N);
+ std::generate(host_x.begin(), host_x.end(), rand);
+ std::generate(host_y.begin(), host_y.end(), rand);
+
+ // transfer data to the device
+ thrust::device_vector<int> device_x = host_x;
+ thrust::device_vector<int> device_y = host_y;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ thrust::transform(device_x.begin(), device_x.end(), device_y.begin(), device_y.begin(), saxpy_functor(2.5f));
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(device_x.begin(), device_x.end(), host_x.begin());
+ thrust::copy(device_y.begin(), device_y.end(), host_y.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_set_difference.cu b/src/boost/libs/compute/perf/perf_thrust_set_difference.cu
new file mode 100644
index 00000000..3465f214
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_set_difference.cu
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// 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 <iostream>
+#include <iterator>
+#include <algorithm>
+
+#include <thrust/device_vector.h>
+#include <thrust/host_vector.h>
+#include <thrust/set_operations.h>
+#include <thrust/sort.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> v1(std::floor(PERF_N / 2.0));
+ thrust::host_vector<int> v2(std::ceil(PERF_N / 2.0));
+ std::generate(v1.begin(), v1.end(), rand_int);
+ std::generate(v2.begin(), v2.end(), rand_int);
+ std::sort(v1.begin(), v1.end());
+ std::sort(v2.begin(), v2.end());
+
+ // transfer data to the device
+ thrust::device_vector<int> gpu_v1 = v1;
+ thrust::device_vector<int> gpu_v2 = v2;
+ thrust::device_vector<int> gpu_v3(PERF_N);
+
+ thrust::device_vector<int>::iterator gpu_v3_end;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ t.start();
+ gpu_v3_end = thrust::set_difference(
+ gpu_v1.begin(), gpu_v1.end(),
+ gpu_v2.begin(), gpu_v2.end(),
+ gpu_v3.begin()
+ );
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+ std::cout << "size: " << thrust::distance(gpu_v3.begin(), gpu_v3_end) << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_sort.cu b/src/boost/libs/compute/perf/perf_thrust_sort.cu
new file mode 100644
index 00000000..b2d90939
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_sort.cu
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------------//
+// 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 <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/sort.h>
+
+#include "perf.hpp"
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec = generate_random_vector<int>(PERF_N);
+
+ // transfer data to the device
+ thrust::device_vector<int> d_vec;
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::sort(d_vec.begin(), d_vec.end());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ // transfer data back to host
+ thrust::copy(d_vec.begin(), d_vec.end(), h_vec.begin());
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_thrust_unique.cu b/src/boost/libs/compute/perf/perf_thrust_unique.cu
new file mode 100644
index 00000000..6030f291
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_thrust_unique.cu
@@ -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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <cstdlib>
+#include <iostream>
+
+#include <thrust/copy.h>
+#include <thrust/device_vector.h>
+#include <thrust/generate.h>
+#include <thrust/host_vector.h>
+#include <thrust/unique.h>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+
+ std::cout << "size: " << PERF_N << std::endl;
+ thrust::host_vector<int> h_vec(PERF_N);
+ std::generate(h_vec.begin(), h_vec.end(), rand_int);
+
+ thrust::device_vector<int> d_vec(PERF_N);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ d_vec = h_vec;
+
+ t.start();
+ thrust::unique(d_vec.begin(), d_vec.end());
+ cudaDeviceSynchronize();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_uniform_int_distribution.cpp b/src/boost/libs/compute/perf/perf_uniform_int_distribution.cpp
new file mode 100644
index 00000000..57973a81
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_uniform_int_distribution.cpp
@@ -0,0 +1,46 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/random/default_random_engine.hpp>
+#include <boost/compute/random/uniform_int_distribution.hpp>
+
+#include "perf.hpp"
+
+namespace compute = boost::compute;
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ compute::device device = compute::system::default_device();
+ compute::context context(device);
+ compute::command_queue queue(context, device);
+
+ compute::vector<compute::uint_> vector(PERF_N, context);
+
+ compute::default_random_engine rng(queue);
+ compute::uniform_int_distribution<compute::uint_> dist(0, 1);
+
+ perf_timer t;
+ t.start();
+ dist.generate(vector.begin(), vector.end(), rng, queue);
+ queue.finish();
+ t.stop();
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_unique.cpp b/src/boost/libs/compute/perf/perf_unique.cpp
new file mode 100644
index 00000000..b25801f1
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_unique.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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/unique.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+ t.start();
+ boost::compute::unique(
+ device_vector.begin(), device_vector.end(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perf_unique_copy.cpp b/src/boost/libs/compute/perf/perf_unique_copy.cpp
new file mode 100644
index 00000000..d7ff98af
--- /dev/null
+++ b/src/boost/libs/compute/perf/perf_unique_copy.cpp
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------//
+// 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.
+//---------------------------------------------------------------------------//
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <vector>
+
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/unique_copy.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "perf.hpp"
+
+int rand_int()
+{
+ return static_cast<int>((rand() / double(RAND_MAX)) * 25.0);
+}
+
+int main(int argc, char *argv[])
+{
+ perf_parse_args(argc, argv);
+ std::cout << "size: " << PERF_N << std::endl;
+
+ // setup context and queue for the default device
+ boost::compute::device device = boost::compute::system::default_device();
+ boost::compute::context context(device);
+ boost::compute::command_queue queue(context, device);
+ std::cout << "device: " << device.name() << std::endl;
+
+ // create vector of random numbers on the host
+ std::vector<int> host_vector(PERF_N);
+ std::generate(host_vector.begin(), host_vector.end(), rand_int);
+
+ // create vector on the device and copy the data
+ boost::compute::vector<int> device_vector(PERF_N, context);
+ boost::compute::vector<int> device_vector2(PERF_N, context);
+
+ perf_timer t;
+ for(size_t trial = 0; trial < PERF_TRIALS; trial++){
+ boost::compute::copy(
+ host_vector.begin(), host_vector.end(), device_vector.begin(), queue
+ );
+ t.start();
+ boost::compute::unique_copy(
+ device_vector.begin(), device_vector.end(), device_vector2.begin(), queue
+ );
+ queue.finish();
+ t.stop();
+ }
+ std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/compute/perf/perfdoc.py b/src/boost/libs/compute/perf/perfdoc.py
new file mode 100755
index 00000000..e9c60362
--- /dev/null
+++ b/src/boost/libs/compute/perf/perfdoc.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+# Copyright (c) 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.
+
+import os
+import sys
+import pylab
+
+from perf import run_benchmark
+
+fignum = 0
+
+def plot_to_file(report, filename):
+ global fignum
+ fignum += 1
+ pylab.figure(fignum)
+
+ run_to_label = {
+ "stl" : "C++ STL",
+ "thrust" : "Thrust",
+ "compute" : "Boost.Compute",
+ "bolt" : "Bolt"
+ }
+
+ for run in sorted(report.samples.keys()):
+ x = []
+ y = []
+
+ for sample in report.samples[run]:
+ x.append(sample[0])
+ y.append(sample[1])
+
+ pylab.loglog(x, y, marker='o', label=run_to_label[run])
+
+ pylab.xlabel("Size")
+ pylab.ylabel("Time (ms)")
+ pylab.legend(loc='upper left')
+ pylab.savefig(filename)
+
+if __name__ == '__main__':
+ sizes = [pow(2, x) for x in range(10, 26)]
+ algorithms = [
+ "accumulate",
+ "count",
+ "inner_product",
+ "merge",
+ "partial_sum",
+ "partition",
+ "reverse",
+ "rotate",
+ "saxpy",
+ "sort",
+ "unique",
+ ]
+
+ try:
+ os.mkdir("perf_plots")
+ except OSError:
+ pass
+
+ for algorithm in algorithms:
+ print("running '%s'" % (algorithm))
+ report = run_benchmark(algorithm, sizes, ["stl", "thrust", "bolt"])
+ plot_to_file(report, "perf_plots/%s_time_plot.png" % algorithm)
+
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()