1/*
2 * Point_operators_functions.hpp
3 *
4 * Created on: Jun 20, 2016
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_SPACE_SHAPE_POINT_OPERATORS_FUNCTIONS_HPP_
9#define OPENFPM_DATA_SRC_SPACE_SHAPE_POINT_OPERATORS_FUNCTIONS_HPP_
10
11#define CREATE_ARG_FUNC_CLASS(fun_base,fun_name,OP_ID) \
12\
13template <typename orig, typename exp1, typename exp2>\
14class point_expression_op<orig,exp1,exp2, OP_ID >\
15{\
16 const exp1 o1;\
17\
18 mutable typename std::remove_const<typename orig::coord_type>::type scal;\
19\
20public:\
21\
22 typedef orig orig_type;\
23\
24 typedef int is_expression;\
25\
26 typedef int has_init;\
27\
28 typedef typename orig::coord_type return_type;\
29\
30 static const unsigned int nvals = exp1::nvals;\
31\
32 __device__ __host__ inline explicit point_expression_op(const exp1 & o1)\
33 :o1(o1),scal(0)\
34 {}\
35\
36 __device__ __host__ inline void init() const\
37 {\
38 o1.init();\
39 }\
40\
41 template<typename r_type=typename std::remove_reference<decltype(o1.value(0))>::type > __device__ __host__ inline r_type value(size_t k) const\
42 {\
43 return fun_base(o1.value(k));\
44 }\
45\
46 template <typename T> __device__ __host__ operator T() const\
47 {\
48 init();\
49 return fun_base(o1.value(0));\
50 }\
51};
52
53/*! A macro to define single value function specialization that apply the function component-wise
54 *
55 * \param fun function name
56 * \param ID function ID
57 *
58 */
59#define CREATE_ARG_FUNC(fun_base,fun_name,OP_ID) \
60\
61template<typename orig,typename exp1, typename exp_2, unsigned int op1>\
62__device__ __host__ inline point_expression_op<orig,point_expression_op<orig,exp1,exp_2,op1>,void, OP_ID >\
63fun_name(const point_expression_op<orig,exp1,exp_2,op1> & va)\
64{\
65 point_expression_op<orig,point_expression_op<orig,exp1,exp_2,op1>,void,OP_ID> exp_sum(va);\
66\
67 return exp_sum;\
68}\
69\
70\
71template<unsigned int dim, typename T>\
72__device__ __host__ inline point_expression_op<Point<dim,T>,Point<dim,T>,void, OP_ID >\
73fun_name(const Point<dim,T> & va)\
74{\
75 point_expression_op<Point<dim,T>,Point<dim,T>,void,OP_ID> exp_sum(va);\
76\
77 return exp_sum;\
78}
79
80
81/*! \brief Point norm operation
82 *
83 * \tparam orig original type
84 * \tparam exp1 expression1
85 * \tparam exp2 expression2
86 * \tparam op operation
87 *
88 */
89template <typename orig, typename exp1, typename exp2>
90class point_expression_op<orig,exp1,exp2,POINT_NORM>
91{
92 const exp1 o1;
93
94 //! Scalar value
95 mutable typename std::remove_const<typename orig::coord_type>::type scal;
96
97public:
98
99 //! Origin type
100 typedef orig orig_type;
101
102 //! indicate that this class encapsulate an expression
103 typedef int is_expression;
104
105 //! indicate that init must be called before value
106 typedef int has_init;
107
108 //! return type of the expression
109 typedef typename orig::coord_type return_type;
110
111 //! this operation produce a scalar as result
112 static const unsigned int nvals = 1;
113
114 //! Constructor from expression
115 __device__ __host__ inline explicit point_expression_op(const exp1 & o1)
116 :o1(o1),scal(0.0)
117 {}
118
119 /*! \brief This function must be called before value
120 *
121 * it calculate the scalar product before return the values
122 *
123 */
124 __device__ __host__ inline void init() const
125 {
126 scal = 0.0;
127
128 for (size_t i = 0 ; i < orig::dims ; i++)
129 scal += o1.value(i) * o1.value(i);
130
131 scal = sqrt(scal);
132
133 o1.init();
134 }
135
136 /*! \brief Evaluate the expression
137 *
138 * \param key where to evaluate the expression
139 *
140 */
141 template<typename r_type=typename std::remove_reference<decltype(o1.value(0))>::type > __device__ __host__ inline r_type value(size_t k) const
142 {
143 return scal;
144 }
145
146 template <typename T>__device__ __host__ operator T() const
147 {
148 init();
149 return scal;
150 }
151};
152
153/*! \brief Point square norm operation
154 *
155 * \tparam orig original type
156 * \tparam exp1 expression1
157 * \tparam exp2 expression2
158 * \tparam op operation
159 *
160 */
161template <typename orig, typename exp1, typename exp2>
162class point_expression_op<orig,exp1,exp2,POINT_NORM2>
163{
164 //! expression
165 const exp1 o1;
166
167 //! result of the expression
168 mutable typename std::remove_const<typename orig::coord_type>::type scal;
169
170public:
171
172 typedef orig orig_type;
173
174 //! indicate that init must be called before value
175 typedef int has_init;
176
177 //! indicate that this class encapsulate an expression
178 typedef int is_expression;
179
180 //! return type of the expression
181 typedef typename orig::coord_type return_type;
182
183 //! this operation produce a vector as result of size dims
184 static const unsigned int nvals = 1;
185
186 //! constructor from an expression
187 __device__ __host__ inline explicit point_expression_op(const exp1 & o1)
188 :o1(o1),scal(0.0)
189 {}
190
191 /*! \brief This function must be called before value
192 *
193 * it calculate the scalar product before return the values
194 *
195 */
196 __device__ __host__ inline void init() const
197 {
198 scal = 0.0;
199
200 for (size_t i = 0 ; i < orig::dims ; i++)
201 scal += o1.value(i) * o1.value(i);
202
203 o1.init();
204 }
205
206 /*! \brief Evaluate the expression
207 *
208 * \param key where to evaluate the expression
209 *
210 */
211 template<typename r_type=typename std::remove_reference<decltype(o1.value(0))>::type > __device__ __host__ inline r_type value(size_t k) const
212 {
213 return scal;
214 }
215
216 //! Cast operator
217 template <typename T> __device__ __host__ operator T() const
218 {
219 init();
220 return scal;
221 }
222};
223
224
225CREATE_ARG_FUNC_CLASS(std::abs,abs,POINT_ABS)
226CREATE_ARG_FUNC_CLASS(std::exp,exp,POINT_EXP)
227CREATE_ARG_FUNC_CLASS(std::exp2,exp2,POINT_EXP2)
228CREATE_ARG_FUNC_CLASS(std::expm1,expm1,POINT_EXPM1)
229CREATE_ARG_FUNC_CLASS(std::log,log,POINT_LOG)
230CREATE_ARG_FUNC_CLASS(std::log10,log10,POINT_LOG10)
231CREATE_ARG_FUNC_CLASS(std::log2,log2,POINT_LOG2)
232CREATE_ARG_FUNC_CLASS(std::log1p,log1p,POINT_LOG1P)
233CREATE_ARG_FUNC_CLASS(std::sqrt,sqrt,POINT_SQRT)
234CREATE_ARG_FUNC_CLASS(std::cbrt,cbrt,POINT_CBRT)
235CREATE_ARG_FUNC_CLASS(std::sin,sin,POINT_SIN)
236CREATE_ARG_FUNC_CLASS(std::cos,cos,POINT_COS)
237CREATE_ARG_FUNC_CLASS(std::tan,tan,POINT_TAN)
238CREATE_ARG_FUNC_CLASS(std::asin,asin,POINT_ASIN)
239CREATE_ARG_FUNC_CLASS(std::acos,acos,POINT_ACOS)
240CREATE_ARG_FUNC_CLASS(std::atan,atan,POINT_ATAN)
241CREATE_ARG_FUNC_CLASS(std::sinh,sinh,POINT_SINH)
242CREATE_ARG_FUNC_CLASS(std::cosh,cosh,POINT_COSH)
243CREATE_ARG_FUNC_CLASS(std::tanh,tanh,POINT_TANH)
244CREATE_ARG_FUNC_CLASS(std::asinh,asinh,POINT_ASINH)
245CREATE_ARG_FUNC_CLASS(std::acosh,acosh,POINT_ACOSH)
246CREATE_ARG_FUNC_CLASS(std::atanh,atanh,POINT_ATANH)
247CREATE_ARG_FUNC_CLASS(std::erf,erf,POINT_ERF)
248CREATE_ARG_FUNC_CLASS(std::erfc,erfc,POINT_ERFC)
249CREATE_ARG_FUNC_CLASS(std::tgamma,tgamma,POINT_TGAMMA)
250CREATE_ARG_FUNC_CLASS(std::lgamma,lgamma,POINT_LGAMMA)
251CREATE_ARG_FUNC_CLASS(std::ceil,ceil,POINT_CEIL)
252CREATE_ARG_FUNC_CLASS(std::floor,floor,POINT_FLOOR)
253CREATE_ARG_FUNC_CLASS(std::trunc,trunc,POINT_TRUNC)
254CREATE_ARG_FUNC_CLASS(std::round,round,POINT_ROUND)
255CREATE_ARG_FUNC_CLASS(std::nearbyint,nearbyint,POINT_NEARBYINT)
256CREATE_ARG_FUNC_CLASS(std::rint,rint,POINT_RINT)
257
258/////// norm operation
259
260/* \brief Calculate the norm of the point
261 *
262 * \param va point expression one
263 *
264 * \return an object that encapsulate the expression
265 *
266 */
267template<typename orig,typename exp1, typename exp2, unsigned int op1>
268__device__ __host__ inline point_expression_op<orig,point_expression_op<orig,exp1,exp2,op1>,void,POINT_NORM>
269norm(const point_expression_op<orig,exp1,exp2,op1> & va)
270{
271 point_expression_op<orig,point_expression_op<orig,exp1,exp2,op1>,void,POINT_NORM> exp_sum(va);
272
273 return exp_sum;
274}
275
276
277/* \brief norm of a scalar
278 *
279 * \param d scalar double or float
280 *
281 * \return d
282 *
283 */
284template <typename T>
285__device__ __host__ T norm(T d)
286{
287 return d;
288}
289
290/* \brief Calculate the norm of the point
291 *
292 * \param va point expression one
293 *
294 * \return an object that encapsulate the expression
295 *
296 */
297template<typename T, typename vmpl>
298__device__ __host__ inline point_expression_op<Point<subar_dim<vmpl>::type::value,T>,
299 point_expression<openfpm::detail::multi_array::sub_array_openfpm<T,1,vmpl>>,
300 void,
301 POINT_NORM>
302norm(const point_expression<openfpm::detail::multi_array::sub_array_openfpm<T,1,vmpl>> & d)
303{
304 point_expression_op<Point<subar_dim<vmpl>::type::value,T>,
305 point_expression<openfpm::detail::multi_array::sub_array_openfpm<T,1,vmpl>>,
306 void,
307 POINT_NORM> exp_sum( (point_expression<openfpm::detail::multi_array::sub_array_openfpm<T,1,vmpl>>(d)) );
308
309 return exp_sum;
310}
311
312/* \brief Calculate the norm of the point
313 *
314 * \param va point expression one
315 *
316 * \return an object that encapsulate the expression
317 *
318 */
319template<unsigned int dim, typename T>
320__device__ __host__ inline point_expression_op<Point<dim,T>,point_expression<T[dim]>,void,POINT_NORM>
321norm(const point_expression<T[dim]> & d)
322{
323 point_expression_op<Point<dim,T>,point_expression<T[dim]>,void,POINT_NORM> exp_sum( (point_expression<T[dim]>(d)) );
324
325 return exp_sum;
326}
327
328
329/* \brief Divide two points expression
330 *
331 * \param va point expression one
332 * \param vb point expression two
333 *
334 * \return an object that encapsulate the expression
335 *
336 */
337template<unsigned int dim, typename T>
338__device__ __host__ inline point_expression_op<Point<dim,T>,Point<dim,T>,void,POINT_NORM>
339norm(const Point<dim,T> & va)
340{
341 point_expression_op<Point<dim,T>,Point<dim,T>,void,POINT_NORM> exp_sum(va);
342
343 return exp_sum;
344}
345
346
347//////////////////////////////////////// norm2 operation //////////////////
348
349/* \brief Calculate the norm of the point
350 *
351 * \param va point expression one
352 *
353 * \return an object that encapsulate the expression
354 *
355 */
356template<typename orig,typename exp1, typename exp2, unsigned int op1>
357__device__ __host__ inline point_expression_op<orig,point_expression_op<orig,exp1,exp2,op1>,void,POINT_NORM2>
358norm2(const point_expression_op<orig,exp1,exp2,op1> & va)
359{
360 point_expression_op<orig,point_expression_op<orig,exp1,exp2,op1>,void,POINT_NORM2> exp_sum(va);
361
362 return exp_sum;
363}
364
365
366/* \brief norm of a scalar
367 *
368 * \param d scalar double or float
369 *
370 * \return d
371 *
372 */
373template <typename T>__device__ __host__ T norm2(T d)
374{
375 return d*d;
376}
377
378
379/* \brief Calculate the norm of the point
380 *
381 * \param va point expression one
382 *
383 * \return an object that encapsulate the expression
384 *
385 */
386template<unsigned int dim, typename T>
387__device__ __host__ inline point_expression_op<Point<dim,T>,point_expression<T[dim]>,void,POINT_NORM2>
388norm2(const point_expression<T[dim]> & d)
389{
390 point_expression_op<Point<dim,T>,point_expression<T[dim]>,void,POINT_NORM2> exp_sum( (point_expression<T[dim]>(d)) );
391
392 return exp_sum;
393}
394
395
396/* \brief Divide two points expression
397 *
398 * \param va point expression one
399 * \param vb point expression two
400 *
401 * \return an object that encapsulate the expression
402 *
403 */
404template<unsigned int dim, typename T>
405__device__ __host__ inline point_expression_op<Point<dim,T>,Point<dim,T>,void,POINT_NORM2>
406norm2(const Point<dim,T> & va)
407{
408 point_expression_op<Point<dim,T>,Point<dim,T>,void,POINT_NORM2> exp_sum(va);
409
410 return exp_sum;
411}
412
413
414/*! \brief General distance formula
415 *
416 *
417 */
418template <typename T, typename P> __device__ __host__ auto distance(T exp1, P exp2) -> decltype(norm(exp1 - exp2))
419{
420 return norm(exp1 - exp2);
421}
422
423
424///// Here we define point operator functions
425
426CREATE_ARG_FUNC(std::abs,abs,POINT_ABS)
427CREATE_ARG_FUNC(std::exp,exp,POINT_EXP)
428CREATE_ARG_FUNC(std::exp2,exp2,POINT_EXP2)
429CREATE_ARG_FUNC(std::expm1,expm1,POINT_EXPM1)
430CREATE_ARG_FUNC(std::log,log,POINT_LOG)
431CREATE_ARG_FUNC(std::log10,log10,POINT_LOG10)
432CREATE_ARG_FUNC(std::log2,log2,POINT_LOG2)
433CREATE_ARG_FUNC(std::log1p,log1p,POINT_LOG1P)
434CREATE_ARG_FUNC(std::sqrt,sqrt,POINT_SQRT)
435CREATE_ARG_FUNC(std::cbrt,cbrt,POINT_CBRT)
436CREATE_ARG_FUNC(std::sin,sin,POINT_SIN)
437CREATE_ARG_FUNC(std::cos,cos,POINT_COS)
438CREATE_ARG_FUNC(std::tan,tan,POINT_TAN)
439CREATE_ARG_FUNC(std::asin,asin,POINT_ASIN)
440CREATE_ARG_FUNC(std::acos,acos,POINT_ACOS)
441CREATE_ARG_FUNC(std::atan,atan,POINT_ATAN)
442CREATE_ARG_FUNC(std::sinh,sinh,POINT_SINH)
443CREATE_ARG_FUNC(std::cosh,cosh,POINT_COSH)
444CREATE_ARG_FUNC(std::tanh,tanh,POINT_TANH)
445CREATE_ARG_FUNC(std::asinh,asinh,POINT_ASINH)
446CREATE_ARG_FUNC(std::acosh,acosh,POINT_ACOSH)
447CREATE_ARG_FUNC(std::atanh,atanh,POINT_ATANH)
448CREATE_ARG_FUNC(std::erf,erf,POINT_ERF)
449CREATE_ARG_FUNC(std::erfc,erfc,POINT_ERFC)
450CREATE_ARG_FUNC(std::tgamma,tgamma,POINT_TGAMMA)
451CREATE_ARG_FUNC(std::lgamma,lgamma,POINT_LGAMMA)
452CREATE_ARG_FUNC(std::ceil,ceil,POINT_CEIL)
453CREATE_ARG_FUNC(std::floor,floor,POINT_FLOOR)
454CREATE_ARG_FUNC(std::trunc,trunc,POINT_TRUNC)
455CREATE_ARG_FUNC(std::round,round,POINT_ROUND)
456CREATE_ARG_FUNC(std::nearbyint,nearbyint,POINT_NEARBYINT)
457CREATE_ARG_FUNC(std::rint,rint,POINT_RINT)
458
459
460#endif /* OPENFPM_DATA_SRC_SPACE_SHAPE_POINT_OPERATORS_FUNCTIONS_HPP_ */
461