TMB Documentation  v1.9.11
TMBad/vectorize.hpp
1 #ifndef HAVE_VECTORIZE_HPP
2 #define HAVE_VECTORIZE_HPP
3 // Autogenerated - do not edit by hand !
4 
5 namespace TMBad {
6 
7 typedef global::ad_segment ad_segment;
8 
9 template <class Type, bool S0 = 0, bool S1 = 0>
10 struct Vectorized {
11  Type x;
12 
13  static constexpr bool stride(bool j) { return j == 0 ? S0 : S1; }
14  operator Type() { return x; }
15  Vectorized(Type x) : x(x) {}
16  Vectorized() {}
17 };
18 
19 template <class Type, bool S0, bool S1>
20 struct ForwardArgs<Vectorized<Type, S0, S1> > : ForwardArgs<Type> {
21  typedef Vectorized<Type, S0, S1> T;
22  typedef ForwardArgs<Type> Base;
23  size_t k;
25  Type x(bool j) const {
26  return Base::values[Base::input(j) + k * T::stride(j)];
27  }
29  Type &y(Index j) { return Base::values[Base::output(j) + k]; }
30  ForwardArgs(const Base &x) : Base(x) {}
31 };
32 
33 template <class Type, bool S0, bool S1>
34 struct ReverseArgs<Vectorized<Type, S0, S1> > : ReverseArgs<Type> {
35  typedef Vectorized<Type, S0, S1> T;
36  typedef ReverseArgs<Type> Base;
37  size_t k;
39  Type x(bool j) const {
40  return Base::values[Base::input(j) + k * T::stride(j)];
41  }
43  Type y(Index j) const { return Base::values[Base::output(j) + k]; }
46  Type &dx(bool j) const {
47  return Base::derivs[Base::input(j) + k * T::stride(j)];
48  }
51  Type dy(Index j) const { return Base::derivs[Base::output(j) + k]; }
52  ReverseArgs(const Base &x) : Base(x) {}
53 };
54 
55 struct VSumOp : global::DynamicOperator<1, 1> {
56  static const bool is_linear = true;
57  size_t n;
58  VSumOp(size_t n);
59  template <class Type>
60  void forward(ForwardArgs<Type> &args) {
61  const Type *x = args.x_ptr(0);
62  Type &y = args.y(0);
63  y = 0;
64  for (size_t i = 0; i < n; i++) y += x[i];
65  }
66  template <class Type>
67  void reverse(ReverseArgs<Type> &args) {
68  Type *dx = args.dx_ptr(0);
69  const Type &dy = args.dy(0);
70  for (size_t i = 0; i < n; i++) dx[i] += dy;
71  }
72 
73  void dependencies(Args<> &args, Dependencies &dep) const;
74  static const bool have_dependencies = true;
76  static const bool implicit_dependencies = true;
78  static const bool allow_remap = false;
79  void forward(ForwardArgs<Writer> &args);
80  void reverse(ReverseArgs<Writer> &args);
81  const char *op_name();
82 };
83 
84 ad_aug sum(ad_segment x);
85 
86 template <class dummy = void>
87 ad_segment operator/(ad_segment x, ad_segment y);
88 template <class dummy = void>
89 ad_segment operator*(ad_segment x, ad_segment y);
90 template <class dummy = void>
91 ad_segment operator+(ad_segment x, ad_segment y);
92 template <class dummy = void>
93 ad_segment operator-(ad_segment x, ad_segment y);
94 template <class dummy = void>
95 ad_segment operator-(ad_segment x);
96 template <class dummy = void>
97 ad_segment &operator+=(ad_segment &x, ad_segment y) {
98  if ((x.size() == 1) && (x.size() < y.size())) y = ad_segment(sum(y), 1);
99  if (x.identicalZero())
100  x = y;
101  else
102  x = x + y;
103  return x;
104 }
105 template <class dummy = void>
106 ad_segment &operator-=(ad_segment &x, ad_segment y) {
107  if ((x.size() == 1) && (x.size() < y.size())) y = ad_segment(sum(y), 1);
108  if (x.identicalZero())
109  x = -y;
110  else
111  x = x - y;
112  return x;
113 }
114 
115 template <class Operator, bool S0 = false, bool S1 = false>
116 struct Vectorize : global::DynamicOperator<Operator::ninput, -1> {
117  size_t n;
118  static const bool have_input_size_output_size = true;
119  Index input_size() const { return Operator::ninput; }
120  Index output_size() const { return this->n; }
121  Vectorize(size_t n) : n(n) {}
122  void forward(ForwardArgs<Scalar> &args) {
123  ForwardArgs<Vectorized<Scalar, S0, S1> > vargs(args);
124  typename global::CPL<Operator>::type Op;
125  for (vargs.k = 0; vargs.k < n; vargs.k++) {
126  Op.forward(vargs);
127  }
128  }
129  void forward(ForwardArgs<Replay> &args) {
130  ad_segment x0(args.x_ptr(0), (S0 ? n : 1));
131  ad_segment x1;
132  if (Operator::ninput > 1) {
133  x1 = ad_segment(args.x_ptr(1), (S1 ? n : 1));
134  }
135  global::Complete<Vectorize> F(*this);
136  ad_segment y = F(x0, x1);
137  for (size_t i = 0; i < y.size(); i++) args.y(i) = y[i];
138  }
139  void reverse(ReverseArgs<Scalar> &args) {
140  ReverseArgs<Vectorized<Scalar, S0, S1> > vargs(args);
141  typename global::CPL<Operator>::type Op;
142  for (vargs.k = 0; vargs.k < n; vargs.k++) {
143  Op.reverse(vargs);
144  }
145  }
146  void reverse(ReverseArgs<Replay> &args) {
147  std::vector<ad_segment> v;
148  std::vector<ad_segment> d;
149  std::vector<Index> i;
150  ad_segment zero;
151 
152  v.push_back(ad_segment(args.x_ptr(0), (S0 ? n : 1)));
153  d.push_back(zero);
154  i.push_back(i.size());
155  if (Operator::ninput > 1) {
156  v.push_back(ad_segment(args.x_ptr(1), (S1 ? n : 1)));
157  d.push_back(zero);
158  i.push_back(i.size());
159  }
160 
161  v.push_back(ad_segment(args.y_ptr(0), n));
162  d.push_back(ad_segment(args.dy_ptr(0), n));
163 
164  ReverseArgs<ad_segment> vargs(i, v, d);
165 
166  vargs.ptr.first = 0;
167  vargs.ptr.second = Operator::ninput;
168  typename global::CPL<Operator>::type Op;
169  Op.reverse(vargs);
170 
171  ad_segment dx_left(args.dx_ptr(0), (S0 ? n : 1), true);
172  dx_left += vargs.dx(0);
173 
174  for (size_t i = 0; i < dx_left.size(); i++) args.dx_ptr(0)[i] = dx_left[i];
175  if (Operator::ninput > 1) {
176  ad_segment dx_right(args.dx_ptr(1), (S1 ? n : 1), true);
177  dx_right += vargs.dx(1);
178 
179  for (size_t i = 0; i < dx_right.size(); i++)
180  args.dx_ptr(1)[i] = dx_right[i];
181  }
182  }
183 
184  void dependencies(Args<> &args, Dependencies &dep) const {
185  dep.add_segment(args.input(0), (S0 ? n : 1));
186  if (Operator::ninput == 2) {
187  dep.add_segment(args.input(1), (S1 ? n : 1));
188  }
189  }
190  static const bool have_dependencies = true;
192  static const bool implicit_dependencies = true;
194  static const bool allow_remap = false;
195  void forward(ForwardArgs<Writer> &args) { TMBAD_ASSERT(false); }
196  void reverse(ReverseArgs<Writer> &args) { TMBAD_ASSERT(false); }
197  const char *op_name() {
198  global::Complete<Operator> Op;
199  static const std::string name = std::string("V") + Op.op_name();
200  return name.c_str();
201  }
202  Vectorize(const ad_segment &x, const ad_segment &y)
203  : n(std::max(x.size(), y.size())) {}
204 };
205 template <class dummy>
206 ad_segment operator/(ad_segment x, ad_segment y) {
207  size_t n = std::max(x.size(), y.size());
208  if (x.size() > 1 && y.size() > 1) {
209  global::Complete<Vectorize<global::ad_plain::DivOp, 1, 1> > F(n);
210  return F(x, y);
211  } else if (x.size() > 1) {
212  global::Complete<Vectorize<global::ad_plain::DivOp, 1, 0> > F(n);
213  return F(x, y);
214  } else if (y.size() > 1) {
215  global::Complete<Vectorize<global::ad_plain::DivOp, 0, 1> > F(n);
216  return F(x, y);
217  } else {
218  global::Complete<Vectorize<global::ad_plain::DivOp, 0, 0> > F(n);
219  return F(x, y);
220  }
221  TMBAD_ASSERT(false);
222  return ad_segment();
223 }
224 template <class dummy>
225 ad_segment operator*(ad_segment x, ad_segment y) {
226  size_t n = std::max(x.size(), y.size());
227  if (x.size() > 1 && y.size() > 1) {
228  global::Complete<Vectorize<global::ad_plain::MulOp, 1, 1> > F(n);
229  return F(x, y);
230  } else if (x.size() > 1) {
231  global::Complete<Vectorize<global::ad_plain::MulOp, 1, 0> > F(n);
232  return F(x, y);
233  } else if (y.size() > 1) {
234  global::Complete<Vectorize<global::ad_plain::MulOp, 0, 1> > F(n);
235  return F(x, y);
236  } else {
237  global::Complete<Vectorize<global::ad_plain::MulOp, 0, 0> > F(n);
238  return F(x, y);
239  }
240  TMBAD_ASSERT(false);
241  return ad_segment();
242 }
243 template <class dummy>
244 ad_segment operator+(ad_segment x, ad_segment y) {
245  size_t n = std::max(x.size(), y.size());
246  if (x.size() > 1 && y.size() > 1) {
247  global::Complete<Vectorize<global::ad_plain::AddOp, 1, 1> > F(n);
248  return F(x, y);
249  } else if (x.size() > 1) {
250  global::Complete<Vectorize<global::ad_plain::AddOp, 1, 0> > F(n);
251  return F(x, y);
252  } else if (y.size() > 1) {
253  global::Complete<Vectorize<global::ad_plain::AddOp, 0, 1> > F(n);
254  return F(x, y);
255  } else {
256  global::Complete<Vectorize<global::ad_plain::AddOp, 0, 0> > F(n);
257  return F(x, y);
258  }
259  TMBAD_ASSERT(false);
260  return ad_segment();
261 }
262 template <class dummy>
263 ad_segment operator-(ad_segment x, ad_segment y) {
264  size_t n = std::max(x.size(), y.size());
265  if (x.size() > 1 && y.size() > 1) {
266  global::Complete<Vectorize<global::ad_plain::SubOp, 1, 1> > F(n);
267  return F(x, y);
268  } else if (x.size() > 1) {
269  global::Complete<Vectorize<global::ad_plain::SubOp, 1, 0> > F(n);
270  return F(x, y);
271  } else if (y.size() > 1) {
272  global::Complete<Vectorize<global::ad_plain::SubOp, 0, 1> > F(n);
273  return F(x, y);
274  } else {
275  global::Complete<Vectorize<global::ad_plain::SubOp, 0, 0> > F(n);
276  return F(x, y);
277  }
278  TMBAD_ASSERT(false);
279  return ad_segment();
280 }
281 template <class dummy = void>
282 ad_segment pow(ad_segment x, ad_segment y);
283 template <class dummy>
284 ad_segment pow(ad_segment x, ad_segment y) {
285  size_t n = std::max(x.size(), y.size());
286  if (x.size() > 1 && y.size() > 1) {
287  global::Complete<Vectorize<PowOp, 1, 1> > F(n);
288  return F(x, y);
289  } else if (x.size() > 1) {
290  global::Complete<Vectorize<PowOp, 1, 0> > F(n);
291  return F(x, y);
292  } else if (y.size() > 1) {
293  global::Complete<Vectorize<PowOp, 0, 1> > F(n);
294  return F(x, y);
295  } else {
296  global::Complete<Vectorize<PowOp, 0, 0> > F(n);
297  return F(x, y);
298  }
299  TMBAD_ASSERT(false);
300  return ad_segment();
301 }
302 template <class dummy>
303 ad_segment operator-(ad_segment x) {
304  size_t n = x.size();
305  global::Complete<Vectorize<global::ad_plain::NegOp, 1, 0> > F(n);
306  return F(x);
307 }
308 
309 template <class dummy = void>
310 ad_segment fabs(ad_segment x) {
311  size_t n = x.size();
312  global::Complete<Vectorize<AbsOp, 1, 0> > F(n);
313  return F(x);
314 }
315 template <class dummy = void>
316 ad_segment sin(ad_segment x) {
317  size_t n = x.size();
318  global::Complete<Vectorize<SinOp, 1, 0> > F(n);
319  return F(x);
320 }
321 template <class dummy = void>
322 ad_segment cos(ad_segment x) {
323  size_t n = x.size();
324  global::Complete<Vectorize<CosOp, 1, 0> > F(n);
325  return F(x);
326 }
327 template <class dummy = void>
328 ad_segment exp(ad_segment x) {
329  size_t n = x.size();
330  global::Complete<Vectorize<ExpOp, 1, 0> > F(n);
331  return F(x);
332 }
333 template <class dummy = void>
334 ad_segment log(ad_segment x) {
335  size_t n = x.size();
336  global::Complete<Vectorize<LogOp, 1, 0> > F(n);
337  return F(x);
338 }
339 template <class dummy = void>
340 ad_segment sqrt(ad_segment x) {
341  size_t n = x.size();
342  global::Complete<Vectorize<SqrtOp, 1, 0> > F(n);
343  return F(x);
344 }
345 template <class dummy = void>
346 ad_segment tan(ad_segment x) {
347  size_t n = x.size();
348  global::Complete<Vectorize<TanOp, 1, 0> > F(n);
349  return F(x);
350 }
351 template <class dummy = void>
352 ad_segment sinh(ad_segment x) {
353  size_t n = x.size();
354  global::Complete<Vectorize<SinhOp, 1, 0> > F(n);
355  return F(x);
356 }
357 template <class dummy = void>
358 ad_segment cosh(ad_segment x) {
359  size_t n = x.size();
360  global::Complete<Vectorize<CoshOp, 1, 0> > F(n);
361  return F(x);
362 }
363 template <class dummy = void>
364 ad_segment tanh(ad_segment x) {
365  size_t n = x.size();
366  global::Complete<Vectorize<TanhOp, 1, 0> > F(n);
367  return F(x);
368 }
369 template <class dummy = void>
370 ad_segment expm1(ad_segment x) {
371  size_t n = x.size();
372  global::Complete<Vectorize<Expm1, 1, 0> > F(n);
373  return F(x);
374 }
375 template <class dummy = void>
376 ad_segment log1p(ad_segment x) {
377  size_t n = x.size();
378  global::Complete<Vectorize<Log1p, 1, 0> > F(n);
379  return F(x);
380 }
381 template <class dummy = void>
382 ad_segment asin(ad_segment x) {
383  size_t n = x.size();
384  global::Complete<Vectorize<AsinOp, 1, 0> > F(n);
385  return F(x);
386 }
387 template <class dummy = void>
388 ad_segment acos(ad_segment x) {
389  size_t n = x.size();
390  global::Complete<Vectorize<AcosOp, 1, 0> > F(n);
391  return F(x);
392 }
393 template <class dummy = void>
394 ad_segment atan(ad_segment x) {
395  size_t n = x.size();
396  global::Complete<Vectorize<AtanOp, 1, 0> > F(n);
397  return F(x);
398 }
399 template <class T>
400 struct ScalarPack {
401  static const int size = (sizeof(T) - 1) / sizeof(Scalar) + 1;
402 };
403 
406 struct SegmentRef {
407  global *glob_ptr;
408  Index offset;
409  Index size;
410  Scalar *value_ptr();
411  Scalar *deriv_ptr();
412  SegmentRef();
413  SegmentRef(const Scalar *x);
414  SegmentRef(global *g, Index o, Index s);
415  SegmentRef(const ad_segment &x);
416  bool isNull();
417  void resize(ad_segment &pack, Index n);
418 };
419 
420 ad_segment pack(const ad_segment &x);
421 ad_segment unpack(const ad_segment &x);
422 
435 struct PackOp : global::DynamicOperator<1, ScalarPack<SegmentRef>::size> {
437  static const Index K = ScalarPack<SegmentRef>::size;
439  Index n;
440  PackOp(const Index n);
442  void forward(ForwardArgs<Scalar> &args);
444  void forward(ForwardArgs<Replay> &args);
446  void reverse(ReverseArgs<Scalar> &args);
448  void reverse(ReverseArgs<Replay> &args);
449  const char *op_name();
451  static const bool allow_remap = false;
452  static const bool have_dependencies = true;
453  static const bool implicit_dependencies = true;
454  void dependencies(Args<> &args, Dependencies &dep) const;
455 
456  template <class T>
457  void forward(ForwardArgs<T> &args) {
458  TMBAD_ASSERT2(false, "PackOp: Invalid method!");
459  }
460  template <class T>
461  void reverse(ReverseArgs<T> &args) {
462  TMBAD_ASSERT2(false, "PackOp: Invalid method!");
463  }
464 };
465 
469  static const Index K = ScalarPack<SegmentRef>::size;
471  Index noutput;
472  UnpkOp(const Index n);
474  void forward(ForwardArgs<Scalar> &args);
475  static const bool add_forward_replay_copy = true;
477  void reverse(ReverseArgs<Scalar> &args);
479  void reverse(ReverseArgs<Replay> &args);
480  const char *op_name();
481 
483  static const bool allow_remap = false;
484  static const bool have_dependencies = true;
485  static const bool implicit_dependencies = true;
486  void dependencies(Args<> &args, Dependencies &dep) const;
487 
488  template <class T>
489  void forward(ForwardArgs<T> &args) {
490  TMBAD_ASSERT2(false, "UnpkOp: Invalid method!");
491  }
492  template <class T>
493  void reverse(ReverseArgs<T> &args) {
494  TMBAD_ASSERT2(false, "UnpkOp: Invalid method!");
495  }
496 };
497 
499 ad_segment pack(const ad_segment &x);
500 
502 ad_segment unpack(const ad_segment &x);
503 
505 template <class T>
506 ad_segment unpack(const std::vector<T> &x, Index j) {
507  Index K = ScalarPack<SegmentRef>::size;
508  ad_segment x_(x[j * K], K);
509  return unpack(x_);
510 }
511 Scalar *unpack(const std::vector<Scalar> &x, Index j);
512 
513 template <class T>
514 std::vector<T> repack(const std::vector<T> &x) {
515  Index K = ScalarPack<SegmentRef>::size;
516  size_t n = x.size() / K;
517  std::vector<T> y;
518  for (size_t j = 0; j < n; j++) {
519  ad_segment x_(x[j * K], K);
520  SegmentRef sr(x_);
521  ad_segment orig(sr.offset, sr.size);
522  ad_segment yj = pack(orig);
523  for (size_t i = 0; i < K; i++) y.push_back(yj[i]);
524  }
525  return y;
526 }
527 
528 std::vector<ad_aug> concat(const std::vector<ad_segment> &x);
529 
530 } // namespace TMBad
531 #endif // HAVE_VECTORIZE_HPP
Automatic differentiation library designed for TMB.
Definition: TMB.hpp:157
Index noutput
Unpacked size.
Access input/output values and derivatives during a reverse pass. Write access granted for the input ...
Definition: global.hpp:311
vector< Type > operator*(matrix< Type > A, vector< Type > x)
Definition: convenience.hpp:42
Struct defining the main AD context.
Definition: global.hpp:797
ad_segment unpack(const ad_segment &x)
Unpack consecutive values on the tape.
Definition: TMBad.cpp:4653
ad_segment pack(const ad_segment &x)
Pack consecutive values on the tape.
Definition: TMBad.cpp:4648
Pack (PackOp) or unpack (UnpkOp) n consecutive values on the tape.
Operator that requires dynamic allocation. Compile time known input/output size.
Definition: global.hpp:1590
Type sum(Vector< Type > x)
Definition: convenience.hpp:33
Representation of a specific contiguous set of values on a specific tape.
Index input(Index j) const
Get variable index of j&#39;th input to current operator.
Definition: global.hpp:265
Pack (PackOp) or unpack (UnpkOp) n consecutive values on the tape.
Type max(const vector< Type > &x)
Index n
Unpacked size.
License: GPL v2