Sleipnir C++ API
Loading...
Searching...
No Matches
expression.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <stdint.h>
6
7#include <algorithm>
8#include <array>
9#include <cmath>
10#include <memory>
11#include <numbers>
12#include <utility>
13
14#include <gch/small_vector.hpp>
15
16#include "sleipnir/autodiff/expression_type.hpp"
17#include "sleipnir/util/intrusive_shared_ptr.hpp"
18#include "sleipnir/util/pool.hpp"
19
20namespace slp::detail {
21
22// The global pool allocator uses a thread-local static pool resource, which
23// isn't guaranteed to be initialized properly across DLL boundaries on Windows
24#ifdef _WIN32
25inline constexpr bool USE_POOL_ALLOCATOR = false;
26#else
27inline constexpr bool USE_POOL_ALLOCATOR = true;
28#endif
29
30template <typename Scalar>
31struct Expression;
32
33template <typename Scalar>
34constexpr void inc_ref_count(Expression<Scalar>* expr);
35template <typename Scalar>
36constexpr void dec_ref_count(Expression<Scalar>* expr);
37
43template <typename Scalar>
44using ExpressionPtr = IntrusiveSharedPtr<Expression<Scalar>>;
45
53template <typename T, typename... Args>
54static ExpressionPtr<typename T::Scalar> make_expression_ptr(Args&&... args) {
55 if constexpr (USE_POOL_ALLOCATOR) {
56 return allocate_intrusive_shared<T>(global_pool_allocator<T>(),
57 std::forward<Args>(args)...);
58 } else {
59 return make_intrusive_shared<T>(std::forward<Args>(args)...);
60 }
61}
62
63template <typename Scalar, ExpressionType T>
64struct BinaryMinusExpression;
65
66template <typename Scalar, ExpressionType T>
67struct BinaryPlusExpression;
68
69template <typename Scalar>
70struct ConstExpression;
71
72template <typename Scalar, ExpressionType T>
73struct DivExpression;
74
75template <typename Scalar, ExpressionType T>
76struct MultExpression;
77
78template <typename Scalar, ExpressionType T>
79struct UnaryMinusExpression;
80
87template <typename Scalar>
88ExpressionPtr<Scalar> constant_ptr(Scalar value);
89
95template <typename Scalar_>
96struct Expression {
101
104
107
110
113
117
120
122 std::array<ExpressionPtr<Scalar>, 2> args{nullptr, nullptr};
123
127 constexpr Expression() = default;
128
134 explicit constexpr Expression(Scalar value) : val{value} {}
135
142 : args{std::move(lhs), nullptr} {}
143
152
153 virtual ~Expression() = default;
154
162 constexpr bool is_constant(Scalar constant) const {
163 return type() == ExpressionType::CONSTANT && val == constant;
164 }
165
173 const ExpressionPtr<Scalar>& rhs) {
174 using enum ExpressionType;
175
176 // Prune expression
177 if (lhs->is_constant(Scalar(0))) {
178 // Return zero
179 return lhs;
180 } else if (rhs->is_constant(Scalar(0))) {
181 // Return zero
182 return rhs;
183 } else if (lhs->is_constant(Scalar(1))) {
184 return rhs;
185 } else if (rhs->is_constant(Scalar(1))) {
186 return lhs;
187 }
188
189 // Evaluate constant
190 if (lhs->type() == CONSTANT && rhs->type() == CONSTANT) {
191 return constant_ptr(lhs->val * rhs->val);
192 }
193
194 // Evaluate expression type
195 if (lhs->type() == CONSTANT) {
196 if (rhs->type() == LINEAR) {
198 } else if (rhs->type() == QUADRATIC) {
200 } else {
202 }
203 } else if (rhs->type() == CONSTANT) {
204 if (lhs->type() == LINEAR) {
206 } else if (lhs->type() == QUADRATIC) {
208 } else {
210 }
211 } else if (lhs->type() == LINEAR && rhs->type() == LINEAR) {
213 } else {
215 }
216 }
217
225 const ExpressionPtr<Scalar>& rhs) {
226 using enum ExpressionType;
227
228 // Prune expression
229 if (lhs->is_constant(Scalar(0))) {
230 // Return zero
231 return lhs;
232 } else if (rhs->is_constant(Scalar(1))) {
233 return lhs;
234 }
235
236 // Evaluate constant
237 if (lhs->type() == CONSTANT && rhs->type() == CONSTANT) {
238 return constant_ptr(lhs->val / rhs->val);
239 }
240
241 // Evaluate expression type
242 if (rhs->type() == CONSTANT) {
243 if (lhs->type() == LINEAR) {
245 } else if (lhs->type() == QUADRATIC) {
247 } else {
249 }
250 } else {
252 }
253 }
254
262 const ExpressionPtr<Scalar>& rhs) {
263 using enum ExpressionType;
264
265 // Prune expression
266 if (lhs == nullptr || lhs->is_constant(Scalar(0))) {
267 return rhs;
268 } else if (rhs == nullptr || rhs->is_constant(Scalar(0))) {
269 return lhs;
270 }
271
272 // Evaluate constant
273 if (lhs->type() == CONSTANT && rhs->type() == CONSTANT) {
274 return constant_ptr(lhs->val + rhs->val);
275 }
276
277 auto type = std::max(lhs->type(), rhs->type());
278 if (type == LINEAR) {
280 rhs);
281 } else if (type == QUADRATIC) {
283 rhs);
284 } else {
286 rhs);
287 }
288 }
289
300
308 const ExpressionPtr<Scalar>& rhs) {
309 using enum ExpressionType;
310
311 // Prune expression
312 if (lhs->is_constant(Scalar(0))) {
313 if (rhs->is_constant(Scalar(0))) {
314 // Return zero
315 return rhs;
316 } else {
317 return -rhs;
318 }
319 } else if (rhs->is_constant(Scalar(0))) {
320 return lhs;
321 }
322
323 // Evaluate constant
324 if (lhs->type() == CONSTANT && rhs->type() == CONSTANT) {
325 return constant_ptr(lhs->val - rhs->val);
326 }
327
328 auto type = std::max(lhs->type(), rhs->type());
329 if (type == LINEAR) {
331 rhs);
332 } else if (type == QUADRATIC) {
334 rhs);
335 } else {
337 rhs);
338 }
339 }
340
347 using enum ExpressionType;
348
349 // Prune expression
350 if (lhs->is_constant(Scalar(0))) {
351 // Return zero
352 return lhs;
353 }
354
355 // Evaluate constant
356 if (lhs->type() == CONSTANT) {
357 return constant_ptr(-lhs->val);
358 }
359
360 if (lhs->type() == LINEAR) {
362 } else if (lhs->type() == QUADRATIC) {
364 } else {
366 }
367 }
368
375 return lhs;
376 }
377
388 [[maybe_unused]] Scalar rhs) const = 0;
389
396 virtual ExpressionType type() const = 0;
397
409 return Scalar(0);
410 }
411
423 return Scalar(0);
424 }
425
438 return constant_ptr(Scalar(0));
439 }
440
453 return constant_ptr(Scalar(0));
454 }
455};
456
457template <typename Scalar>
458ExpressionPtr<Scalar> constant_ptr(Scalar value) {
460}
461
462template <typename Scalar>
463ExpressionPtr<Scalar> cbrt(const ExpressionPtr<Scalar>& x);
464template <typename Scalar>
465ExpressionPtr<Scalar> exp(const ExpressionPtr<Scalar>& x);
466template <typename Scalar>
467ExpressionPtr<Scalar> sin(const ExpressionPtr<Scalar>& x);
468template <typename Scalar>
469ExpressionPtr<Scalar> sinh(const ExpressionPtr<Scalar>& x);
470template <typename Scalar>
471ExpressionPtr<Scalar> sqrt(const ExpressionPtr<Scalar>& x);
472
479template <typename Scalar, ExpressionType T>
490
491 Scalar value(Scalar lhs, Scalar rhs) const override { return lhs - rhs; }
492
493 ExpressionType type() const override { return T; }
494
496 return parent_adjoint;
497 }
498
500 return -parent_adjoint;
501 }
502
508
514};
515
522template <typename Scalar, ExpressionType T>
533
534 Scalar value(Scalar lhs, Scalar rhs) const override { return lhs + rhs; }
535
536 ExpressionType type() const override { return T; }
537
539 return parent_adjoint;
540 }
541
543 return parent_adjoint;
544 }
545
551
557};
558
564template <typename Scalar>
572 : Expression<Scalar>{std::move(lhs)} {}
573
574 Scalar value(Scalar x, Scalar) const override {
575 using std::cbrt;
576 return cbrt(x);
577 }
578
579 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
580
582 using std::cbrt;
583
584 Scalar c = cbrt(x);
585 return parent_adjoint / (Scalar(3) * c * c);
586 }
587
590 const ExpressionPtr<Scalar>& parent_adjoint) const override {
591 auto c = cbrt(x);
592 return parent_adjoint / (constant_ptr(Scalar(3)) * c * c);
593 }
594};
595
602template <typename Scalar>
604 using enum ExpressionType;
605 using std::cbrt;
606
607 // Evaluate constant
608 if (x->type() == CONSTANT) {
609 if (x->val == Scalar(0)) {
610 // Return zero
611 return x;
612 } else if (x->val == Scalar(-1) || x->val == Scalar(1)) {
613 return x;
614 } else {
615 return constant_ptr(cbrt(x->val));
616 }
617 }
618
619 return make_expression_ptr<CbrtExpression<Scalar>>(x);
620}
621
627template <typename Scalar>
634 explicit constexpr ConstExpression(Scalar value)
635 : Expression<Scalar>{value} {}
636
637 Scalar value(Scalar, Scalar) const override { return this->val; }
638
639 ExpressionType type() const override { return ExpressionType::CONSTANT; }
640};
641
647template <typename Scalar>
652 constexpr DecisionVariableExpression() = default;
653
661
662 Scalar value(Scalar, Scalar) const override { return this->val; }
663
664 ExpressionType type() const override { return ExpressionType::LINEAR; }
665};
666
673template <typename Scalar, ExpressionType T>
683
684 Scalar value(Scalar lhs, Scalar rhs) const override { return lhs / rhs; }
685
686 ExpressionType type() const override { return T; }
687
689 return parent_adjoint / rhs;
690 };
691
693 return parent_adjoint * -lhs / (rhs * rhs);
694 }
695
701
707};
708
715template <typename Scalar, ExpressionType T>
725
726 Scalar value(Scalar lhs, Scalar rhs) const override { return lhs * rhs; }
727
728 ExpressionType type() const override { return T; }
729
731 Scalar parent_adjoint) const override {
732 return parent_adjoint * rhs;
733 }
734
736 Scalar parent_adjoint) const override {
737 return parent_adjoint * lhs;
738 }
739
746
753};
754
761template <typename Scalar, ExpressionType T>
769 : Expression<Scalar>{std::move(lhs)} {}
770
771 Scalar value(Scalar lhs, Scalar) const override { return -lhs; }
772
773 ExpressionType type() const override { return T; }
774
776 return -parent_adjoint;
777 }
778
784};
785
792template <typename Scalar>
793constexpr void inc_ref_count(Expression<Scalar>* expr) {
794 ++expr->ref_count;
795}
796
803template <typename Scalar>
804constexpr void dec_ref_count(Expression<Scalar>* expr) {
805 // If a deeply nested tree is being deallocated all at once, calling the
806 // Expression destructor when expr's refcount reaches zero can cause a stack
807 // overflow. Instead, we iterate over its children to decrement their
808 // refcounts and deallocate them.
809 gch::small_vector<Expression<Scalar>*> stack;
810 stack.emplace_back(expr);
811
812 while (!stack.empty()) {
813 auto elem = stack.back();
814 stack.pop_back();
815
816 // Decrement the current node's refcount. If it reaches zero, deallocate the
817 // node and enqueue its children so their refcounts are decremented too.
818 if (--elem->ref_count == 0) {
819 if (elem->adjoint_expr != nullptr) {
820 stack.emplace_back(elem->adjoint_expr.get());
821 }
822 for (auto& arg : elem->args) {
823 if (arg != nullptr) {
824 stack.emplace_back(arg.get());
825 }
826 }
827
828 // Not calling the destructor here is safe because it only decrements
829 // refcounts, which was already done above.
830 if constexpr (USE_POOL_ALLOCATOR) {
831 auto alloc = global_pool_allocator<Expression<Scalar>>();
832 std::allocator_traits<decltype(alloc)>::deallocate(
833 alloc, elem, sizeof(Expression<Scalar>));
834 }
835 }
836 }
837}
838
844template <typename Scalar>
852 : Expression<Scalar>{std::move(lhs)} {}
853
854 Scalar value(Scalar x, Scalar) const override {
855 using std::abs;
856 return abs(x);
857 }
858
859 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
860
862 if (x < Scalar(0)) {
863 return -parent_adjoint;
864 } else if (x > Scalar(0)) {
865 return parent_adjoint;
866 } else {
867 return Scalar(0);
868 }
869 }
870
873 const ExpressionPtr<Scalar>& parent_adjoint) const override {
874 if (x->val < Scalar(0)) {
875 return -parent_adjoint;
876 } else if (x->val > Scalar(0)) {
877 return parent_adjoint;
878 } else {
879 return constant_ptr(Scalar(0));
880 }
881 }
882};
883
890template <typename Scalar>
892 using enum ExpressionType;
893 using std::abs;
894
895 // Prune expression
896 if (x->is_constant(Scalar(0))) {
897 // Return zero
898 return x;
899 }
900
901 // Evaluate constant
902 if (x->type() == CONSTANT) {
903 return constant_ptr(abs(x->val));
904 }
905
906 return make_expression_ptr<AbsExpression<Scalar>>(x);
907}
908
914template <typename Scalar>
922 : Expression<Scalar>{std::move(lhs)} {}
923
924 Scalar value(Scalar x, Scalar) const override {
925 using std::acos;
926 return acos(x);
927 }
928
929 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
930
932 using std::sqrt;
933 return -parent_adjoint / sqrt(Scalar(1) - x * x);
934 }
935
938 const ExpressionPtr<Scalar>& parent_adjoint) const override {
939 return -parent_adjoint / sqrt(constant_ptr(Scalar(1)) - x * x);
940 }
941};
942
949template <typename Scalar>
951 using enum ExpressionType;
952 using std::acos;
953
954 // Prune expression
955 if (x->is_constant(Scalar(0))) {
956 return constant_ptr(Scalar(std::numbers::pi) / Scalar(2));
957 }
958
959 // Evaluate constant
960 if (x->type() == CONSTANT) {
961 return constant_ptr(acos(x->val));
962 }
963
964 return make_expression_ptr<AcosExpression<Scalar>>(x);
965}
966
972template <typename Scalar>
980 : Expression<Scalar>{std::move(lhs)} {}
981
982 Scalar value(Scalar x, Scalar) const override {
983 using std::asin;
984 return asin(x);
985 }
986
987 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
988
990 using std::sqrt;
991 return parent_adjoint / sqrt(Scalar(1) - x * x);
992 }
993
996 const ExpressionPtr<Scalar>& parent_adjoint) const override {
997 return parent_adjoint / sqrt(constant_ptr(Scalar(1)) - x * x);
998 }
999};
1000
1007template <typename Scalar>
1009 using enum ExpressionType;
1010 using std::asin;
1011
1012 // Prune expression
1013 if (x->is_constant(Scalar(0))) {
1014 // Return zero
1015 return x;
1016 }
1017
1018 // Evaluate constant
1019 if (x->type() == CONSTANT) {
1020 return constant_ptr(asin(x->val));
1021 }
1022
1023 return make_expression_ptr<AsinExpression<Scalar>>(x);
1024}
1025
1031template <typename Scalar>
1039 : Expression<Scalar>{std::move(lhs)} {}
1040
1041 Scalar value(Scalar x, Scalar) const override {
1042 using std::atan;
1043 return atan(x);
1044 }
1045
1046 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1047
1049 return parent_adjoint / (Scalar(1) + x * x);
1050 }
1051
1054 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1055 return parent_adjoint / (constant_ptr(Scalar(1)) + x * x);
1056 }
1057};
1058
1065template <typename Scalar>
1067 using enum ExpressionType;
1068 using std::atan;
1069
1070 // Prune expression
1071 if (x->is_constant(Scalar(0))) {
1072 // Return zero
1073 return x;
1074 }
1075
1076 // Evaluate constant
1077 if (x->type() == CONSTANT) {
1078 return constant_ptr(atan(x->val));
1079 }
1080
1081 return make_expression_ptr<AtanExpression<Scalar>>(x);
1082}
1083
1089template <typename Scalar>
1099 : Expression<Scalar>{std::move(lhs), std::move(rhs)} {}
1100
1101 Scalar value(Scalar y, Scalar x) const override {
1102 using std::atan2;
1103 return atan2(y, x);
1104 }
1105
1106 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1107
1109 return parent_adjoint * x / (y * y + x * x);
1110 }
1111
1113 return parent_adjoint * -y / (y * y + x * x);
1114 }
1115
1118 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1119 return parent_adjoint * x / (y * y + x * x);
1120 }
1121
1124 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1125 return parent_adjoint * -y / (y * y + x * x);
1126 }
1127};
1128
1136template <typename Scalar>
1138 const ExpressionPtr<Scalar>& x) {
1139 using enum ExpressionType;
1140 using std::atan2;
1141
1142 // Prune expression
1143 if (y->is_constant(Scalar(0))) {
1144 // Return zero
1145 return y;
1146 } else if (x->is_constant(Scalar(0))) {
1147 return constant_ptr(Scalar(std::numbers::pi) / Scalar(2));
1148 }
1149
1150 // Evaluate constant
1151 if (y->type() == CONSTANT && x->type() == CONSTANT) {
1152 return constant_ptr(atan2(y->val, x->val));
1153 }
1154
1155 return make_expression_ptr<Atan2Expression<Scalar>>(y, x);
1156}
1157
1163template <typename Scalar>
1171 : Expression<Scalar>{std::move(lhs)} {}
1172
1173 Scalar value(Scalar x, Scalar) const override {
1174 using std::cos;
1175 return cos(x);
1176 }
1177
1178 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1179
1181 using std::sin;
1182 return parent_adjoint * -sin(x);
1183 }
1184
1187 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1188 return parent_adjoint * -sin(x);
1189 }
1190};
1191
1198template <typename Scalar>
1200 using enum ExpressionType;
1201 using std::cos;
1202
1203 // Prune expression
1204 if (x->is_constant(Scalar(0))) {
1205 return constant_ptr(Scalar(1));
1206 }
1207
1208 // Evaluate constant
1209 if (x->type() == CONSTANT) {
1210 return constant_ptr(cos(x->val));
1211 }
1212
1213 return make_expression_ptr<CosExpression<Scalar>>(x);
1214}
1215
1221template <typename Scalar>
1229 : Expression<Scalar>{std::move(lhs)} {}
1230
1231 Scalar value(Scalar x, Scalar) const override {
1232 using std::cosh;
1233 return cosh(x);
1234 }
1235
1236 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1237
1239 using std::sinh;
1240 return parent_adjoint * sinh(x);
1241 }
1242
1245 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1246 return parent_adjoint * sinh(x);
1247 }
1248};
1249
1256template <typename Scalar>
1258 using enum ExpressionType;
1259 using std::cosh;
1260
1261 // Prune expression
1262 if (x->is_constant(Scalar(0))) {
1263 return constant_ptr(Scalar(1));
1264 }
1265
1266 // Evaluate constant
1267 if (x->type() == CONSTANT) {
1268 return constant_ptr(cosh(x->val));
1269 }
1270
1271 return make_expression_ptr<CoshExpression<Scalar>>(x);
1272}
1273
1279template <typename Scalar>
1287 : Expression<Scalar>{std::move(lhs)} {}
1288
1289 Scalar value(Scalar x, Scalar) const override {
1290 using std::erf;
1291 return erf(x);
1292 }
1293
1294 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1295
1297 using std::exp;
1298 return parent_adjoint * Scalar(2.0 * std::numbers::inv_sqrtpi) *
1299 exp(-x * x);
1300 }
1301
1304 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1305 return parent_adjoint *
1306 constant_ptr(Scalar(2.0 * std::numbers::inv_sqrtpi)) * exp(-x * x);
1307 }
1308};
1309
1316template <typename Scalar>
1318 using enum ExpressionType;
1319 using std::erf;
1320
1321 // Prune expression
1322 if (x->is_constant(Scalar(0))) {
1323 // Return zero
1324 return x;
1325 }
1326
1327 // Evaluate constant
1328 if (x->type() == CONSTANT) {
1329 return constant_ptr(erf(x->val));
1330 }
1331
1332 return make_expression_ptr<ErfExpression<Scalar>>(x);
1333}
1334
1340template <typename Scalar>
1348 : Expression<Scalar>{std::move(lhs)} {}
1349
1350 Scalar value(Scalar x, Scalar) const override {
1351 using std::exp;
1352 return exp(x);
1353 }
1354
1355 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1356
1358 using std::exp;
1359 return parent_adjoint * exp(x);
1360 }
1361
1364 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1365 return parent_adjoint * exp(x);
1366 }
1367};
1368
1375template <typename Scalar>
1377 using enum ExpressionType;
1378 using std::exp;
1379
1380 // Prune expression
1381 if (x->is_constant(Scalar(0))) {
1382 return constant_ptr(Scalar(1));
1383 }
1384
1385 // Evaluate constant
1386 if (x->type() == CONSTANT) {
1387 return constant_ptr(exp(x->val));
1388 }
1389
1390 return make_expression_ptr<ExpExpression<Scalar>>(x);
1391}
1392
1393template <typename Scalar>
1394ExpressionPtr<Scalar> hypot(const ExpressionPtr<Scalar>& x,
1395 const ExpressionPtr<Scalar>& y);
1396
1402template <typename Scalar>
1412 : Expression<Scalar>{std::move(lhs), std::move(rhs)} {}
1413
1414 Scalar value(Scalar x, Scalar y) const override {
1415 using std::hypot;
1416 return hypot(x, y);
1417 }
1418
1419 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1420
1422 using std::hypot;
1423 return parent_adjoint * x / hypot(x, y);
1424 }
1425
1427 using std::hypot;
1428 return parent_adjoint * y / hypot(x, y);
1429 }
1430
1433 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1434 return parent_adjoint * x / hypot(x, y);
1435 }
1436
1439 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1440 return parent_adjoint * y / hypot(x, y);
1441 }
1442};
1443
1451template <typename Scalar>
1453 const ExpressionPtr<Scalar>& y) {
1454 using enum ExpressionType;
1455 using std::hypot;
1456
1457 // Prune expression
1458 if (x->is_constant(Scalar(0))) {
1459 return y;
1460 } else if (y->is_constant(Scalar(0))) {
1461 return x;
1462 }
1463
1464 // Evaluate constant
1465 if (x->type() == CONSTANT && y->type() == CONSTANT) {
1466 return constant_ptr(hypot(x->val, y->val));
1467 }
1468
1469 return make_expression_ptr<HypotExpression<Scalar>>(x, y);
1470}
1471
1477template <typename Scalar>
1485 : Expression<Scalar>{std::move(lhs)} {}
1486
1487 Scalar value(Scalar x, Scalar) const override {
1488 using std::log;
1489 return log(x);
1490 }
1491
1492 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1493
1495 return parent_adjoint / x;
1496 }
1497
1500 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1501 return parent_adjoint / x;
1502 }
1503};
1504
1511template <typename Scalar>
1513 using enum ExpressionType;
1514 using std::log;
1515
1516 // Prune expression
1517 if (x->is_constant(Scalar(0))) {
1518 // Return zero
1519 return x;
1520 }
1521
1522 // Evaluate constant
1523 if (x->type() == CONSTANT) {
1524 return constant_ptr(log(x->val));
1525 }
1526
1527 return make_expression_ptr<LogExpression<Scalar>>(x);
1528}
1529
1535template <typename Scalar>
1543 : Expression<Scalar>{std::move(lhs)} {}
1544
1545 Scalar value(Scalar x, Scalar) const override {
1546 using std::log10;
1547 return log10(x);
1548 }
1549
1550 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1551
1553 return parent_adjoint / (Scalar(std::numbers::ln10) * x);
1554 }
1555
1558 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1559 return parent_adjoint / (constant_ptr(Scalar(std::numbers::ln10)) * x);
1560 }
1561};
1562
1569template <typename Scalar>
1571 using enum ExpressionType;
1572 using std::log10;
1573
1574 // Prune expression
1575 if (x->is_constant(Scalar(0))) {
1576 // Return zero
1577 return x;
1578 }
1579
1580 // Evaluate constant
1581 if (x->type() == CONSTANT) {
1582 return constant_ptr(log10(x->val));
1583 }
1584
1585 return make_expression_ptr<Log10Expression<Scalar>>(x);
1586}
1587
1588template <typename Scalar>
1589ExpressionPtr<Scalar> pow(const ExpressionPtr<Scalar>& base,
1590 const ExpressionPtr<Scalar>& power);
1591
1598template <typename Scalar, ExpressionType T>
1608
1609 Scalar value(Scalar base, Scalar power) const override {
1610 using std::pow;
1611 return pow(base, power);
1612 }
1613
1614 ExpressionType type() const override { return T; }
1615
1617 Scalar parent_adjoint) const override {
1618 using std::pow;
1619 return parent_adjoint * pow(base, power - Scalar(1)) * power;
1620 }
1621
1623 Scalar parent_adjoint) const override {
1624 using std::log;
1625 using std::pow;
1626
1627 // Since x log(x) -> 0 as x -> 0
1628 if (base == Scalar(0)) {
1629 return Scalar(0);
1630 } else {
1631 return parent_adjoint * pow(base, power) * log(base);
1632 }
1633 }
1634
1637 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1638 return parent_adjoint * pow(base, power - constant_ptr(Scalar(1))) * power;
1639 }
1640
1643 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1644 // Since x log(x) -> 0 as x -> 0
1645 if (base->val == Scalar(0)) {
1646 // Return zero
1647 return base;
1648 } else {
1649 return parent_adjoint * pow(base, power) * log(base);
1650 }
1651 }
1652};
1653
1661template <typename Scalar>
1664 using enum ExpressionType;
1665 using std::pow;
1666
1667 // Prune expression
1668 if (base->is_constant(Scalar(0))) {
1669 // Return zero
1670 return base;
1671 } else if (base->is_constant(Scalar(1))) {
1672 // Return one
1673 return base;
1674 }
1675 if (power->is_constant(Scalar(0))) {
1676 return constant_ptr(Scalar(1));
1677 } else if (power->is_constant(Scalar(1))) {
1678 return base;
1679 }
1680
1681 // Evaluate constant
1682 if (base->type() == CONSTANT && power->type() == CONSTANT) {
1683 return constant_ptr(pow(base->val, power->val));
1684 }
1685
1686 if (power->is_constant(Scalar(2))) {
1687 if (base->type() == LINEAR) {
1688 return make_expression_ptr<MultExpression<Scalar, QUADRATIC>>(base, base);
1689 } else {
1690 return make_expression_ptr<MultExpression<Scalar, NONLINEAR>>(base, base);
1691 }
1692 }
1693
1694 return make_expression_ptr<PowExpression<Scalar, NONLINEAR>>(base, power);
1695}
1696
1702template <typename Scalar>
1710 : Expression<Scalar>{std::move(lhs)} {}
1711
1712 Scalar value(Scalar x, Scalar) const override {
1713 if (x < Scalar(0)) {
1714 return Scalar(-1);
1715 } else if (x == Scalar(0)) {
1716 return Scalar(0);
1717 } else {
1718 return Scalar(1);
1719 }
1720 }
1721
1722 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1723};
1724
1731template <typename Scalar>
1733 using enum ExpressionType;
1734
1735 // Evaluate constant
1736 if (x->type() == CONSTANT) {
1737 if (x->val < Scalar(0)) {
1738 return constant_ptr(Scalar(-1));
1739 } else if (x->val == Scalar(0)) {
1740 // Return zero
1741 return x;
1742 } else {
1743 return constant_ptr(Scalar(1));
1744 }
1745 }
1746
1747 return make_expression_ptr<SignExpression<Scalar>>(x);
1748}
1749
1755template <typename Scalar>
1763 : Expression<Scalar>{std::move(lhs)} {}
1764
1765 Scalar value(Scalar x, Scalar) const override {
1766 using std::sin;
1767 return sin(x);
1768 }
1769
1770 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1771
1773 using std::cos;
1774 return parent_adjoint * cos(x);
1775 }
1776
1779 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1780 return parent_adjoint * cos(x);
1781 }
1782};
1783
1790template <typename Scalar>
1792 using enum ExpressionType;
1793 using std::sin;
1794
1795 // Prune expression
1796 if (x->is_constant(Scalar(0))) {
1797 // Return zero
1798 return x;
1799 }
1800
1801 // Evaluate constant
1802 if (x->type() == CONSTANT) {
1803 return constant_ptr(sin(x->val));
1804 }
1805
1806 return make_expression_ptr<SinExpression<Scalar>>(x);
1807}
1808
1814template <typename Scalar>
1822 : Expression<Scalar>{std::move(lhs)} {}
1823
1824 Scalar value(Scalar x, Scalar) const override {
1825 using std::sinh;
1826 return sinh(x);
1827 }
1828
1829 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1830
1832 using std::cosh;
1833 return parent_adjoint * cosh(x);
1834 }
1835
1838 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1839 return parent_adjoint * cosh(x);
1840 }
1841};
1842
1849template <typename Scalar>
1851 using enum ExpressionType;
1852 using std::sinh;
1853
1854 // Prune expression
1855 if (x->is_constant(Scalar(0))) {
1856 // Return zero
1857 return x;
1858 }
1859
1860 // Evaluate constant
1861 if (x->type() == CONSTANT) {
1862 return constant_ptr(sinh(x->val));
1863 }
1864
1865 return make_expression_ptr<SinhExpression<Scalar>>(x);
1866}
1867
1873template <typename Scalar>
1881 : Expression<Scalar>{std::move(lhs)} {}
1882
1883 Scalar value(Scalar x, Scalar) const override {
1884 using std::sqrt;
1885 return sqrt(x);
1886 }
1887
1888 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1889
1891 using std::sqrt;
1892 return parent_adjoint / (Scalar(2) * sqrt(x));
1893 }
1894
1897 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1898 return parent_adjoint / (constant_ptr(Scalar(2)) * sqrt(x));
1899 }
1900};
1901
1908template <typename Scalar>
1910 using enum ExpressionType;
1911 using std::sqrt;
1912
1913 // Evaluate constant
1914 if (x->type() == CONSTANT) {
1915 if (x->val == Scalar(0)) {
1916 // Return zero
1917 return x;
1918 } else if (x->val == Scalar(1)) {
1919 return x;
1920 } else {
1921 return constant_ptr(sqrt(x->val));
1922 }
1923 }
1924
1925 return make_expression_ptr<SqrtExpression<Scalar>>(x);
1926}
1927
1933template <typename Scalar>
1941 : Expression<Scalar>{std::move(lhs)} {}
1942
1943 Scalar value(Scalar x, Scalar) const override {
1944 using std::tan;
1945 return tan(x);
1946 }
1947
1948 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
1949
1951 using std::cos;
1952
1953 auto c = cos(x);
1954 return parent_adjoint / (c * c);
1955 }
1956
1959 const ExpressionPtr<Scalar>& parent_adjoint) const override {
1960 auto c = cos(x);
1961 return parent_adjoint / (c * c);
1962 }
1963};
1964
1971template <typename Scalar>
1973 using enum ExpressionType;
1974 using std::tan;
1975
1976 // Prune expression
1977 if (x->is_constant(Scalar(0))) {
1978 // Return zero
1979 return x;
1980 }
1981
1982 // Evaluate constant
1983 if (x->type() == CONSTANT) {
1984 return constant_ptr(tan(x->val));
1985 }
1986
1987 return make_expression_ptr<TanExpression<Scalar>>(x);
1988}
1989
1995template <typename Scalar>
2003 : Expression<Scalar>{std::move(lhs)} {}
2004
2005 Scalar value(Scalar x, Scalar) const override {
2006 using std::tanh;
2007 return tanh(x);
2008 }
2009
2010 ExpressionType type() const override { return ExpressionType::NONLINEAR; }
2011
2013 using std::cosh;
2014
2015 auto c = cosh(x);
2016 return parent_adjoint / (c * c);
2017 }
2018
2021 const ExpressionPtr<Scalar>& parent_adjoint) const override {
2022 auto c = cosh(x);
2023 return parent_adjoint / (c * c);
2024 }
2025};
2026
2033template <typename Scalar>
2035 using enum ExpressionType;
2036 using std::tanh;
2037
2038 // Prune expression
2039 if (x->is_constant(Scalar(0))) {
2040 // Return zero
2041 return x;
2042 }
2043
2044 // Evaluate constant
2045 if (x->type() == CONSTANT) {
2046 return constant_ptr(tanh(x->val));
2047 }
2048
2049 return make_expression_ptr<TanhExpression<Scalar>>(x);
2050}
2051
2052} // namespace slp::detail
Definition intrusive_shared_ptr.hpp:29
Definition expression.hpp:845
constexpr AbsExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:851
ExpressionType type() const override
Definition expression.hpp:859
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:861
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:871
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:854
Definition expression.hpp:915
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:936
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:924
constexpr AcosExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:921
ExpressionType type() const override
Definition expression.hpp:929
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:931
Definition expression.hpp:973
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:989
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:982
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:994
ExpressionType type() const override
Definition expression.hpp:987
constexpr AsinExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:979
Definition expression.hpp:1090
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &y, const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1116
Scalar value(Scalar y, Scalar x) const override
Definition expression.hpp:1101
constexpr Atan2Expression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:1097
Scalar grad_r(Scalar y, Scalar x, Scalar parent_adjoint) const override
Definition expression.hpp:1112
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &y, const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1122
ExpressionType type() const override
Definition expression.hpp:1106
Scalar grad_l(Scalar y, Scalar x, Scalar parent_adjoint) const override
Definition expression.hpp:1108
Definition expression.hpp:1032
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1052
constexpr AtanExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1038
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1041
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1048
ExpressionType type() const override
Definition expression.hpp:1046
Definition expression.hpp:480
constexpr BinaryMinusExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:487
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:503
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:509
Scalar grad_r(Scalar, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:499
Scalar value(Scalar lhs, Scalar rhs) const override
Definition expression.hpp:491
ExpressionType type() const override
Definition expression.hpp:493
Scalar grad_l(Scalar, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:495
Definition expression.hpp:523
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:546
Scalar value(Scalar lhs, Scalar rhs) const override
Definition expression.hpp:534
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:552
constexpr BinaryPlusExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:530
ExpressionType type() const override
Definition expression.hpp:536
Scalar grad_r(Scalar, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:542
Scalar grad_l(Scalar, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:538
Definition expression.hpp:565
constexpr CbrtExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:571
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:581
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:588
ExpressionType type() const override
Definition expression.hpp:579
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:574
Definition expression.hpp:628
Scalar value(Scalar, Scalar) const override
Definition expression.hpp:637
ExpressionType type() const override
Definition expression.hpp:639
constexpr ConstExpression(Scalar value)
Definition expression.hpp:634
Definition expression.hpp:1164
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1173
ExpressionType type() const override
Definition expression.hpp:1178
constexpr CosExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1170
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1185
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1180
Definition expression.hpp:1222
ExpressionType type() const override
Definition expression.hpp:1236
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1231
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1243
constexpr CoshExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1228
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1238
Definition expression.hpp:648
constexpr DecisionVariableExpression()=default
Scalar value(Scalar, Scalar) const override
Definition expression.hpp:662
constexpr DecisionVariableExpression(Scalar value)
Definition expression.hpp:659
ExpressionType type() const override
Definition expression.hpp:664
Definition expression.hpp:674
constexpr DivExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:681
ExpressionType type() const override
Definition expression.hpp:686
Scalar grad_r(Scalar lhs, Scalar rhs, Scalar parent_adjoint) const override
Definition expression.hpp:692
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:702
Scalar grad_l(Scalar, Scalar rhs, Scalar parent_adjoint) const override
Definition expression.hpp:688
Scalar value(Scalar lhs, Scalar rhs) const override
Definition expression.hpp:684
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:696
Definition expression.hpp:1280
constexpr ErfExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1286
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1296
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1289
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1302
ExpressionType type() const override
Definition expression.hpp:1294
Definition expression.hpp:1341
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1357
ExpressionType type() const override
Definition expression.hpp:1355
constexpr ExpExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1347
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1362
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1350
Definition expression.hpp:96
Scalar val
The value of the expression node.
Definition expression.hpp:103
friend ExpressionPtr< Scalar > operator-(const ExpressionPtr< Scalar > &lhs)
Definition expression.hpp:346
int32_t col
This expression's column in a Jacobian, or -1 otherwise.
Definition expression.hpp:112
virtual Scalar grad_r(Scalar lhs, Scalar rhs, Scalar parent_adjoint) const
Definition expression.hpp:420
std::array< ExpressionPtr< Scalar >, 2 > args
Expression arguments.
Definition expression.hpp:122
uint32_t ref_count
Reference count for intrusive shared pointer.
Definition expression.hpp:119
constexpr Expression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:141
virtual ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const
Definition expression.hpp:434
virtual ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const
Definition expression.hpp:449
Scalar adjoint
The adjoint of the expression node, used during autodiff.
Definition expression.hpp:106
friend ExpressionPtr< Scalar > operator+(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs)
Definition expression.hpp:261
constexpr bool is_constant(Scalar constant) const
Definition expression.hpp:162
constexpr Expression()=default
constexpr Expression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:150
ExpressionPtr< Scalar > adjoint_expr
Definition expression.hpp:116
Scalar_ Scalar
Definition expression.hpp:100
virtual ExpressionType type() const =0
friend ExpressionPtr< Scalar > operator/(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs)
Definition expression.hpp:224
uint32_t incoming_edges
Counts incoming edges for this node.
Definition expression.hpp:109
friend ExpressionPtr< Scalar > operator-(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs)
Definition expression.hpp:307
friend ExpressionPtr< Scalar > operator*(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs)
Definition expression.hpp:172
virtual Scalar value(Scalar lhs, Scalar rhs) const =0
virtual Scalar grad_l(Scalar lhs, Scalar rhs, Scalar parent_adjoint) const
Definition expression.hpp:406
friend ExpressionPtr< Scalar > operator+=(ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs)
Definition expression.hpp:296
constexpr Expression(Scalar value)
Definition expression.hpp:134
friend ExpressionPtr< Scalar > operator+(const ExpressionPtr< Scalar > &lhs)
Definition expression.hpp:374
Definition expression.hpp:1403
constexpr HypotExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:1410
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &y, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1437
ExpressionType type() const override
Definition expression.hpp:1419
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &y, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1431
Scalar grad_l(Scalar x, Scalar y, Scalar parent_adjoint) const override
Definition expression.hpp:1421
Scalar value(Scalar x, Scalar y) const override
Definition expression.hpp:1414
Scalar grad_r(Scalar x, Scalar y, Scalar parent_adjoint) const override
Definition expression.hpp:1426
Definition expression.hpp:1536
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1545
constexpr Log10Expression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1542
ExpressionType type() const override
Definition expression.hpp:1550
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1556
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1552
Definition expression.hpp:1478
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1498
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1494
ExpressionType type() const override
Definition expression.hpp:1492
constexpr LogExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1484
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1487
Definition expression.hpp:716
Scalar value(Scalar lhs, Scalar rhs) const override
Definition expression.hpp:726
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:740
Scalar grad_l(Scalar lhs, Scalar rhs, Scalar parent_adjoint) const override
Definition expression.hpp:730
constexpr MultExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:723
ExpressionType type() const override
Definition expression.hpp:728
Scalar grad_r(Scalar lhs, Scalar rhs, Scalar parent_adjoint) const override
Definition expression.hpp:735
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &lhs, const ExpressionPtr< Scalar > &rhs, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:747
Definition expression.hpp:1599
Scalar value(Scalar base, Scalar power) const override
Definition expression.hpp:1609
Scalar grad_l(Scalar base, Scalar power, Scalar parent_adjoint) const override
Definition expression.hpp:1616
ExpressionType type() const override
Definition expression.hpp:1614
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &base, const ExpressionPtr< Scalar > &power, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1635
Scalar grad_r(Scalar base, Scalar power, Scalar parent_adjoint) const override
Definition expression.hpp:1622
ExpressionPtr< Scalar > grad_expr_r(const ExpressionPtr< Scalar > &base, const ExpressionPtr< Scalar > &power, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1641
constexpr PowExpression(ExpressionPtr< Scalar > lhs, ExpressionPtr< Scalar > rhs)
Definition expression.hpp:1606
Definition expression.hpp:1703
constexpr SignExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1709
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1712
ExpressionType type() const override
Definition expression.hpp:1722
Definition expression.hpp:1756
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1772
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1777
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1765
ExpressionType type() const override
Definition expression.hpp:1770
constexpr SinExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1762
Definition expression.hpp:1815
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1831
ExpressionType type() const override
Definition expression.hpp:1829
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1836
constexpr SinhExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1821
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1824
Definition expression.hpp:1874
ExpressionType type() const override
Definition expression.hpp:1888
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1895
constexpr SqrtExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1880
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1890
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1883
Definition expression.hpp:1934
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:1957
constexpr TanExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:1940
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:1950
ExpressionType type() const override
Definition expression.hpp:1948
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:1943
Definition expression.hpp:1996
ExpressionType type() const override
Definition expression.hpp:2010
Scalar grad_l(Scalar x, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:2012
Scalar value(Scalar x, Scalar) const override
Definition expression.hpp:2005
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &x, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:2019
constexpr TanhExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:2002
Definition expression.hpp:762
constexpr UnaryMinusExpression(ExpressionPtr< Scalar > lhs)
Definition expression.hpp:768
ExpressionPtr< Scalar > grad_expr_l(const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &, const ExpressionPtr< Scalar > &parent_adjoint) const override
Definition expression.hpp:779
Scalar grad_l(Scalar, Scalar, Scalar parent_adjoint) const override
Definition expression.hpp:775
ExpressionType type() const override
Definition expression.hpp:773
Scalar value(Scalar lhs, Scalar) const override
Definition expression.hpp:771