Cortenn
operator.hpp
Go to the documentation of this file.
1 
10 #include <cstring>
11 #include <cmath>
12 #include <functional>
13 #include <random>
14 
15 #include "llo/data.hpp"
16 
17 #ifndef LLO_OPERATOR_HPP
18 #define LLO_OPERATOR_HPP
19 
20 namespace llo
21 {
22 
24 using EngineT = std::default_random_engine;
25 
27 EngineT& get_engine (void);
28 
30 template <typename T>
31 void unary (T* out, ade::Shape& outshape,
32  VecRef<T> in, std::function<T(const T&)> f)
33 {
34  if (in.mapper == ade::identity)
35  {
36  for (ade::NElemT i = 0, n = in.shape.n_elems(); i < n; ++i)
37  {
38  out[i] = f(in.data[i]);
39  }
40  }
41  else if (in.push)
42  {
43  ade::CoordT coord;
44  for (ade::NElemT i = 0, n = in.shape.n_elems(); i < n; ++i)
45  {
46  in.mapper->forward(coord.begin(),
47  ade::coordinate(in.shape, i).begin());
48  out[ade::index(outshape, coord)] = f(in.data[i]);
49  }
50  }
51  else
52  {
53  ade::CoordT coord;
54  for (ade::NElemT i = 0, n = outshape.n_elems(); i < n; ++i)
55  {
56  in.mapper->forward(coord.begin(),
57  ade::coordinate(outshape, i).begin());
58  out[i] = f(in.data[ade::index(in.shape, coord)]);
59  }
60  }
61 }
62 
65 template <typename T>
66 void abs (T* out, VecRef<T> in)
67 {
68  unary<T>(out, in.shape, in, [](const T& src) { return std::abs(src); });
69 }
70 
71 template <>
72 void abs<uint8_t> (uint8_t* out, VecRef<uint8_t> in);
73 
74 template <>
75 void abs<uint16_t> (uint16_t* out, VecRef<uint16_t> in);
76 
77 template <>
78 void abs<uint32_t> (uint32_t* out, VecRef<uint32_t> in);
79 
80 template <>
81 void abs<uint64_t> (uint64_t* out, VecRef<uint64_t> in);
82 
85 template <typename T>
86 void neg (T* out, VecRef<T> in)
87 {
88  unary<T>(out, in.shape, in, [](const T& src) { return -src; });
89 }
90 
91 template <>
92 void neg<uint8_t> (uint8_t* out, VecRef<uint8_t> in);
93 
94 template <>
95 void neg<uint16_t> (uint16_t* out, VecRef<uint16_t> in);
96 
97 template <>
98 void neg<uint32_t> (uint32_t* out, VecRef<uint32_t> in);
99 
100 template <>
101 void neg<uint64_t> (uint64_t* out, VecRef<uint64_t> in);
102 
105 template <typename T>
106 void bit_not (T* out, VecRef<T> in)
107 {
108  unary<T>(out, in.shape, in, [](const T& src) { return !src; });
109 }
110 
113 template <typename T>
114 void sin (T* out, VecRef<T> in)
115 {
116  unary<T>(out, in.shape, in, [](const T& src) { return std::sin(src); });
117 }
118 
121 template <typename T>
122 void cos (T* out, VecRef<T> in)
123 {
124  unary<T>(out, in.shape, in, [](const T& src) { return std::cos(src); });
125 }
126 
129 template <typename T>
130 void tan (T* out, VecRef<T> in)
131 {
132  unary<T>(out, in.shape, in, [](const T& src) { return std::tan(src); });
133 }
134 
137 template <typename T>
138 void exp (T* out, VecRef<T> in)
139 {
140  unary<T>(out, in.shape, in, [](const T& src) { return std::exp(src); });
141 }
142 
145 template <typename T>
146 void log (T* out, VecRef<T> in)
147 {
148  unary<T>(out, in.shape, in, [](const T& src) { return std::log(src); });
149 }
150 
153 template <typename T>
154 void sqrt (T* out, VecRef<T> in)
155 {
156  unary<T>(out, in.shape, in, [](const T& src) { return std::sqrt(src); });
157 }
158 
161 template <typename T>
162 void round (T* out, VecRef<T> in)
163 {
164  unary<T>(out, in.shape, in, [](const T& src) { return std::round(src); });
165 }
166 
168 template <typename OUT, typename ATYPE, typename BTYPE>
169 void binary (OUT* out, ade::Shape& outshape, VecRef<ATYPE> a, VecRef<BTYPE> b,
170  std::function<OUT(const ATYPE&,const BTYPE&)> f)
171 {
172  // avoid tmpdata by checking if it's needed
173  // tmpdata not needed if neither a nor b are pushing
174  if (false == (a.push || b.push))
175  {
176  ade::CoordT coord;
177  ade::CoordT acoord;
178  ade::CoordT bcoord;
179  for (ade::NElemT i = 0, n = outshape.n_elems(); i < n; ++i)
180  {
181  coord = ade::coordinate(outshape, i);
182  a.mapper->forward(acoord.begin(), coord.begin());
183  b.mapper->forward(bcoord.begin(), coord.begin());
184  out[i] = f(
185  a.data[ade::index(a.shape, acoord)],
186  b.data[ade::index(b.shape, bcoord)]);
187  }
188  }
189  else // a.push || b.push
190  {
191  std::vector<ATYPE> tmpdata(outshape.n_elems());
192  ade::CoordT coord;
193  if (a.push)
194  {
195  for (ade::NElemT i = 0, n = a.shape.n_elems(); i < n; ++i)
196  {
197  a.mapper->forward(coord.begin(),
198  ade::coordinate(a.shape, i).begin());
199  tmpdata[ade::index(outshape, coord)] = a.data[i];
200  }
201  }
202  else
203  {
204  for (ade::NElemT i = 0, n = outshape.n_elems(); i < n; ++i)
205  {
206  a.mapper->forward(coord.begin(),
207  ade::coordinate(outshape, i).begin());
208  tmpdata[i] = a.data[ade::index(a.shape, coord)];
209  }
210  }
211  if (b.push)
212  {
213  for (ade::NElemT i = 0, n = b.shape.n_elems(); i < n; ++i)
214  {
215  b.mapper->forward(coord.begin(),
216  ade::coordinate(b.shape, i).begin());
217  ade::NElemT outidx = ade::index(outshape, coord);
218  out[outidx] = f(tmpdata[outidx], b.data[i]);
219  }
220  }
221  else
222  {
223  for (ade::NElemT i = 0, n = outshape.n_elems(); i < n; ++i)
224  {
225  b.mapper->forward(coord.begin(),
226  ade::coordinate(outshape, i).begin());
227  out[i] = f(tmpdata[i], b.data[ade::index(b.shape, coord)]);
228  }
229  }
230  }
231 }
232 
236 template <typename T>
237 void pow (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
238 {
239  binary<T,T,T>(out, outshape, a, b,
240  [](const T& b, const T& x) { return std::pow(b, x); });
241 }
242 
246 template <typename T>
247 void sub (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
248 {
249  binary<T,T,T>(out, outshape, a, b,
250  [](const T& a, const T& b) { return a - b; });
251 }
252 
256 template <typename T>
257 void div (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
258 {
259  binary<T,T,T>(out, outshape, a, b,
260  [](const T& a, const T& b) { return a / b; });
261 }
262 
266 template <typename T>
267 void eq (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
268 {
269  binary<T,T,T>(out, outshape, a, b,
270  [](const T& a, const T& b) { return a == b; });
271 }
272 
276 template <typename T>
277 void neq (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
278 {
279  binary<T,T,T>(out, outshape, a, b,
280  [](const T& a, const T& b) { return a != b; });
281 }
282 
286 template <typename T>
287 void lt (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
288 {
289  binary<T,T,T>(out, outshape, a, b,
290  [](const T& a, const T& b) { return a < b; });
291 }
292 
296 template <typename T>
297 void gt (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
298 {
299  binary<T,T,T>(out, outshape, a, b,
300  [](const T& a, const T& b) { return a > b; });
301 }
302 
306 template <typename T>
307 void rand_binom (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<double> b)
308 {
309  binary<T,T,double>(out, outshape, a, b,
310  [](const T& a, const double& b)
311  {
312  std::binomial_distribution<T> dist(a, b);
313  return dist(get_engine());
314  });
315 }
316 
317 template <>
318 void rand_binom<double> (double* out,
319  ade::Shape& outshape, VecRef<double> a, VecRef<double> b);
320 
321 template <>
322 void rand_binom<float> (float* out,
323  ade::Shape& outshape, VecRef<float> a, VecRef<double> b);
324 
328 template <typename T>
329 void rand_uniform (T* out,
330  ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
331 {
332  binary<T,T,T>(out, outshape, a, b,
333  [](const T& a, const T& b)
334  {
335  std::uniform_int_distribution<T> dist(a, b);
336  return dist(get_engine());
337  });
338 }
339 
340 template <>
341 void rand_uniform<double> (double* out,
342  ade::Shape& outshape, VecRef<double> a, VecRef<double> b);
343 
344 template <>
345 void rand_uniform<float> (float* out,
346  ade::Shape& outshape, VecRef<float> a, VecRef<float> b);
347 
351 template <typename T>
352 void rand_normal (T* out, ade::Shape& outshape, VecRef<T> a, VecRef<T> b)
353 {
354  throw std::bad_function_call();
355 }
356 
357 template <>
358 void rand_normal<double> (double* out,
359  ade::Shape& outshape, VecRef<double> a, VecRef<double> b);
360 
361 template <>
362 void rand_normal<float> (float* out,
363  ade::Shape& outshape, VecRef<float> a, VecRef<float> b);
364 
366 template <typename T>
367 void nnary (T* out, ade::Shape& outshape, std::vector<VecRef<T>> args,
368  std::function<void(T&, const T&)> acc)
369 {
370  ade::NElemT nout = outshape.n_elems();
371  bool visited[nout];
372  std::memset(visited, false, nout);
373  ade::CoordT coord;
374  for (VecRef<T>& arg : args)
375  {
376  if (arg.push)
377  {
378  for (ade::NElemT i = 0, n = arg.shape.n_elems(); i < n; ++i)
379  {
380  arg.mapper->forward(coord.begin(),
381  ade::coordinate(arg.shape, i).begin());
382  ade::NElemT outidx = ade::index(outshape, coord);
383  if (visited[outidx])
384  {
385  acc(out[outidx], arg.data[i]);
386  }
387  else
388  {
389  out[outidx] = arg.data[i];
390  visited[outidx] = true;
391  }
392  }
393  }
394  else
395  {
396  for (ade::NElemT i = 0, n = outshape.n_elems(); i < n; ++i)
397  {
398  arg.mapper->forward(coord.begin(),
399  ade::coordinate(outshape, i).begin());
400  ade::NElemT inidx = ade::index(arg.shape, coord);
401  if (visited[i])
402  {
403  acc(out[i], arg.data[inidx]);
404  }
405  else
406  {
407  out[i] = arg.data[inidx];
408  visited[i] = true;
409  }
410  }
411  }
412  }
413  // todo: do something/check unvisited elements
414 }
415 
418 template <typename T>
419 void add (T* out, ade::Shape& outshape, std::vector<VecRef<T>> args)
420 {
421  nnary<T>(out, outshape, args,
422  [](T& out, const T& val) { out += val; });
423 }
424 
427 template <typename T>
428 void mul (T* out, ade::Shape& outshape, std::vector<VecRef<T>> args)
429 {
430  nnary<T>(out, outshape, args,
431  [](T& out, const T& val) { out *= val; });
432 }
433 
436 template <typename T>
437 void min (T* out, ade::Shape& outshape, std::vector<VecRef<T>> args)
438 {
439  nnary<T>(out, outshape, args,
440  [](T& out, const T& val) { out = std::min(out, val); });
441 }
442 
445 template <typename T>
446 void max (T* out, ade::Shape& outshape, std::vector<VecRef<T>> args)
447 {
448  nnary<T>(out, outshape, args,
449  [](T& out, const T& val) { out = std::max(out, val); });
450 }
451 
452 }
453 
454 #endif // LLO_OPERATOR_HPP
void abs< uint64_t >(uint64_t *out, VecRef< uint64_t > in)
void gt(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:297
const T * data
Raw input data.
Definition: data.hpp:249
void tan(T *out, VecRef< T > in)
Definition: operator.hpp:130
void rand_binom< double >(double *out, ade::Shape &outshape, VecRef< double > a, VecRef< double > b)
void neg< uint8_t >(uint8_t *out, VecRef< uint8_t > in)
void nnary(T *out, ade::Shape &outshape, std::vector< VecRef< T >> args, std::function< void(T &, const T &)> acc)
Generic n-nary operation.
Definition: operator.hpp:367
void neg< uint16_t >(uint16_t *out, VecRef< uint16_t > in)
void exp(T *out, VecRef< T > in)
Definition: operator.hpp:138
EngineT & get_engine(void)
Return global random generator.
void eq(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:267
void abs< uint32_t >(uint32_t *out, VecRef< uint32_t > in)
Definition: data.hpp:246
std::default_random_engine EngineT
RNG engine used.
Definition: operator.hpp:24
void add(T *out, ade::Shape &outshape, std::vector< VecRef< T >> args)
Definition: operator.hpp:419
void unary(T *out, ade::Shape &outshape, VecRef< T > in, std::function< T(const T &)> f)
Generic unary operation assuming identity mapping.
Definition: operator.hpp:31
void binary(OUT *out, ade::Shape &outshape, VecRef< ATYPE > a, VecRef< BTYPE > b, std::function< OUT(const ATYPE &, const BTYPE &)> f)
Generic binary operation assuming identity mapping.
Definition: operator.hpp:169
void cos(T *out, VecRef< T > in)
Definition: operator.hpp:122
void rand_normal< double >(double *out, ade::Shape &outshape, VecRef< double > a, VecRef< double > b)
void neq(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:277
void round(T *out, VecRef< T > in)
Definition: operator.hpp:162
void rand_binom< float >(float *out, ade::Shape &outshape, VecRef< float > a, VecRef< double > b)
void min(T *out, ade::Shape &outshape, std::vector< VecRef< T >> args)
Definition: operator.hpp:437
void rand_uniform(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:329
void rand_uniform< float >(float *out, ade::Shape &outshape, VecRef< float > a, VecRef< float > b)
void abs< uint8_t >(uint8_t *out, VecRef< uint8_t > in)
void rand_uniform< double >(double *out, ade::Shape &outshape, VecRef< double > a, VecRef< double > b)
void sqrt(T *out, VecRef< T > in)
Definition: operator.hpp:154
void neg< uint64_t >(uint64_t *out, VecRef< uint64_t > in)
void rand_normal(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:352
Definition: data.hpp:20
bool push
Definition: data.hpp:259
ade::Shape shape
Shape info of the raw input.
Definition: data.hpp:252
void sub(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:247
void log(T *out, VecRef< T > in)
Definition: operator.hpp:146
void abs< uint16_t >(uint16_t *out, VecRef< uint16_t > in)
void max(T *out, ade::Shape &outshape, std::vector< VecRef< T >> args)
Definition: operator.hpp:446
void abs(T *out, VecRef< T > in)
Definition: operator.hpp:66
void mul(T *out, ade::Shape &outshape, std::vector< VecRef< T >> args)
Definition: operator.hpp:428
void sin(T *out, VecRef< T > in)
Definition: operator.hpp:114
void lt(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:287
void div(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:257
void neg(T *out, VecRef< T > in)
Definition: operator.hpp:86
ade::CoordptrT mapper
Coordinate mapper of input to output.
Definition: data.hpp:255
void rand_normal< float >(float *out, ade::Shape &outshape, VecRef< float > a, VecRef< float > b)
void pow(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< T > b)
Definition: operator.hpp:237
void rand_binom(T *out, ade::Shape &outshape, VecRef< T > a, VecRef< double > b)
Definition: operator.hpp:307
void bit_not(T *out, VecRef< T > in)
Definition: operator.hpp:106
void neg< uint32_t >(uint32_t *out, VecRef< uint32_t > in)