TMB Documentation
v1.9.11
TMB
inst
include
tmbad_atomic_macro.hpp
1
2
3
#define TMB_ATOMIC_VECTOR_FUNCTION_DEFINE( \
4
ATOMIC_NAME, OUTPUT_DIM, \
5
ATOMIC_DOUBLE, \
6
ATOMIC_REVERSE \
7
) \
8
template<class dummy> \
9
CppAD::vector<TMBad::ad_aug> \
10
ATOMIC_NAME (const CppAD::vector<TMBad::ad_aug> &x); \
11
template<class dummy> \
12
CppAD::vector<double> \
13
ATOMIC_NAME (const CppAD::vector<double> &tx) CSKIP_ATOMIC({ \
14
CppAD::vector<double> ty(OUTPUT_DIM); \
15
ATOMIC_DOUBLE; \
16
return ty; \
17
}) \
18
template<class dummy=void> \
19
struct ATOMIC_NAME ## Op : TMBad::global::DynamicInputOutputOperator { \
20
typedef TMBad::global::DynamicInputOutputOperator Base; \
21
ATOMIC_NAME ## Op (TMBad::Index n, TMBad::Index m) : Base(n, m) {} \
22
const char* op_name() { return #ATOMIC_NAME; } \
23
static const bool add_static_identifier = true; \
24
void forward(TMBad::ForwardArgs<TMBad::Scalar> _args_) { \
25
CppAD::vector<TMBad::Scalar> tx(this->input_size()); \
26
CppAD::vector<TMBad::Scalar> ty(this->output_size()); \
27
for (size_t i=0; i<tx.size(); i++) tx[i] = _args_.x(i); \
28
ATOMIC_DOUBLE; \
29
for (size_t i=0; i<ty.size(); i++) _args_.y(i) = ty[i]; \
30
} \
31
void forward(TMBad::ForwardArgs<TMBad::Replay> _args_) { \
32
CppAD::vector<TMBad::Replay> tx(this->input_size()); \
33
for (size_t i=0; i<tx.size(); i++) tx[i] = _args_.x(i); \
34
CppAD::vector<TMBad::Replay> ty = ATOMIC_NAME(tx); \
35
for (size_t i=0; i<ty.size(); i++) _args_.y(i) = ty[i]; \
36
} \
37
template<class Type> void reverse(TMBad::ReverseArgs<Type> _args_) { \
38
if (isDouble<Type>::value && \
39
this->output_size() == 1 && \
40
_args_.dy(0) == Type(0)) { \
41
return; \
42
} \
43
CppAD::vector<Type> tx(this->input_size()); \
44
CppAD::vector<Type> ty(this->output_size()); \
45
CppAD::vector<Type> px(this->input_size()); \
46
CppAD::vector<Type> py(this->output_size()); \
47
for (size_t i=0; i<tx.size(); i++) tx[i] = _args_.x(i); \
48
for (size_t i=0; i<ty.size(); i++) ty[i] = _args_.y(i); \
49
for (size_t i=0; i<py.size(); i++) py[i] = _args_.dy(i); \
50
ATOMIC_REVERSE; \
51
for (size_t i=0; i<px.size(); i++) _args_.dx(i) += px[i]; \
52
} \
53
void forward \
54
(TMBad::ForwardArgs<TMBad::Writer> &args) { TMBAD_ASSERT(false); } \
55
void reverse \
56
(TMBad::ReverseArgs<TMBad::Writer> &args) { TMBAD_ASSERT(false); } \
57
}; \
58
template<class dummy> \
59
CppAD::vector<TMBad::ad_aug> \
60
ATOMIC_NAME (const CppAD::vector<TMBad::ad_aug> &tx) CSKIP_ATOMIC({ \
61
TMBad::Index n = tx.size(); \
62
TMBad::Index m = OUTPUT_DIM; \
63
typedef ATOMIC_NAME ## Op <> OP; \
64
bool all_constant = true; \
65
for (size_t i = 0; i<tx.size(); i++) \
66
all_constant &= tx[i].constant(); \
67
CppAD::vector<TMBad::ad_aug> ty(m); \
68
if (all_constant) { \
69
CppAD::vector<double> xd(tx.size()); \
70
for (size_t i=0; i<xd.size(); i++) xd[i] = tx[i].Value(); \
71
CppAD::vector<double> yd = ATOMIC_NAME(xd); \
72
for (size_t i=0; i<yd.size(); i++) ty[i] = yd[i]; \
73
} else { \
74
TMBad::OperatorPure* \
75
pOp = TMBad::get_glob()->getOperator<OP>(n, m); \
76
std::vector<TMBad::ad_plain> \
77
x(&tx[0], &tx[0] + tx.size()); \
78
std::vector<TMBad::ad_plain> \
79
y = TMBad::get_glob()->add_to_stack<OP>(pOp, x); \
80
for (size_t i=0; i<y.size(); i++) ty[i] = y[i]; \
81
} \
82
return ty; \
83
}) \
84
template<class dummy=void> \
85
void ATOMIC_NAME (const CppAD::vector<TMBad::ad_aug> &tx, \
86
CppAD::vector<TMBad::ad_aug> &ty) { \
87
ty = ATOMIC_NAME(tx); \
88
} \
89
IF_TMB_PRECOMPILE_ATOMICS( \
90
template \
91
CppAD::vector<double> \
92
ATOMIC_NAME<> (const CppAD::vector<double>& tx); \
93
template \
94
CppAD::vector<TMBad::ad_aug> \
95
ATOMIC_NAME<>(const CppAD::vector<TMBad::ad_aug>& tx); \
96
)
97
98
#define TMB_ATOMIC_STATIC_FUNCTION( \
99
ATOMIC_NAME, \
100
INPUT_SIZE, \
101
ATOMIC_DOUBLE, \
102
ATOMIC_REVERSE \
103
) \
104
template<class dummy=void> \
105
CppAD::vector<TMBad::ad_aug> ATOMIC_NAME \
106
(const CppAD::vector<TMBad::ad_aug> &x); \
107
template<class dummy=void> \
108
CppAD::vector<double> ATOMIC_NAME \
109
(const CppAD::vector<double> &tx) CSKIP_ATOMIC({ \
110
CppAD::vector<double> ty(1); \
111
ATOMIC_DOUBLE; \
112
return ty; \
113
}) \
114
template<class dummy=void> \
115
double ATOMIC_NAME (const double *tx) { \
116
double ty[1]; \
117
ATOMIC_DOUBLE; \
118
return ty[0]; \
119
} \
120
template<class dummy=void> \
121
TMBad::ad_aug ATOMIC_NAME (const TMBad::ad_aug *tx) { \
122
CppAD::vector<TMBad::ad_aug> tx_(INPUT_SIZE); \
123
for (size_t i=0; i<INPUT_SIZE; i++) tx_[i]=tx[i]; \
124
return ATOMIC_NAME(tx_)[0]; \
125
} \
126
template<class dummy=void> \
127
struct ATOMIC_NAME ## Op : TMBad::global::Operator<INPUT_SIZE, 1> { \
128
ATOMIC_NAME ## Op () {} \
129
const char* op_name() { return #ATOMIC_NAME; } \
130
void forward(TMBad::ForwardArgs<TMBad::Scalar> _args_) { \
131
TMBad::Scalar tx[INPUT_SIZE]; \
132
TMBad::Scalar ty[1] ; \
133
for (size_t i=0; i<INPUT_SIZE; i++) tx[i] = _args_.x(i); \
134
ATOMIC_DOUBLE; \
135
for (size_t i=0; i<1; i++) _args_.y(i) = ty[i]; \
136
} \
137
static const bool add_forward_replay_copy = true; \
138
template<class Type> void no_W_set_but_not_used(Type *p) { } \
139
template<class Type> void reverse(TMBad::ReverseArgs<Type> _args_) { \
140
Type tx[INPUT_SIZE]; \
141
Type ty[1] ; \
142
Type px[INPUT_SIZE]; \
143
Type py[1] ; \
144
no_W_set_but_not_used(tx); \
145
no_W_set_but_not_used(ty); \
146
no_W_set_but_not_used(py); \
147
for (size_t i=0; i<INPUT_SIZE; i++) tx[i] = _args_.x(i); \
148
for (size_t i=0; i<1 ; i++) ty[i] = _args_.y(i); \
149
for (size_t i=0; i<1 ; i++) py[i] = _args_.dy(i); \
150
ATOMIC_REVERSE; \
151
for (size_t i=0; i<INPUT_SIZE; i++) _args_.dx(i) += px[i]; \
152
} \
153
template<class Type> \
154
void forward \
155
(TMBad::ForwardArgs<Type> &args) { TMBAD_ASSERT(false); } \
156
void reverse \
157
(TMBad::ReverseArgs<TMBad::Writer> &args) { TMBAD_ASSERT(false); } \
158
}; \
159
template<class dummy> \
160
CppAD::vector<TMBad::ad_aug> ATOMIC_NAME \
161
(const CppAD::vector<TMBad::ad_aug> &tx) CSKIP_ATOMIC({ \
162
TMBad::Index m = 1; \
163
typedef ATOMIC_NAME ## Op <> OP; \
164
bool all_constant = true; \
165
for (size_t i = 0; i<tx.size(); i++) \
166
all_constant &= tx[i].constant(); \
167
CppAD::vector<TMBad::ad_aug> ty(m); \
168
if (all_constant) { \
169
CppAD::vector<double> xd(tx.size()); \
170
for (size_t i=0; i<xd.size(); i++) xd[i] = tx[i].Value(); \
171
CppAD::vector<double> yd = ATOMIC_NAME(xd); \
172
for (size_t i=0; i<yd.size(); i++) ty[i] = yd[i]; \
173
} else { \
174
TMBad::OperatorPure* \
175
pOp = TMBad::get_glob()->getOperator<OP>(); \
176
std::vector<TMBad::ad_plain> \
177
x(&tx[0], &tx[0] + tx.size()); \
178
std::vector<TMBad::ad_plain> \
179
y = TMBad::get_glob()->add_to_stack<OP>(pOp, x); \
180
for (size_t i=0; i<y.size(); i++) ty[i] = y[i]; \
181
} \
182
return ty; \
183
}) \
184
template<class dummy=void> \
185
void ATOMIC_NAME (const CppAD::vector<TMBad::ad_aug> &tx, \
186
CppAD::vector<TMBad::ad_aug> &ty) { \
187
ty = ATOMIC_NAME(tx); \
188
} \
189
IF_TMB_PRECOMPILE_ATOMICS( \
190
template \
191
CppAD::vector<double> \
192
ATOMIC_NAME<> (const CppAD::vector<double>& tx); \
193
template \
194
CppAD::vector<TMBad::ad_aug> \
195
ATOMIC_NAME<>(const CppAD::vector<TMBad::ad_aug>& tx); \
196
)
197
// Helper to forward declare atomic
198
#define TMB_ATOMIC_VECTOR_FUNCTION_DECLARE(ATOMIC_NAME) \
199
template<class dummy=void> \
200
CppAD::vector<TMBad::ad_aug> \
201
ATOMIC_NAME (const CppAD::vector<TMBad::ad_aug> &x); \
202
template<class dummy=void> \
203
CppAD::vector<double> \
204
ATOMIC_NAME (const CppAD::vector<double> &tx);
205
217
#define TMB_ATOMIC_VECTOR_FUNCTION( \
218
ATOMIC_NAME, OUTPUT_DIM, \
219
ATOMIC_DOUBLE, \
220
ATOMIC_REVERSE \
221
) \
222
TMB_ATOMIC_VECTOR_FUNCTION_DECLARE(ATOMIC_NAME) \
223
TMB_ATOMIC_VECTOR_FUNCTION_DEFINE( \
224
ATOMIC_NAME, OUTPUT_DIM, \
225
ATOMIC_DOUBLE, \
226
ATOMIC_REVERSE \
227
)
License:
GPL v2