traits.hpp
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief Traits of matrix expressions
6  *
7  * \author O. Krause
8  * \date 2013
9  *
10  *
11  * \par Copyright 1995-2015 Shark Development Team
12  *
13  * <BR><HR>
14  * This file is part of Shark.
15  * <http://image.diku.dk/shark/>
16  *
17  * Shark is free software: you can redistribute it and/or modify
18  * it under the terms of the GNU Lesser General Public License as published
19  * by the Free Software Foundation, either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * Shark is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public License
28  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
29  *
30  */
31 //===========================================================================
32 
33 #ifndef REMORA_CPU_TRAITS_HPP
34 #define REMORA_CPU_TRAITS_HPP
35 
36 #include "../expression_types.hpp"
37 #include "iterator.hpp"
38 #include <cmath>
39 
40 namespace remora{
41 
42 template<class Device>
43 struct device_traits;
44 
45 template<>
46 struct device_traits<cpu_tag>{
47  //queue (not used on cpu)
48  struct queue_type{};
49 
50  static queue_type& default_queue(){
51  static queue_type queue;
52  return queue;
53  }
54 
55  //adding of indices
56  static std::size_t index_add(std::size_t i, std::size_t j){
57  return i+j;
58  }
59 
60  template<class E>
61  static typename E::reference linearized_matrix_element(matrix_expression<E, cpu_tag> const& e, std::size_t i){
62  std::size_t leading_dimension = E::orientation::index_m(e().size1(), e().size2());
63  std::size_t i1 = i / leading_dimension;
64  std::size_t i2 = i % leading_dimension;
65  return e()(E::orientation::index_M(i1,i2), E::orientation::index_m(i1,i2));
66  }
67 
68  template <class Iterator, class Functor>
69  struct transform_iterator{
70  typedef iterators::transform_iterator<Iterator, Functor> type;
71  };
72 
73  template <class Iterator>
74  struct subrange_iterator{
75  typedef iterators::subrange_iterator<Iterator> type;
76  };
77 
78  template <class Iterator1, class Iterator2, class Functor>
79  struct binary_transform_iterator{
80  typedef iterators::binary_transform_iterator<Iterator1,Iterator2, Functor> type;
81  };
82 
83  template<class T>
84  struct constant_iterator{
85  typedef iterators::constant_iterator<T> type;
86  };
87 
88  template<class T>
89  struct one_hot_iterator{
90  typedef iterators::one_hot_iterator<T> type;
91  };
92 
93  template<class Closure>
94  struct indexed_iterator{
95  typedef iterators::indexed_iterator<Closure> type;
96  };
97 
98  //functors
99  template<class T>
100  struct add {
101  static const bool left_zero_remains = false;
102  static const bool right_zero_remains = false;
103  static const bool right_zero_identity = true;
104  static const bool left_zero_identity = false;
105  typedef T result_type;
106  T operator()(T x, T y)const{
107  return x+y;
108  }
109  };
110  template<class T>
111  struct subtract {
112  static const bool left_zero_remains = false;
113  static const bool right_zero_remains = false;
114  static const bool right_zero_identity = true;
115  static const bool left_zero_identity = false;
116  typedef T result_type;
117  T operator()(T x, T y)const{
118  return x-y;
119  }
120  };
121 
122  template<class T>
123  struct multiply {
124  static const bool left_zero_remains = true;
125  static const bool right_zero_remains = true;
126  static const bool right_zero_identity = false;
127  static const bool left_zero_identity = true;
128  typedef T result_type;
129  T operator()(T x, T y)const{
130  return x*y;
131  }
132  };
133 
134  template<class T>
135  struct divide {
136  static const bool left_zero_remains = true;
137  static const bool right_zero_remains = false;
138  static const bool right_zero_identity = false;
139  static const bool left_zero_identity = true;
140  typedef T result_type;
141  T operator()(T x, T y)const{
142  return x/y;
143  }
144  };
145 
146  template<class T>
147  struct multiply_and_add{
148  static const bool left_zero_remains = false;
149  static const bool right_zero_remains = false;
150  static const bool right_zero_identity = true;
151  static const bool left_zero_identity = false;
152  typedef T result_type;
153  multiply_and_add(T scalar):scalar(scalar){}
154  T operator()(T x, T y)const{
155  return x+scalar * y;
156  }
157  private:
158  T scalar;
159  };
160  template<class T>
161  struct multiply_assign{
162  static const bool left_zero_remains = false;
163  static const bool right_zero_remains = false;
164  static const bool right_zero_identity = true;
165  static const bool left_zero_identity = false;
166  typedef T result_type;
167  multiply_assign(T scalar):scalar(scalar){}
168  T operator()(T, T y)const{
169  return scalar * y;
170  }
171  private:
172  T scalar;
173  };
174  template<class T>
175  struct pow {
176  static const bool left_zero_remains = false;
177  static const bool right_zero_remains = false;
178  typedef T result_type;
179  T operator()(T x, T y)const {
180  using std::pow;
181  return pow(x,y);
182  }
183  };
184  template<class T>
185  struct multiply_scalar{
186  static const bool zero_identity = true;
187  typedef T result_type;
188  multiply_scalar(T scalar):m_scalar(scalar){}
189  T operator()(T x) const{
190  return x * m_scalar;
191  }
192  private:
193  T m_scalar;
194  };
195  template<class T>
196  struct safe_divide {
197  static const bool left_zero_remains = true;
198  static const bool right_zero_remains = false;
199  safe_divide(T defaultValue):m_defaultValue(defaultValue) {}
200  typedef T result_type;
201  T operator()(T x, T y)const{
202  return y == T()? m_defaultValue : x/y;
203  }
204  private:
205  T m_defaultValue;
206  };
207 
208  //math unary functions
209  #define REMORA_STD_UNARY_FUNCTION(func, id)\
210  template<class T>\
211  struct func{\
212  static const bool zero_identity = id;\
213  typedef T result_type;\
214  T operator()(T x)const {\
215  return std::func(x);\
216  }\
217  };
218 
219  REMORA_STD_UNARY_FUNCTION(abs, true)
220  REMORA_STD_UNARY_FUNCTION(sqrt, true)
221  REMORA_STD_UNARY_FUNCTION(cbrt, true)
222 
223  REMORA_STD_UNARY_FUNCTION(exp, false)
224  REMORA_STD_UNARY_FUNCTION(log, false)
225 
226  //trigonometric functions
227  REMORA_STD_UNARY_FUNCTION(cos, false)
228  REMORA_STD_UNARY_FUNCTION(sin, true)
229  REMORA_STD_UNARY_FUNCTION(tan, true)
230 
231  REMORA_STD_UNARY_FUNCTION(acos, false)
232  REMORA_STD_UNARY_FUNCTION(asin, true)
233  REMORA_STD_UNARY_FUNCTION(atan, true)
234 
235  //sigmoid type functions
236  REMORA_STD_UNARY_FUNCTION(tanh, true)
237 
238  //special functions
239  REMORA_STD_UNARY_FUNCTION(erf, false)
240  REMORA_STD_UNARY_FUNCTION(erfc, false)
241 #undef REMORA_STD_UNARY_FUNCTION
242 
243  template<class T>
244  struct sigmoid {
245  static const bool zero_identity = false;
246  typedef T result_type;
247  T operator()(T x)const {
248  using std::tanh;
249  return (tanh(x/T(2)) + T(1))/T(2);
250  }
251  };
252  template<class T>
253  struct soft_plus {
254  static const bool zero_identity = false;
255  typedef T result_type;
256  T operator()(T x)const {
257  if(x > 100){
258  return x;
259  }
260  if(x < -100){
261  return 0;
262  }
263  return std::log(1+std::exp(x));
264  }
265  };
266 
267  template<class T>
268  struct inv {
269  static const bool zero_identity = false;
270  typedef T result_type;
271  T operator()(T x)const {
272  return T(1)/x;
273  }
274  };
275  template<class T>
276  struct sqr{
277  static const bool zero_identity = true;
278  typedef T result_type;
279  T operator()(T x)const {
280  return x*x;
281  }
282  };
283 
284 
285  //min/max
286  template<class T>
287  struct min{
288  static const bool left_zero_remains = false;
289  static const bool right_zero_remains = false;
290  typedef T result_type;
291  T operator()(T x, T y)const{
292  return std::min(x,y);
293  }
294  };
295 
296  template<class T>
297  struct max{
298  static const bool left_zero_remains = false;
299  static const bool right_zero_remains = false;
300  typedef T result_type;
301  T operator()(T x, T y)const{
302  return std::max(x,y);
303  }
304  };
305 
306 
307  //comparison
308  template<class T>
309  struct less{
310  static const bool left_zero_remains = false;
311  static const bool right_zero_remains = false;
312  typedef int result_type;
313  int operator()(T x1, T x2)const {
314  return x1 < x2;
315  }
316  };
317  template<class T>
318  struct less_equal{
319  static const bool left_zero_remains = false;
320  static const bool right_zero_remains = false;
321  typedef int result_type;
322  int operator()(T x1, T x2)const {
323  return x1 <= x2;
324  }
325  };
326 
327  template<class T>
328  struct greater{
329  static const bool left_zero_remains = false;
330  static const bool right_zero_remains = false;
331  typedef int result_type;
332  int operator()(T x1, T x2)const {
333  return x1 > x2;
334  }
335  };
336 
337  template<class T>
338  struct greater_equal{
339  static const bool left_zero_remains = false;
340  static const bool right_zero_remains = false;
341  typedef int result_type;
342  int operator()(T x1, T x2)const {
343  return x1 >= x2;
344  }
345  };
346 
347  template<class T>
348  struct equal{
349  static const bool left_zero_remains = false;
350  static const bool right_zero_remains = false;
351  typedef int result_type;
352  int operator()(T x1, T x2)const {
353  return x1 == x2;
354  }
355  };
356 
357  template<class T>
358  struct not_equal{
359  static const bool left_zero_remains = false;
360  static const bool right_zero_remains = false;
361  typedef int result_type;
362  int operator()(T x1, T x2)const {
363  return x1 != x2;
364  }
365  };
366 };
367 
368 }
369 
370 #endif