chainrules/unary/
hyperbolic_extra.rs

1use crate::unary::{
2    cosh, cosh_frule, cosh_rrule, inv, inv_frule, inv_rrule, sinh, sinh_frule, sinh_rrule, tanh,
3    tanh_frule, tanh_rrule,
4};
5use crate::ScalarAd;
6
7/// Primal `sech`.
8///
9/// # Examples
10///
11/// ```rust
12/// use chainrules::sech;
13///
14/// assert!((sech(0.5_f64) - 1.0 / 0.5_f64.cosh()).abs() < 1e-12);
15/// ```
16pub fn sech<S: ScalarAd>(x: S) -> S {
17    inv(cosh(x))
18}
19
20/// Forward rule for `sech`.
21///
22/// # Examples
23///
24/// ```rust
25/// use chainrules::sech_frule;
26///
27/// let (_, dy) = sech_frule(0.5_f64, 1.0);
28/// let sech_x = 1.0 / 0.5_f64.cosh();
29/// assert!((dy + sech_x * 0.5_f64.tanh()).abs() < 1e-12);
30/// ```
31pub fn sech_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
32    let (y, dy) = cosh_frule(x, dx);
33    inv_frule(y, dy)
34}
35
36/// Reverse rule for `sech`.
37///
38/// # Examples
39///
40/// ```rust
41/// use chainrules::sech_rrule;
42///
43/// let dy = sech_rrule(0.5_f64, 1.0);
44/// let sech_x = 1.0 / 0.5_f64.cosh();
45/// assert!((dy + sech_x * 0.5_f64.tanh()).abs() < 1e-12);
46/// ```
47pub fn sech_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
48    let y = sech(x);
49    let d_y = inv_rrule(y, cotangent);
50    cosh_rrule(x, d_y)
51}
52
53/// Primal `csch`.
54///
55/// # Examples
56///
57/// ```rust
58/// use chainrules::csch;
59///
60/// assert!((csch(0.5_f64) - 1.0 / 0.5_f64.sinh()).abs() < 1e-12);
61/// ```
62pub fn csch<S: ScalarAd>(x: S) -> S {
63    inv(sinh(x))
64}
65
66/// Forward rule for `csch`.
67///
68/// # Examples
69///
70/// ```rust
71/// use chainrules::csch_frule;
72///
73/// let (_, dy) = csch_frule(0.5_f64, 1.0);
74/// let csch_x = 1.0 / 0.5_f64.sinh();
75/// assert!((dy + csch_x * 0.5_f64.cosh() / 0.5_f64.sinh()).abs() < 1e-12);
76/// ```
77pub fn csch_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
78    let (y, dy) = sinh_frule(x, dx);
79    inv_frule(y, dy)
80}
81
82/// Reverse rule for `csch`.
83///
84/// # Examples
85///
86/// ```rust
87/// use chainrules::csch_rrule;
88///
89/// let dy = csch_rrule(0.5_f64, 1.0);
90/// let csch_x = 1.0 / 0.5_f64.sinh();
91/// assert!((dy + csch_x * 0.5_f64.cosh() / 0.5_f64.sinh()).abs() < 1e-12);
92/// ```
93pub fn csch_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
94    let y = csch(x);
95    let d_y = inv_rrule(y, cotangent);
96    sinh_rrule(x, d_y)
97}
98
99/// Primal `coth`.
100///
101/// # Examples
102///
103/// ```rust
104/// use chainrules::coth;
105///
106/// assert!((coth(0.5_f64) - 1.0 / 0.5_f64.tanh()).abs() < 1e-12);
107/// ```
108pub fn coth<S: ScalarAd>(x: S) -> S {
109    inv(tanh(x))
110}
111
112/// Forward rule for `coth`.
113///
114/// # Examples
115///
116/// ```rust
117/// use chainrules::coth_frule;
118///
119/// let (_, dy) = coth_frule(0.5_f64, 1.0);
120/// assert!((dy + 1.0 / 0.5_f64.sinh().powi(2)).abs() < 1e-12);
121/// ```
122pub fn coth_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
123    let (y, dy) = tanh_frule(x, dx);
124    inv_frule(y, dy)
125}
126
127/// Reverse rule for `coth`.
128///
129/// # Examples
130///
131/// ```rust
132/// use chainrules::coth_rrule;
133///
134/// let dy = coth_rrule(0.5_f64, 1.0);
135/// assert!((dy + 1.0 / 0.5_f64.sinh().powi(2)).abs() < 1e-12);
136/// ```
137pub fn coth_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
138    let y = coth(x);
139    let d_y = inv_rrule(y, cotangent);
140    tanh_rrule(tanh(x), d_y)
141}