1 #ifndef HAVE_VECTORIZE_HPP 2 #define HAVE_VECTORIZE_HPP 7 typedef global::ad_segment ad_segment;
9 template <
class Type,
bool S0 = 0,
bool S1 = 0>
13 static constexpr
bool stride(
bool j) {
return j == 0 ? S0 : S1; }
14 operator Type() {
return x; }
15 Vectorized(Type x) : x(x) {}
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;
25 Type x(
bool j)
const {
26 return Base::values[Base::input(j) + k * T::stride(j)];
29 Type &y(Index j) {
return Base::values[Base::output(j) + k]; }
30 ForwardArgs(
const Base &x) : Base(x) {}
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;
39 Type x(
bool j)
const {
40 return Base::values[Base::input(j) + k * T::stride(j)];
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)];
51 Type dy(Index j)
const {
return Base::derivs[Base::output(j) + k]; }
52 ReverseArgs(
const Base &x) : Base(x) {}
55 struct VSumOp : global::DynamicOperator<1, 1> {
56 static const bool is_linear =
true;
60 void forward(ForwardArgs<Type> &args) {
61 const Type *x = args.x_ptr(0);
64 for (
size_t i = 0; i < n; i++) y += x[i];
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;
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();
84 ad_aug
sum(ad_segment x);
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())
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())
115 template <
class Operator,
bool S0 = false,
bool S1 = false>
116 struct Vectorize : global::DynamicOperator<Operator::ninput, -1> {
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++) {
129 void forward(ForwardArgs<Replay> &args) {
130 ad_segment x0(args.x_ptr(0), (S0 ? n : 1));
132 if (Operator::ninput > 1) {
133 x1 = ad_segment(args.x_ptr(1), (S1 ? n : 1));
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];
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++) {
146 void reverse(ReverseArgs<Replay> &args) {
147 std::vector<ad_segment> v;
148 std::vector<ad_segment> d;
149 std::vector<Index> i;
152 v.push_back(ad_segment(args.x_ptr(0), (S0 ? n : 1)));
154 i.push_back(i.size());
155 if (Operator::ninput > 1) {
156 v.push_back(ad_segment(args.x_ptr(1), (S1 ? n : 1)));
158 i.push_back(i.size());
161 v.push_back(ad_segment(args.y_ptr(0), n));
162 d.push_back(ad_segment(args.dy_ptr(0), n));
164 ReverseArgs<ad_segment> vargs(i, v, d);
167 vargs.ptr.second = Operator::ninput;
168 typename global::CPL<Operator>::type Op;
171 ad_segment dx_left(args.dx_ptr(0), (S0 ? n : 1),
true);
172 dx_left += vargs.dx(0);
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);
179 for (
size_t i = 0; i < dx_right.size(); i++)
180 args.dx_ptr(1)[i] = dx_right[i];
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));
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();
202 Vectorize(
const ad_segment &x,
const ad_segment &y)
203 : n(std::max(x.size(), y.size())) {}
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);
211 }
else if (x.size() > 1) {
212 global::Complete<Vectorize<global::ad_plain::DivOp, 1, 0> > F(n);
214 }
else if (y.size() > 1) {
215 global::Complete<Vectorize<global::ad_plain::DivOp, 0, 1> > F(n);
218 global::Complete<Vectorize<global::ad_plain::DivOp, 0, 0> > F(n);
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);
230 }
else if (x.size() > 1) {
231 global::Complete<Vectorize<global::ad_plain::MulOp, 1, 0> > F(n);
233 }
else if (y.size() > 1) {
234 global::Complete<Vectorize<global::ad_plain::MulOp, 0, 1> > F(n);
237 global::Complete<Vectorize<global::ad_plain::MulOp, 0, 0> > F(n);
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);
249 }
else if (x.size() > 1) {
250 global::Complete<Vectorize<global::ad_plain::AddOp, 1, 0> > F(n);
252 }
else if (y.size() > 1) {
253 global::Complete<Vectorize<global::ad_plain::AddOp, 0, 1> > F(n);
256 global::Complete<Vectorize<global::ad_plain::AddOp, 0, 0> > F(n);
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);
268 }
else if (x.size() > 1) {
269 global::Complete<Vectorize<global::ad_plain::SubOp, 1, 0> > F(n);
271 }
else if (y.size() > 1) {
272 global::Complete<Vectorize<global::ad_plain::SubOp, 0, 1> > F(n);
275 global::Complete<Vectorize<global::ad_plain::SubOp, 0, 0> > F(n);
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);
289 }
else if (x.size() > 1) {
290 global::Complete<Vectorize<PowOp, 1, 0> > F(n);
292 }
else if (y.size() > 1) {
293 global::Complete<Vectorize<PowOp, 0, 1> > F(n);
296 global::Complete<Vectorize<PowOp, 0, 0> > F(n);
302 template <
class dummy>
303 ad_segment operator-(ad_segment x) {
305 global::Complete<Vectorize<global::ad_plain::NegOp, 1, 0> > F(n);
309 template <
class dummy =
void>
310 ad_segment fabs(ad_segment x) {
312 global::Complete<Vectorize<AbsOp, 1, 0> > F(n);
315 template <
class dummy =
void>
316 ad_segment sin(ad_segment x) {
318 global::Complete<Vectorize<SinOp, 1, 0> > F(n);
321 template <
class dummy =
void>
322 ad_segment cos(ad_segment x) {
324 global::Complete<Vectorize<CosOp, 1, 0> > F(n);
327 template <
class dummy =
void>
328 ad_segment exp(ad_segment x) {
330 global::Complete<Vectorize<ExpOp, 1, 0> > F(n);
333 template <
class dummy =
void>
334 ad_segment log(ad_segment x) {
336 global::Complete<Vectorize<LogOp, 1, 0> > F(n);
339 template <
class dummy =
void>
340 ad_segment sqrt(ad_segment x) {
342 global::Complete<Vectorize<SqrtOp, 1, 0> > F(n);
345 template <
class dummy =
void>
346 ad_segment tan(ad_segment x) {
348 global::Complete<Vectorize<TanOp, 1, 0> > F(n);
351 template <
class dummy =
void>
352 ad_segment sinh(ad_segment x) {
354 global::Complete<Vectorize<SinhOp, 1, 0> > F(n);
357 template <
class dummy =
void>
358 ad_segment cosh(ad_segment x) {
360 global::Complete<Vectorize<CoshOp, 1, 0> > F(n);
363 template <
class dummy =
void>
364 ad_segment tanh(ad_segment x) {
366 global::Complete<Vectorize<TanhOp, 1, 0> > F(n);
369 template <
class dummy =
void>
370 ad_segment expm1(ad_segment x) {
372 global::Complete<Vectorize<Expm1, 1, 0> > F(n);
375 template <
class dummy =
void>
376 ad_segment log1p(ad_segment x) {
378 global::Complete<Vectorize<Log1p, 1, 0> > F(n);
381 template <
class dummy =
void>
382 ad_segment asin(ad_segment x) {
384 global::Complete<Vectorize<AsinOp, 1, 0> > F(n);
387 template <
class dummy =
void>
388 ad_segment acos(ad_segment x) {
390 global::Complete<Vectorize<AcosOp, 1, 0> > F(n);
393 template <
class dummy =
void>
394 ad_segment atan(ad_segment x) {
396 global::Complete<Vectorize<AtanOp, 1, 0> > F(n);
401 static const int size = (
sizeof(T) - 1) /
sizeof(Scalar) + 1;
417 void resize(ad_segment &
pack, Index n);
420 ad_segment
pack(
const ad_segment &x);
421 ad_segment
unpack(
const ad_segment &x);
437 static const Index K = ScalarPack<SegmentRef>::size;
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;
458 TMBAD_ASSERT2(
false,
"PackOp: Invalid method!");
462 TMBAD_ASSERT2(
false,
"PackOp: Invalid method!");
469 static const Index K = ScalarPack<SegmentRef>::size;
475 static const bool add_forward_replay_copy =
true;
480 const char *op_name();
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;
490 TMBAD_ASSERT2(
false,
"UnpkOp: Invalid method!");
494 TMBAD_ASSERT2(
false,
"UnpkOp: Invalid method!");
499 ad_segment
pack(
const ad_segment &x);
502 ad_segment
unpack(
const ad_segment &x);
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);
511 Scalar *
unpack(
const std::vector<Scalar> &x, Index j);
514 std::vector<T> repack(
const std::vector<T> &x) {
515 Index K = ScalarPack<SegmentRef>::size;
516 size_t n = x.size() / K;
518 for (
size_t j = 0; j < n; j++) {
519 ad_segment x_(x[j * K], K);
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]);
528 std::vector<ad_aug> concat(
const std::vector<ad_segment> &x);
531 #endif // HAVE_VECTORIZE_HPP Automatic differentiation library designed for TMB.
Index noutput
Unpacked size.
Access input/output values and derivatives during a reverse pass. Write access granted for the input ...
vector< Type > operator*(matrix< Type > A, vector< Type > x)
Struct defining the main AD context.
ad_segment unpack(const ad_segment &x)
Unpack consecutive values on the tape.
ad_segment pack(const ad_segment &x)
Pack consecutive values on the tape.
Pack (PackOp) or unpack (UnpkOp) n consecutive values on the tape.
Operator that requires dynamic allocation. Compile time known input/output size.
Type sum(Vector< Type > x)
Representation of a specific contiguous set of values on a specific tape.
Index input(Index j) const
Get variable index of j'th input to current operator.
Pack (PackOp) or unpack (UnpkOp) n consecutive values on the tape.
Type max(const vector< Type > &x)