Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:04

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
0009 //---------------------------------------------------------------------------//
0010 
0011 #ifndef BOOST_COMPUTE_TYPES_STRUCT_HPP
0012 #define BOOST_COMPUTE_TYPES_STRUCT_HPP
0013 
0014 #include <sstream>
0015 
0016 #include <boost/static_assert.hpp>
0017 
0018 #include <boost/preprocessor/expr_if.hpp>
0019 #include <boost/preprocessor/stringize.hpp>
0020 #include <boost/preprocessor/seq/fold_left.hpp>
0021 #include <boost/preprocessor/seq/for_each.hpp>
0022 #include <boost/preprocessor/seq/transform.hpp>
0023 
0024 #include <boost/compute/type_traits/type_definition.hpp>
0025 #include <boost/compute/type_traits/type_name.hpp>
0026 #include <boost/compute/detail/meta_kernel.hpp>
0027 #include <boost/compute/detail/variadic_macros.hpp>
0028 
0029 namespace boost {
0030 namespace compute {
0031 namespace detail {
0032 
0033 template<class Struct, class T>
0034 inline std::string adapt_struct_insert_member(T Struct::*, const char *name)
0035 {
0036     std::stringstream s;
0037     s << "    " << type_name<T>() << " " << name << ";\n";
0038     return s.str();
0039 }
0040 
0041 
0042 template<class Struct, class T, int N>
0043 inline std::string adapt_struct_insert_member(T (Struct::*)[N], const char *name)
0044 {
0045     std::stringstream s;
0046     s << "    " << type_name<T>() << " " << name << "[" << N << "]" << ";\n";
0047     return s.str();
0048 }
0049 
0050 } // end detail namespace
0051 } // end compute namespace
0052 } // end boost namespace
0053 
0054 /// \internal_
0055 #define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER(r, type, member) \
0056     << ::boost::compute::detail::adapt_struct_insert_member( \
0057            &type::member, BOOST_PP_STRINGIZE(member) \
0058        )
0059 
0060 /// \internal_
0061 #define BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER(r, data, i, elem) \
0062     BOOST_PP_EXPR_IF(i, << ", ") << data.elem
0063 
0064 /// \internal_
0065 #define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE(s, struct_, member_) \
0066     sizeof(((struct_ *)0)->member_)
0067 
0068 /// \internal_
0069 #define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD(s, x, y) (x+y)
0070 
0071 /// \internal_
0072 #define BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_) \
0073     BOOST_PP_SEQ_FOLD_LEFT( \
0074         BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_ADD, \
0075         0, \
0076         BOOST_PP_SEQ_TRANSFORM( \
0077             BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE, struct_, members_ \
0078         ) \
0079     )
0080 
0081 /// \internal_
0082 ///
0083 /// Returns true if struct_ contains no internal padding bytes (i.e. it is
0084 /// packed). members_ is a sequence of the names of the struct members.
0085 #define BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(struct_, members_) \
0086     (sizeof(struct_) == BOOST_COMPUTE_DETAIL_STRUCT_MEMBER_SIZE_SUM(struct_, members_))
0087 
0088 /// The BOOST_COMPUTE_ADAPT_STRUCT() macro makes a C++ struct/class available
0089 /// to OpenCL kernels.
0090 ///
0091 /// \param type The C++ type.
0092 /// \param name The OpenCL name.
0093 /// \param members A tuple of the struct's members.
0094 ///
0095 /// For example, to adapt a 2D particle struct with position (x, y) and
0096 /// velocity (dx, dy):
0097 /// \code
0098 /// // c++ struct definition
0099 /// struct Particle
0100 /// {
0101 ///     float x, y;
0102 ///     float dx, dy;
0103 /// };
0104 ///
0105 /// // adapt struct for OpenCL
0106 /// BOOST_COMPUTE_ADAPT_STRUCT(Particle, Particle, (x, y, dx, dy))
0107 /// \endcode
0108 ///
0109 /// After adapting the struct it can be used in Boost.Compute containers
0110 /// and with Boost.Compute algorithms:
0111 /// \code
0112 /// // create vector of particles
0113 /// boost::compute::vector<Particle> particles = ...
0114 ///
0115 /// // function to compare particles by their x-coordinate
0116 /// BOOST_COMPUTE_FUNCTION(bool, sort_by_x, (Particle a, Particle b),
0117 /// {
0118 ///     return a.x < b.x;
0119 /// });
0120 ///
0121 /// // sort particles by their x-coordinate
0122 /// boost::compute::sort(
0123 ///     particles.begin(), particles.end(), sort_by_x, queue
0124 /// );
0125 /// \endcode
0126 ///
0127 /// Due to differences in struct padding between the host compiler and the
0128 /// device compiler, the \c BOOST_COMPUTE_ADAPT_STRUCT() macro requires that
0129 /// the adapted struct is packed (i.e. no padding bytes between members).
0130 ///
0131 /// \see type_name()
0132 #define BOOST_COMPUTE_ADAPT_STRUCT(type, name, members) \
0133     BOOST_STATIC_ASSERT_MSG( \
0134         BOOST_COMPUTE_DETAIL_STRUCT_IS_PACKED(type, BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members)), \
0135         "BOOST_COMPUTE_ADAPT_STRUCT() does not support structs with internal padding." \
0136     ); \
0137     BOOST_COMPUTE_TYPE_NAME(type, name) \
0138     namespace boost { namespace compute { \
0139     template<> \
0140     inline std::string type_definition<type>() \
0141     { \
0142         std::stringstream declaration; \
0143         declaration << "typedef struct __attribute__((packed)) {\n" \
0144                     BOOST_PP_SEQ_FOR_EACH( \
0145                         BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_INSERT_MEMBER, \
0146                         type, \
0147                         BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
0148                     ) \
0149                     << "} " << type_name<type>() << ";\n"; \
0150         return declaration.str(); \
0151     } \
0152     namespace detail { \
0153     template<> \
0154     struct inject_type_impl<type> \
0155     { \
0156         void operator()(meta_kernel &kernel) \
0157         { \
0158             kernel.add_type_declaration<type>(type_definition<type>()); \
0159         } \
0160     }; \
0161     inline meta_kernel& operator<<(meta_kernel &k, type s) \
0162     { \
0163         return k << "(" << #name << "){" \
0164                BOOST_PP_SEQ_FOR_EACH_I( \
0165                    BOOST_COMPUTE_DETAIL_ADAPT_STRUCT_STREAM_MEMBER, \
0166                    s, \
0167                    BOOST_COMPUTE_PP_TUPLE_TO_SEQ(members) \
0168                ) \
0169                << "}"; \
0170     } \
0171     }}}
0172 
0173 #endif // BOOST_COMPUTE_TYPES_STRUCT_HPP