chainrules/unary/
hyperbolic.rs

1use crate::unary::one;
2use crate::ScalarAd;
3
4/// Primal `tanh`.
5pub fn tanh<S: ScalarAd>(x: S) -> S {
6    x.tanh()
7}
8
9/// Forward rule for `tanh`.
10pub fn tanh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
11    let y = x.tanh();
12    let scale = one::<S>() - y * y;
13    (y, dx * scale)
14}
15
16/// Reverse rule for `tanh`.
17pub fn tanh_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
18    cotangent * (one::<S>() - result * result).conj()
19}
20
21/// Primal `sinh`.
22pub fn sinh<S: ScalarAd>(x: S) -> S {
23    x.sinh()
24}
25
26/// Forward rule for `sinh`.
27pub fn sinh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
28    let y = x.sinh();
29    (y, dx * x.cosh())
30}
31
32/// Reverse rule for `sinh`.
33pub fn sinh_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
34    cotangent * x.cosh().conj()
35}
36
37/// Primal `cosh`.
38pub fn cosh<S: ScalarAd>(x: S) -> S {
39    x.cosh()
40}
41
42/// Forward rule for `cosh`.
43pub fn cosh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
44    let y = x.cosh();
45    (y, dx * x.sinh())
46}
47
48/// Reverse rule for `cosh`.
49pub fn cosh_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
50    cotangent * x.sinh().conj()
51}
52
53fn inverse_sqrt_one_plus_square<S: ScalarAd>(x: S) -> S {
54    one::<S>() / (one::<S>() + x * x).sqrt()
55}
56
57/// Primal `asinh`.
58pub fn asinh<S: ScalarAd>(x: S) -> S {
59    x.asinh()
60}
61
62/// Forward rule for `asinh`.
63pub fn asinh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
64    let y = x.asinh();
65    let scale = inverse_sqrt_one_plus_square(x);
66    (y, dx * scale)
67}
68
69/// Reverse rule for `asinh`.
70pub fn asinh_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
71    cotangent * inverse_sqrt_one_plus_square(x).conj()
72}
73
74fn inverse_acosh_scale<S: ScalarAd>(x: S) -> S {
75    one::<S>() / ((x - one::<S>()).sqrt() * (x + one::<S>()).sqrt())
76}
77
78/// Primal `acosh`.
79pub fn acosh<S: ScalarAd>(x: S) -> S {
80    x.acosh()
81}
82
83/// Forward rule for `acosh`.
84pub fn acosh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
85    let y = x.acosh();
86    let scale = inverse_acosh_scale(x);
87    (y, dx * scale)
88}
89
90/// Reverse rule for `acosh`.
91pub fn acosh_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
92    cotangent * inverse_acosh_scale(x).conj()
93}
94
95/// Primal `atanh`.
96pub fn atanh<S: ScalarAd>(x: S) -> S {
97    x.atanh()
98}
99
100/// Forward rule for `atanh`.
101pub fn atanh_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
102    let y = x.atanh();
103    let scale = one::<S>() / (one::<S>() - x * x);
104    (y, dx * scale)
105}
106
107/// Reverse rule for `atanh`.
108pub fn atanh_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
109    cotangent * (one::<S>() / (one::<S>() - x * x)).conj()
110}