1/*
2 * aggregate_copy.hpp
3 *
4 * Created on: Oct 31, 2015
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_UTIL_COPY_GENERAL_HPP_
9#define OPENFPM_DATA_SRC_UTIL_COPY_GENERAL_HPP_
10
11#include "util/common.hpp"
12#include "util/util_debug.hpp"
13#include "copy_compare_aggregates.hpp"
14#include "util/for_each_ref.hpp"
15#include <boost/mpl/range_c.hpp>
16#include <iostream>
17#include "util/cuda_util.hpp"
18#include "data_type/aggregate.hpp"
19
20/*! \brief This structure define the operation add to use with copy general
21 *
22 * \tparam Tdst destination object type
23 * \tparam Tsrc source object type
24 *
25 */
26template<typename Tdst, typename Tsrc>
27struct max_
28{
29 /*! \brief Defition of the add operation
30 *
31 * \param dst Destination object
32 * \param src Source object
33 *
34 */
35 static inline void operation(Tdst & dst, const Tsrc & src)
36 {
37 dst = (src > dst)?src:dst;
38 }
39};
40
41/*! \brief This structure define the operation add to use with copy general
42 *
43 * \tparam Tdst destination object type
44 * \tparam Tsrc source object type
45 *
46 */
47template<typename Tdst, typename Tsrc>
48struct min_
49{
50 /*! \brief Defition of the add operation
51 *
52 * \param dst Destination object
53 * \param src Source object
54 *
55 */
56 static inline void operation(Tdst & dst, const Tsrc & src)
57 {
58 dst = (src < dst)?src:dst;
59 }
60};
61
62/*! \brief This structure define the operation add to use with copy general
63 *
64 * \tparam Tdst destination object type
65 * \tparam Tsrc source object type
66 *
67 */
68template<typename Tdst, typename Tsrc>
69struct add_
70{
71 /*! \brief Defition of the add operation
72 *
73 * \param dst Destination object
74 * \param src Source object
75 *
76 */
77 __device__ __host__ static inline void operation(Tdst & dst, const Tsrc & src)
78 {
79 dst += src;
80 }
81};
82
83#ifdef __clang__
84template<typename Tsrc>
85__host__ Tsrc atomicAdd(Tsrc * ptr, Tsrc value)
86{
87 std::cout << __FILE__ << ":" << __LINE__ << "Error: atomicAdd is supported only in device code not host" << std::endl;
88 return 0;
89}
90#endif
91
92/*! \brief This structure define the operation add to use with copy general
93 *
94 * \tparam Tdst destination object type
95 * \tparam Tsrc source object type
96 *
97 */
98template<typename Tdst, typename Tsrc>
99struct add_atomic_
100{
101 /*! \brief Defition of the add operation
102 *
103 * \param dst Destination object
104 * \param src Source object
105 *
106 */
107 __device__ __host__ static inline void operation(Tdst & dst, const Tsrc & src)
108 {
109 atomicAdd(&dst,src);
110 }
111};
112
113/*! \brief This structure define the operation add to use with copy general
114 *
115 * \tparam Tdst destination object type
116 * \tparam Tsrc source object type
117 *
118 */
119template<typename Tdst, typename Tsrc>
120struct replace_
121{
122 /*! \brief Defition of the replace operation
123 *
124 * \param dst Destination object
125 * \param src Source object
126 *
127 */
128 static inline void operation(Tdst & dst, const Tsrc & src)
129 {
130 dst = src;
131 }
132};
133
134/*! \brief This structure define the operation add to use with copy general
135 *
136 * \tparam Tdst destination object type
137 * \tparam Tsrc source object type
138 *
139 */
140template<typename Tdst, typename Tsrc>
141struct merge_
142{
143 /*! \brief Defition of the add operation
144 *
145 * \param dst Destination object
146 * \param src Source object
147 *
148 */
149 static inline void operation(Tdst & dst, const Tsrc & src)
150 {
151 dst.add(src);
152 }
153};
154
155/*! \brief structure to copy aggregates
156 *
157 * \tparam T type to copy
158 *
159 */
160template<typename T, unsigned int agg=2 * is_aggregate<T>::value + std::is_copy_assignable<T>::value>
161struct copy_general
162{
163 /*! \brief Specialization when there is unknown copy method
164 *
165 * \param src source object to copy
166 * \param dst destination object
167 *
168 */
169 inline copy_general(const T & src, T & dst)
170 {
171#ifndef DISABLE_ALL_RTTI
172 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " " << demangle(typeid(T).name()) << " does not have an operator= and is not an aggregate or an openfpm native structure, copy is not possible" << "\n";
173#endif
174 }
175};
176
177//! Specialization for if dst type is copy assignable from src type
178template<typename T>
179struct copy_general<T,1>
180{
181 /*! \brief copy objects that has an operator= (implicit or explicit)
182 *
183 * \param src source object to copy
184 * \param dst destination object
185 *
186 */
187 __device__ __host__ inline copy_general(const T & src, T & dst)
188 {
189 dst = src;
190 }
191};
192
193//! Specialization for aggregate type object
194template<typename T>
195struct copy_general<T,2>
196{
197 /*! \brief copy objects that are aggregates
198 *
199 * \param src source object to copy
200 * \param dst destination object
201 *
202 */
203 inline copy_general(const T & src, T & dst)
204 {
205 copy_aggregate<T> cp(src,dst);
206
207 boost::mpl::for_each_ref<boost::mpl::range_c<int,0,T::max_prop>>(cp);
208 }
209};
210
211//! Specialization for aggregate type object that define an operator=
212template<typename T>
213struct copy_general<T,3>
214{
215 /*! \brief copy objects that are aggregates but define an operator=
216 *
217 * \param src source object to copy
218 * \param dst destination object
219 *
220 */
221 inline copy_general(const T & src, T & dst)
222 {
223 dst = src;
224 }
225};
226
227/////////////////// VERSION WITH OPERATIONS ///////////////////
228
229/*! \brief structure to copy aggregates applying an operation
230 *
231 * \tparam T type to copy
232 *
233 */
234template<template<typename,typename> class op, typename T, unsigned int agg=2 * is_aggregate<T>::value + std::is_copy_assignable<T>::value>
235struct copy_general_op
236{
237 /*! \brief Specialization when there is unknown copy method
238 *
239 * \param src source object to copy
240 * \param dst destination object
241 *
242 */
243 inline copy_general_op(const T & src, T & dst)
244 {
245#ifndef DISABLE_ALL_RTTI
246 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " " << demangle(typeid(T).name()) << " does not have an operator " << demangle(typeid(op<T,T>).name()) << "defined" << std::endl;
247#endif
248 }
249};
250
251//! Specialization for object that can be assigned with an operator copy
252template<template<typename,typename> class op,typename T>
253struct copy_general_op<op,T,1>
254{
255 /*! \brief copy objects that has an operator= (implicit or explicit)
256 *
257 * \param src source object to copy
258 * \param dst destination object
259 *
260 */
261 __device__ __host__ inline copy_general_op(const T & src, T & dst)
262 {
263 op<T,T>::operation(dst,src);
264 }
265};
266
267//! Specialization for aggregate type objects
268template<template<typename,typename> class op, typename T>
269struct copy_general_op<op,T,3>
270{
271 /*! \brief copy objects that are aggregates
272 *
273 * \param src source object to copy
274 * \param dst destination object
275 *
276 */
277 __device__ __host__ inline copy_general_op(const T & src, T & dst)
278 {
279 copy_aggregate_op<op,T> cp(src,dst);
280
281 boost::mpl::for_each_ref<boost::mpl::range_c<int,0,T::max_prop>>(cp);
282 }
283};
284
285
286#endif /* OPENFPM_DATA_SRC_UTIL_COPY_GENERAL_HPP_ */
287