]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/compute/include/boost/compute/types/struct.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / compute / include / boost / compute / types / struct.hpp
CommitLineData
7c673cae
FG
1//---------------------------------------------------------------------------//
2// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
3//
4// Distributed under the Boost Software License, Version 1.0
5// See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt
7//
8// See http://boostorg.github.com/compute for more information.
9//---------------------------------------------------------------------------//
10
11#ifndef BOOST_COMPUTE_TYPES_STRUCT_HPP
12#define BOOST_COMPUTE_TYPES_STRUCT_HPP
13
14#include <sstream>
15
16#include <boost/static_assert.hpp>
17
18#include <boost/preprocessor/expr_if.hpp>
19#include <boost/preprocessor/stringize.hpp>
20#include <boost/preprocessor/seq/fold_left.hpp>
21#include <boost/preprocessor/seq/for_each.hpp>
22#include <boost/preprocessor/seq/transform.hpp>
23
24#include <boost/compute/type_traits/type_definition.hpp>
25#include <boost/compute/type_traits/type_name.hpp>
26#include <boost/compute/detail/meta_kernel.hpp>
27#include <boost/compute/detail/variadic_macros.hpp>
28
29namespace boost {
30namespace compute {
31namespace detail {
32
33template<class Struct, class T>
34inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
35{
36 std::stringstream s;
37 s << " " << type_name<T>() << " " << name << ";\n";
38 return s.str();
39}
40
41
42template<class Struct, class T, int N>
43inline std::string adapt_struct_insert_member(T (Struct::*)[N], const char *name)
44{
45 std::stringstream s;
46 s << " " << type_name<T>() << " " << name << "[" << N << "]" << ";\n";
47 return s.str();
48}
49
50} // end detail namespace
51} // end compute namespace
52} // end boost namespace
53
54/// \internal_
55#define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER(r, type, member) \
56 << ::boost::compute::detail::adapt_struct_insert_member( \
57 &type::member, BOOST_PP_STRINGIZE(member) \
58 )
59
60/// \internal_
61#define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER(r, data, i, elem) \
62 BOOST_PP_EXPR_IF(i, << ", ") << data.elem
63
64/// \internal_
65#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE(s, struct_, member_) \
66 sizeof(((struct_ *)0)->member_)
67
68/// \internal_
69#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD(s, x, y) (x+y)
70
71/// \internal_
72#define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_) \
73 BOOST_PP_SEQ_FOLD_LEFT( \
74 BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD, \
75 0, \
76 BOOST_PP_SEQ_TRANSFORM( \
77 BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE, struct_, members_ \
78 ) \
79 )
80
81/// \internal_
82///
83/// Returns true if struct_ contains no internal padding bytes (i.e. it is
84/// packed). members_ is a sequence of the names of the struct members.
85#define BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(struct_, members_) \
86 (sizeof(struct_) == BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_))
87
88/// The BOOST_COMPUTE_ADAPT_STRUCT() macro makes a C++ struct/class available
89/// to OpenCL kernels.
90///
91/// \param type The C++ type.
92/// \param name The OpenCL name.
93/// \param members A tuple of the struct's members.
94///
95/// For example, to adapt a 2D particle struct with position (x, y) and
96/// velocity (dx, dy):
97/// \code
98/// // c++ struct definition
99/// struct Particle
100/// {
101/// float x, y;
102/// float dx, dy;
103/// };
104///
105/// // adapt struct for OpenCL
106/// BOOST_COMPUTE_ADAPT_STRUCT(Particle, Particle, (x, y, dx, dy))
107/// \endcode
108///
109/// After adapting the struct it can be used in Boost.Compute containers
110/// and with Boost.Compute algorithms:
111/// \code
112/// // create vector of particles
113/// boost::compute::vector<Particle> particles = ...
114///
115/// // function to compare particles by their x-coordinate
116/// BOOST_COMPUTE_FUNCTION(bool, sort_by_x, (Particle a, Particle b),
117/// {
118/// return a.x < b.x;
119/// });
120///
121/// // sort particles by their x-coordinate
122/// boost::compute::sort(
123/// particles.begin(), particles.end(), sort_by_x, queue
124/// );
125/// \endcode
126///
127/// Due to differences in struct padding between the host compiler and the
128/// device compiler, the \c BOOST_COMPUTE_ADAPT_STRUCT() macro requires that
129/// the adapted struct is packed (i.e. no padding bytes between members).
130///
131/// \see type_name()
132#define BOOST_COMPUTE_ADAPT_STRUCT(type, name, members) \
133 BOOST_STATIC_ASSERT_MSG( \
134 BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(type, BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members)), \
135 "BOOST_COMPUTE_ADAPT_STRUCT() does not support structs with internal padding." \
136 ); \
137 BOOST_COMPUTE_TYPE_NAME(type, name) \
138 namespace boost { namespace compute { \
139 template<> \
140 inline std::string type_definition<type>() \
141 { \
142 std::stringstream declaration; \
143 declaration << "typedef struct __attribute__((packed)) {\n" \
144 BOOST_PP_SEQ_FOR_EACH( \
145 BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER, \
146 type, \
147 BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
148 ) \
149 << "} " << type_name<type>() << ";\n"; \
150 return declaration.str(); \
151 } \
152 namespace detail { \
153 template<> \
154 struct inject_type_impl<type> \
155 { \
156 void operator()(meta_kernel &kernel) \
157 { \
158 kernel.add_type_declaration<type>(type_definition<type>()); \
159 } \
160 }; \
161 inline meta_kernel& operator<<(meta_kernel &k, type s) \
162 { \
163 return k << "(" << #name << "){" \
164 BOOST_PP_SEQ_FOR_EACH_I( \
165 BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER, \
166 s, \
167 BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
168 ) \
169 << "}"; \
170 } \
171 }}}
172
173#endif // BOOST_COMPUTE_TYPES_STRUCT_HPP