Sleipnir C++ API
Loading...
Searching...
No Matches
expression_functions.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <algorithm>
6#include <cmath>
7#include <concepts>
8#include <numbers>
9#include <string_view>
10#include <type_traits>
11#include <utility>
12
13#include "sleipnir/autodiff/expression.hpp"
14#include "sleipnir/autodiff/expression_type.hpp"
15
16namespace slp::detail {
20template <typename Scalar>
21struct AbsExpression final
22 : NonLeafExpression<AbsExpression<Scalar>, Scalar, 1> {
23 using AbsExpression::NonLeafExpression::NonLeafExpression;
24
26 static constexpr std::string_view NAME = "abs";
27
28 static Scalar eval(Scalar x) {
29 using std::abs;
30 return abs(x);
31 }
32
33 template <typename Value>
34 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
35 const Value& x) {
36 if constexpr (std::same_as<Value, Scalar>) {
37 if (x < Scalar(0)) {
38 g[0] = Scalar(-1);
39 } else if (x > Scalar(0)) {
40 g[0] = Scalar(1);
41 } else {
42 g[0] = Scalar(0);
43 }
44 } else {
45 g[0] = sign(x);
46 }
47 }
48};
49
54template <typename Scalar>
55ExpressionPtr<Scalar> abs(const ExpressionPtr<Scalar>& x) {
56 return fold_or_make<AbsExpression<Scalar>>(x);
57}
58
62template <typename Scalar>
63struct AcosExpression final
64 : NonLeafExpression<AcosExpression<Scalar>, Scalar, 1> {
65 using AcosExpression::NonLeafExpression::NonLeafExpression;
66
68 static constexpr std::string_view NAME = "acos";
69
70 static Scalar eval(Scalar x) {
71 using std::acos;
72 return acos(x);
73 }
74
75 template <typename Value>
76 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
77 const Value& x) {
78 using std::sqrt;
79 g[0] = lit<Value>(Scalar(-1)) / sqrt(lit<Value>(Scalar(1)) - x * x);
80 }
81};
82
87template <typename Scalar>
88ExpressionPtr<Scalar> acos(const ExpressionPtr<Scalar>& x) {
89 return fold_or_make<AcosExpression<Scalar>>(x);
90}
91
95template <typename Scalar>
96struct AsinExpression final
97 : NonLeafExpression<AsinExpression<Scalar>, Scalar, 1> {
98 using AsinExpression::NonLeafExpression::NonLeafExpression;
99
101 static constexpr std::string_view NAME = "asin";
102
103 static Scalar eval(Scalar x) {
104 using std::asin;
105 return asin(x);
106 }
107
108 template <typename Value>
109 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
110 const Value& x) {
111 using std::sqrt;
112 g[0] = lit<Value>(Scalar(1)) / sqrt(lit<Value>(Scalar(1)) - x * x);
113 }
114};
115
120template <typename Scalar>
121ExpressionPtr<Scalar> asin(const ExpressionPtr<Scalar>& x) {
122 return fold_or_make<AsinExpression<Scalar>>(x);
123}
124
128template <typename Scalar>
129struct AtanExpression final
130 : NonLeafExpression<AtanExpression<Scalar>, Scalar, 1> {
131 using AtanExpression::NonLeafExpression::NonLeafExpression;
132
134 static constexpr std::string_view NAME = "atan";
135
136 static Scalar eval(Scalar x) {
137 using std::atan;
138 return atan(x);
139 }
140
141 template <typename Value>
142 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
143 const Value& x) {
144 g[0] = lit<Value>(Scalar(1)) / (lit<Value>(Scalar(1)) + x * x);
145 }
146};
147
152template <typename Scalar>
153ExpressionPtr<Scalar> atan(const ExpressionPtr<Scalar>& x) {
154 return fold_or_make<AtanExpression<Scalar>>(x);
155}
156
160template <typename Scalar>
161struct Atan2Expression final
162 : NonLeafExpression<Atan2Expression<Scalar>, Scalar, 2> {
163 using Atan2Expression::NonLeafExpression::NonLeafExpression;
164
166 static constexpr std::string_view NAME = "atan2";
167
168 static Scalar eval(Scalar y, Scalar x) {
169 using std::atan2;
170 return atan2(y, x);
171 }
172
173 template <typename Value>
174 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
175 const Value& y, const Value& x) {
176 Value d = y * y + x * x;
177 g[0] = x / d;
178 g[1] = -y / d;
179 }
180};
181
187template <typename Scalar>
188ExpressionPtr<Scalar> atan2(const ExpressionPtr<Scalar>& y,
189 const ExpressionPtr<Scalar>& x) {
190 return fold_or_make<Atan2Expression<Scalar>>(y, x);
191}
192
196template <typename Scalar>
197struct CbrtExpression final
198 : NonLeafExpression<CbrtExpression<Scalar>, Scalar, 1> {
199 using CbrtExpression::NonLeafExpression::NonLeafExpression;
200
202 static constexpr std::string_view NAME = "cbrt";
203
204 static Scalar eval(Scalar x) {
205 using std::cbrt;
206 return cbrt(x);
207 }
208
209 template <typename Value>
210 static void eval_grad(ArgArray<Value>& g, const Value& val,
211 [[maybe_unused]] const Value& x) {
212 g[0] = lit<Value>(Scalar(1)) / (lit<Value>(Scalar(3)) * val * val);
213 }
214};
215
220template <typename Scalar>
221ExpressionPtr<Scalar> cbrt(const ExpressionPtr<Scalar>& x) {
222 return fold_or_make<CbrtExpression<Scalar>>(x);
223}
224
228template <typename Scalar>
229struct CosExpression final
230 : NonLeafExpression<CosExpression<Scalar>, Scalar, 1> {
231 using CosExpression::NonLeafExpression::NonLeafExpression;
232
234 static constexpr std::string_view NAME = "cos";
235
236 static Scalar eval(Scalar x) {
237 using std::cos;
238 return cos(x);
239 }
240
241 template <typename Value>
242 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
243 const Value& x) {
244 using std::sin;
245 g[0] = -sin(x);
246 }
247};
248
253template <typename Scalar>
254ExpressionPtr<Scalar> cos(const ExpressionPtr<Scalar>& x) {
255 return fold_or_make<CosExpression<Scalar>>(x);
256}
257
261template <typename Scalar>
262struct CoshExpression final
263 : NonLeafExpression<CoshExpression<Scalar>, Scalar, 1> {
264 using CoshExpression::NonLeafExpression::NonLeafExpression;
265
267 static constexpr std::string_view NAME = "cosh";
268
269 static Scalar eval(Scalar x) {
270 using std::cosh;
271 return cosh(x);
272 }
273
274 template <typename Value>
275 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
276 const Value& x) {
277 using std::sinh;
278 g[0] = sinh(x);
279 }
280};
281
286template <typename Scalar>
287ExpressionPtr<Scalar> cosh(const ExpressionPtr<Scalar>& x) {
288 return fold_or_make<CoshExpression<Scalar>>(x);
289}
290
294template <typename Scalar>
295struct ErfExpression final
296 : NonLeafExpression<ErfExpression<Scalar>, Scalar, 1> {
297 using ErfExpression::NonLeafExpression::NonLeafExpression;
298
300 static constexpr std::string_view NAME = "erf";
301
302 static Scalar eval(Scalar x) {
303 using std::erf;
304 return erf(x);
305 }
306
307 template <typename Value>
308 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
309 const Value& x) {
310 using std::exp;
311 g[0] = lit<Value>(Scalar(2.0 * std::numbers::inv_sqrtpi)) * exp(-x * x);
312 }
313};
314
319template <typename Scalar>
320ExpressionPtr<Scalar> erf(const ExpressionPtr<Scalar>& x) {
321 return fold_or_make<ErfExpression<Scalar>>(x);
322}
323
327template <typename Scalar>
328struct ExpExpression final
329 : NonLeafExpression<ExpExpression<Scalar>, Scalar, 1> {
330 using ExpExpression::NonLeafExpression::NonLeafExpression;
331
333 static constexpr std::string_view NAME = "exp";
334
335 static Scalar eval(Scalar x) {
336 using std::exp;
337 return exp(x);
338 }
339
340 template <typename Value>
341 static void eval_grad(ArgArray<Value>& g, const Value& val,
342 [[maybe_unused]] const Value& x) {
343 g[0] = val;
344 }
345};
346
351template <typename Scalar>
352ExpressionPtr<Scalar> exp(const ExpressionPtr<Scalar>& x) {
353 return fold_or_make<ExpExpression<Scalar>>(x);
354}
355
356template <typename Scalar>
357ExpressionPtr<Scalar> hypot(const ExpressionPtr<Scalar>& x,
358 const ExpressionPtr<Scalar>& y);
359
363template <typename Scalar>
365 : NonLeafExpression<Hypot2Expression<Scalar>, Scalar, 2> {
366 using Hypot2Expression::NonLeafExpression::NonLeafExpression;
367
369 static constexpr std::string_view NAME = "hypot";
370
371 static Scalar eval(Scalar x, Scalar y) {
372 using std::hypot;
373 return hypot(x, y);
374 }
375
376 template <typename Value>
377 static void eval_grad(ArgArray<Value>& g, const Value& val, const Value& x,
378 const Value& y) {
379 g[0] = x / val;
380 g[1] = y / val;
381 }
382};
383
389template <typename Scalar>
390ExpressionPtr<Scalar> hypot(const ExpressionPtr<Scalar>& x,
391 const ExpressionPtr<Scalar>& y) {
392 // Prune expression
393 if (x->is_constant(Scalar(0))) {
394 return abs(y);
395 } else if (y->is_constant(Scalar(0))) {
396 return abs(x);
397 }
398
399 return fold_or_make<Hypot2Expression<Scalar>>(x, y);
400}
401
402template <typename Scalar>
403ExpressionPtr<Scalar> hypot(const ExpressionPtr<Scalar>& x,
404 const ExpressionPtr<Scalar>& y,
405 const ExpressionPtr<Scalar>& z);
406
410template <typename Scalar>
412 : NonLeafExpression<Hypot3Expression<Scalar>, Scalar, 3> {
413 using Hypot3Expression::NonLeafExpression::NonLeafExpression;
414
416 static constexpr std::string_view NAME = "hypot";
417
418 static Scalar eval(Scalar x, Scalar y, Scalar z) {
419 using std::hypot;
420 return hypot(x, y, z);
421 }
422
423 template <typename Value>
424 static void eval_grad(ArgArray<Value>& g, const Value& val, const Value& x,
425 const Value& y, const Value& z) {
426 g[0] = x / val;
427 g[1] = y / val;
428 g[2] = z / val;
429 }
430};
431
438template <typename Scalar>
439ExpressionPtr<Scalar> hypot(const ExpressionPtr<Scalar>& x,
440 const ExpressionPtr<Scalar>& y,
441 const ExpressionPtr<Scalar>& z) {
442 // Prune expression
443 if (x->is_constant(Scalar(0))) {
444 return hypot(y, z);
445 } else if (y->is_constant(Scalar(0))) {
446 return hypot(x, z);
447 } else if (z->is_constant(Scalar(0))) {
448 return hypot(x, y);
449 }
450
451 return fold_or_make<Hypot3Expression<Scalar>>(x, y, z);
452}
453
459template <typename Scalar>
461 : NonLeafExpression<IfElseExpression<Scalar>, Scalar, 4> {
463 static constexpr std::string_view NAME = "if-else";
464
466 bool (*cond)(Scalar a, Scalar b);
467
475 constexpr IfElseExpression(bool (*cond)(Scalar a, Scalar b),
478 : IfElseExpression::NonLeafExpression{std::move(a), std::move(b),
479 std::move(t), std::move(f)},
480 cond{cond} {}
481
482 Scalar eval(Scalar a, Scalar b, Scalar t, Scalar f) const {
483 return cond(a, b) ? t : f;
484 }
485
486 template <typename Value>
487 void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
488 const Value& a, const Value& b,
489 [[maybe_unused]] const Value& t,
490 [[maybe_unused]] const Value& f) const {
491 // a and b have zero gradient
492 if constexpr (std::same_as<Value, Scalar>) {
493 bool c = cond(a, b);
494 g[2] = c ? Scalar(1) : Scalar(0);
495 g[3] = c ? Scalar(0) : Scalar(1);
496 } else {
497 auto zero = constant_ptr(Scalar(0));
498 auto one = constant_ptr(Scalar(1));
499 g[2] = if_else(cond, a, b, one, zero);
500 g[3] = if_else(cond, a, b, zero, one);
501 }
502 }
503};
504
513template <typename Scalar>
514ExpressionPtr<Scalar> if_else(
515 std::type_identity_t<bool (*)(Scalar a, Scalar b)> cond,
516 const ExpressionPtr<Scalar>& a, const ExpressionPtr<Scalar>& b,
517 const ExpressionPtr<Scalar>& t, const ExpressionPtr<Scalar>& f) {
518 using enum ExpressionType;
519
520 // Prune expression
521 if (t == f) {
522 // Return t, which both branches currently are
523 return t;
524 } else if (t->type() == CONSTANT && f->type() == CONSTANT &&
525 t->val == f->val) {
526 // Return t, which both branches currently equal
527 return t;
528 }
529
530 // Evaluate constant condition
531 if (a->type() == CONSTANT && b->type() == CONSTANT) {
532 return cond(a->val, b->val) ? t : f;
533 }
534
535 return make_expression_ptr<IfElseExpression<Scalar>>(cond, a, b, t, f);
536}
537
541template <typename Scalar>
542struct LogExpression final
543 : NonLeafExpression<LogExpression<Scalar>, Scalar, 1> {
544 using LogExpression::NonLeafExpression::NonLeafExpression;
545
547 static constexpr std::string_view NAME = "log";
548
549 static Scalar eval(Scalar x) {
550 using std::log;
551 return log(x);
552 }
553
554 template <typename Value>
555 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
556 const Value& x) {
557 g[0] = lit<Value>(Scalar(1)) / x;
558 }
559};
560
565template <typename Scalar>
566ExpressionPtr<Scalar> log(const ExpressionPtr<Scalar>& x) {
567 return fold_or_make<LogExpression<Scalar>>(x);
568}
569
573template <typename Scalar>
574struct Log10Expression final
575 : NonLeafExpression<Log10Expression<Scalar>, Scalar, 1> {
576 using Log10Expression::NonLeafExpression::NonLeafExpression;
577
579 static constexpr std::string_view NAME = "log10";
580
581 static Scalar eval(Scalar x) {
582 using std::log10;
583 return log10(x);
584 }
585
586 template <typename Value>
587 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
588 const Value& x) {
589 g[0] = lit<Value>(Scalar(1)) / (lit<Value>(Scalar(std::numbers::ln10)) * x);
590 }
591};
592
597template <typename Scalar>
598ExpressionPtr<Scalar> log10(const ExpressionPtr<Scalar>& x) {
599 return fold_or_make<Log10Expression<Scalar>>(x);
600}
601
607template <typename Scalar>
608struct MaxExpression final
609 : NonLeafExpression<MaxExpression<Scalar>, Scalar, 2> {
610 using MaxExpression::NonLeafExpression::NonLeafExpression;
611
613 static constexpr std::string_view NAME = "max";
614
615 static Scalar eval(Scalar a, Scalar b) {
616 using std::max;
617 return max(a, b);
618 }
619
620 template <typename Value>
621 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
622 const Value& a, const Value& b) {
623 if constexpr (std::same_as<Value, Scalar>) {
624 bool c = a >= b;
625 g[0] = c ? Scalar(1) : Scalar(0);
626 g[1] = c ? Scalar(0) : Scalar(1);
627 } else {
628 auto zero = constant_ptr(Scalar(0));
629 auto one = constant_ptr(Scalar(1));
630 auto cond = [](Scalar a, Scalar b) { return a >= b; };
631 g[0] = if_else(cond, a, b, one, zero);
632 g[1] = if_else(cond, a, b, zero, one);
633 }
634 }
635};
636
642template <typename Scalar>
643ExpressionPtr<Scalar> max(const ExpressionPtr<Scalar>& a,
644 const ExpressionPtr<Scalar>& b) {
645 return fold_or_make<MaxExpression<Scalar>>(a, b);
646}
647
653template <typename Scalar>
654struct MinExpression final
655 : NonLeafExpression<MinExpression<Scalar>, Scalar, 2> {
656 using MinExpression::NonLeafExpression::NonLeafExpression;
657
659 static constexpr std::string_view NAME = "min";
660
661 static Scalar eval(Scalar a, Scalar b) {
662 using std::min;
663 return min(a, b);
664 }
665
666 template <typename Value>
667 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
668 const Value& a, const Value& b) {
669 if constexpr (std::same_as<Value, Scalar>) {
670 bool c = a <= b;
671 g[0] = c ? Scalar(1) : Scalar(0);
672 g[1] = c ? Scalar(0) : Scalar(1);
673 } else {
674 auto zero = constant_ptr(Scalar(0));
675 auto one = constant_ptr(Scalar(1));
676 auto cond = [](Scalar a, Scalar b) { return a <= b; };
677 g[0] = if_else(cond, a, b, one, zero);
678 g[1] = if_else(cond, a, b, zero, one);
679 }
680 }
681};
682
688template <typename Scalar>
689ExpressionPtr<Scalar> min(const ExpressionPtr<Scalar>& a,
690 const ExpressionPtr<Scalar>& b) {
691 return fold_or_make<MinExpression<Scalar>>(a, b);
692}
693
694template <typename Scalar>
695ExpressionPtr<Scalar> pow(const ExpressionPtr<Scalar>& base,
696 const ExpressionPtr<Scalar>& power);
697
698template <typename Scalar>
699ExpressionPtr<Scalar> sqrt(const ExpressionPtr<Scalar>& x);
700
705template <typename Scalar, ExpressionType T>
706struct PowExpression final
707 : NonLeafExpression<PowExpression<Scalar, T>, Scalar, 2, T> {
708 using PowExpression::NonLeafExpression::NonLeafExpression;
709
711 static constexpr std::string_view NAME = "pow";
712
713 static Scalar eval(Scalar base, Scalar power) {
714 using std::pow;
715 return pow(base, power);
716 }
717
718 template <typename Value>
719 static void eval_grad(ArgArray<Value>& g, const Value& val, const Value& base,
720 const Value& power) {
721 using std::log;
722 using std::pow;
723
724 g[0] = pow(base, power - lit<Value>(Scalar(1))) * power;
725 g[1] = val * log(base);
726 }
727};
728
734template <typename Scalar>
735ExpressionPtr<Scalar> pow(const ExpressionPtr<Scalar>& base,
736 const ExpressionPtr<Scalar>& power) {
737 using enum ExpressionType;
738 using std::pow;
739
740 // Prune expression
741 if (base->is_constant(Scalar(0))) {
742 // Return zero, which base currently is
743 return base;
744 } else if (base->is_constant(Scalar(1))) {
745 // Return one, which base currently is
746 return base;
747 }
748 if (power->is_constant(Scalar(0))) {
749 return constant_ptr(Scalar(1));
750 } else if (power->is_constant(Scalar(1))) {
751 // Return base unmodified
752 return base;
753 }
754
755 // Evaluate constant
756 if (base->type() == CONSTANT && power->type() == CONSTANT) {
757 return constant_ptr(pow(base->val, power->val));
758 }
759
760 if (power->is_constant(Scalar(2))) {
761 auto type = base->type() == LINEAR ? QUADRATIC : NONLINEAR;
762 return make_typed_expression_ptr<MultExpression, Scalar>(type, base, base);
763 } else if (power->is_constant(Scalar(0.5))) {
764 return sqrt(base);
765 }
766
767 return make_expression_ptr<PowExpression<Scalar, NONLINEAR>>(base, power);
768}
769
773template <typename Scalar>
774struct SignExpression final
775 : NonLeafExpression<SignExpression<Scalar>, Scalar, 1> {
776 using SignExpression::NonLeafExpression::NonLeafExpression;
777
779 static constexpr std::string_view NAME = "sign";
780
781 static Scalar eval(Scalar x) {
782 if (x < Scalar(0)) {
783 return Scalar(-1);
784 } else if (x == Scalar(0)) {
785 return Scalar(0);
786 } else {
787 return Scalar(1);
788 }
789 }
790};
791
796template <typename Scalar>
797ExpressionPtr<Scalar> sign(const ExpressionPtr<Scalar>& x) {
798 return fold_or_make<SignExpression<Scalar>>(x);
799}
800
804template <typename Scalar>
805struct SinExpression final
806 : NonLeafExpression<SinExpression<Scalar>, Scalar, 1> {
807 using SinExpression::NonLeafExpression::NonLeafExpression;
808
810 static constexpr std::string_view NAME = "sin";
811
812 static Scalar eval(Scalar x) {
813 using std::sin;
814 return sin(x);
815 }
816
817 template <typename Value>
818 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
819 const Value& x) {
820 using std::cos;
821 g[0] = cos(x);
822 }
823};
824
829template <typename Scalar>
830ExpressionPtr<Scalar> sin(const ExpressionPtr<Scalar>& x) {
831 return fold_or_make<SinExpression<Scalar>>(x);
832}
833
837template <typename Scalar>
838struct SinhExpression final
839 : NonLeafExpression<SinhExpression<Scalar>, Scalar, 1> {
840 using SinhExpression::NonLeafExpression::NonLeafExpression;
841
843 static constexpr std::string_view NAME = "sinh";
844
845 static Scalar eval(Scalar x) {
846 using std::sinh;
847 return sinh(x);
848 }
849
850 template <typename Value>
851 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
852 const Value& x) {
853 using std::cosh;
854 g[0] = cosh(x);
855 }
856};
857
862template <typename Scalar>
863ExpressionPtr<Scalar> sinh(const ExpressionPtr<Scalar>& x) {
864 return fold_or_make<SinhExpression<Scalar>>(x);
865}
866
870template <typename Scalar>
871struct SqrtExpression final
872 : NonLeafExpression<SqrtExpression<Scalar>, Scalar, 1> {
873 using SqrtExpression::NonLeafExpression::NonLeafExpression;
874
876 static constexpr std::string_view NAME = "sqrt";
877
878 static Scalar eval(Scalar x) {
879 using std::sqrt;
880 return sqrt(x);
881 }
882
883 template <typename Value>
884 static void eval_grad(ArgArray<Value>& g, const Value& val,
885 [[maybe_unused]] const Value& x) {
886 g[0] = lit<Value>(Scalar(1)) / (lit<Value>(Scalar(2)) * val);
887 }
888};
889
894template <typename Scalar>
895ExpressionPtr<Scalar> sqrt(const ExpressionPtr<Scalar>& x) {
896 return fold_or_make<SqrtExpression<Scalar>>(x);
897}
898
902template <typename Scalar>
903struct TanExpression final
904 : NonLeafExpression<TanExpression<Scalar>, Scalar, 1> {
905 using TanExpression::NonLeafExpression::NonLeafExpression;
906
908 static constexpr std::string_view NAME = "tan";
909
910 static Scalar eval(Scalar x) {
911 using std::tan;
912 return tan(x);
913 }
914
915 template <typename Value>
916 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
917 const Value& x) {
918 using std::cos;
919
920 Value c = cos(x);
921 g[0] = lit<Value>(Scalar(1)) / (c * c);
922 }
923};
924
929template <typename Scalar>
930ExpressionPtr<Scalar> tan(const ExpressionPtr<Scalar>& x) {
931 return fold_or_make<TanExpression<Scalar>>(x);
932}
933
937template <typename Scalar>
938struct TanhExpression final
939 : NonLeafExpression<TanhExpression<Scalar>, Scalar, 1> {
940 using TanhExpression::NonLeafExpression::NonLeafExpression;
941
943 static constexpr std::string_view NAME = "tanh";
944
945 static Scalar eval(Scalar x) {
946 using std::tanh;
947 return tanh(x);
948 }
949
950 template <typename Value>
951 static void eval_grad(ArgArray<Value>& g, [[maybe_unused]] const Value& val,
952 const Value& x) {
953 using std::cosh;
954
955 Value c = cosh(x);
956 g[0] = lit<Value>(Scalar(1)) / (c * c);
957 }
958};
959
964template <typename Scalar>
965ExpressionPtr<Scalar> tanh(const ExpressionPtr<Scalar>& x) {
966 return fold_or_make<TanhExpression<Scalar>>(x);
967}
968
969} // namespace slp::detail
Definition intrusive_shared_ptr.hpp:27
Definition expression_functions.hpp:22
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:26
Definition expression_functions.hpp:64
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:68
Definition expression_functions.hpp:97
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:101
Definition expression_functions.hpp:162
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:166
Definition expression_functions.hpp:130
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:134
Definition expression_functions.hpp:198
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:202
Definition expression_functions.hpp:230
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:234
Definition expression_functions.hpp:263
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:267
Definition expression_functions.hpp:296
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:300
Definition expression_functions.hpp:329
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:333
Scalar val
The value of the expression node.
Definition expression.hpp:138
Scalar Scalar
Scalar type alias.
Definition expression.hpp:135
Definition expression_functions.hpp:365
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:369
Definition expression_functions.hpp:412
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:416
Definition expression_functions.hpp:461
constexpr IfElseExpression(bool(*cond)(Scalar a, Scalar b), ExpressionPtr< Scalar > a, ExpressionPtr< Scalar > b, ExpressionPtr< Scalar > t, ExpressionPtr< Scalar > f)
Definition expression_functions.hpp:475
bool(* cond)(Scalar a, Scalar b)
Condition evaluated on a and b.
Definition expression_functions.hpp:466
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:463
Definition expression_functions.hpp:575
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:579
Definition expression_functions.hpp:543
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:547
Definition expression_functions.hpp:609
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:613
Definition expression_functions.hpp:655
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:659
Definition expression.hpp:405
Definition expression_functions.hpp:707
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:711
Definition expression_functions.hpp:775
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:779
Definition expression_functions.hpp:806
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:810
Definition expression_functions.hpp:839
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:843
Definition expression_functions.hpp:872
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:876
Definition expression_functions.hpp:904
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:908
Definition expression_functions.hpp:939
static constexpr std::string_view NAME
The expression's name.
Definition expression_functions.hpp:943