chainrules/unary/
exp_log.rs

1use crate::unary::one;
2use crate::ScalarAd;
3use num_traits::FloatConst;
4fn ln_2<S: ScalarAd>() -> S {
5    S::from_real(S::Real::LN_2())
6}
7fn ln_10<S: ScalarAd>() -> S {
8    S::from_real(S::Real::LN_10())
9}
10/// Primal `exp`.
11pub fn exp<S: ScalarAd>(x: S) -> S {
12    x.exp()
13}
14/// Forward rule for `exp`.
15pub fn exp_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
16    let y = x.exp();
17    (y, dx * y)
18}
19/// Reverse rule for `exp`.
20pub fn exp_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
21    cotangent * result.conj()
22}
23/// Primal `exp(x) - 1`.
24pub fn expm1<S: ScalarAd>(x: S) -> S {
25    x.expm1()
26}
27/// Forward rule for `exp(x) - 1`.
28pub fn expm1_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
29    let y = x.expm1();
30    let scale = y + one::<S>();
31    (y, dx * scale)
32}
33/// Reverse rule for `exp(x) - 1`.
34pub fn expm1_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
35    cotangent * (result + one::<S>()).conj()
36}
37#[doc = "Primal `2^x`.\n\n# Examples\n```rust\nuse chainrules::exp2;\n\nassert!((exp2(3.0_f64) - 8.0).abs() < 1e-12);\n```"]
38pub fn exp2<S: ScalarAd>(x: S) -> S {
39    x.exp2()
40}
41#[doc = "Forward rule for `2^x`.\n\n# Examples\n```rust\nuse chainrules::exp2_frule;\n\nlet (y, dy) = exp2_frule(3.0_f64, 1.0);\nassert!((y - 8.0).abs() < 1e-12);\nassert!((dy - 8.0_f64 * std::f64::consts::LN_2).abs() < 1e-12);\n```"]
42pub fn exp2_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
43    let y = x.exp2();
44    (y, dx * (y * ln_2::<S>()))
45}
46#[doc = "Reverse rule for `2^x`.\n\n# Examples\n```rust\nuse chainrules::exp2_rrule;\n\nlet dy = exp2_rrule(8.0_f64, 1.0);\nassert!((dy - 8.0_f64 * std::f64::consts::LN_2).abs() < 1e-12);\n```"]
47pub fn exp2_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
48    cotangent * (result * ln_2::<S>()).conj()
49}
50#[doc = "Primal `10^x`.\n\n# Examples\n```rust\nuse chainrules::exp10;\n\nassert!((exp10(2.0_f64) - 100.0).abs() < 1e-12);\n```"]
51pub fn exp10<S: ScalarAd>(x: S) -> S {
52    x.exp10()
53}
54#[doc = "Forward rule for `10^x`.\n\n# Examples\n```rust\nuse chainrules::exp10_frule;\n\nlet (y, dy) = exp10_frule(2.0_f64, 0.5);\nassert!((y - 100.0).abs() < 1e-12);\nassert!((dy - 0.5_f64 * 100.0_f64 * std::f64::consts::LN_10).abs() < 1e-12);\n```"]
55pub fn exp10_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
56    let y = x.exp10();
57    (y, dx * (y * ln_10::<S>()))
58}
59#[doc = "Reverse rule for `10^x`.\n\n# Examples\n```rust\nuse chainrules::exp10_rrule;\n\nlet dy = exp10_rrule(100.0_f64, 0.5);\nassert!((dy - 0.5_f64 * 100.0_f64 * std::f64::consts::LN_10).abs() < 1e-12);\n```"]
60pub fn exp10_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
61    cotangent * (result * ln_10::<S>()).conj()
62}
63/// Primal `log`.
64pub fn log<S: ScalarAd>(x: S) -> S {
65    x.ln()
66}
67/// Forward rule for `log`.
68pub fn log_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
69    let y = x.ln();
70    let dy = dx * (one::<S>() / x);
71    (y, dy)
72}
73/// Reverse rule for `log`.
74pub fn log_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
75    cotangent * (one::<S>() / x).conj()
76}
77/// Primal `log(1 + x)`.
78pub fn log1p<S: ScalarAd>(x: S) -> S {
79    x.log1p()
80}
81/// Forward rule for `log(1 + x)`.
82pub fn log1p_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
83    let y = x.log1p();
84    let dy = dx * (one::<S>() / (one::<S>() + x));
85    (y, dy)
86}
87/// Reverse rule for `log(1 + x)`.
88pub fn log1p_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
89    cotangent * (one::<S>() / (one::<S>() + x)).conj()
90}
91#[doc = "Primal `log2`.\n\n# Examples\n```rust\nuse chainrules::log2;\n\nassert_eq!(log2(8.0_f64), 3.0);\n```"]
92pub fn log2<S: ScalarAd>(x: S) -> S {
93    x.log2()
94}
95#[doc = "Forward rule for `log2`.\n\n# Examples\n```rust\nuse chainrules::log2_frule;\n\nlet (y, dy) = log2_frule(8.0_f64, 2.0);\nassert!((y - 3.0).abs() < 1e-12);\nassert!((dy - (2.0_f64 / (8.0_f64 * std::f64::consts::LN_2))).abs() < 1e-12);\n```"]
96pub fn log2_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
97    let y = x.log2();
98    let scale = one::<S>() / (x * ln_2::<S>());
99    (y, dx * scale)
100}
101#[doc = "Reverse rule for `log2`.\n\n# Examples\n```rust\nuse chainrules::log2_rrule;\n\nlet dy = log2_rrule(8.0_f64, 2.0);\nassert!((dy - (2.0_f64 / (8.0_f64 * std::f64::consts::LN_2))).abs() < 1e-12);\n```"]
102pub fn log2_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
103    cotangent * (one::<S>() / (x * ln_2::<S>())).conj()
104}
105#[doc = "Primal `log10`.\n\n# Examples\n```rust\nuse chainrules::log10;\n\nassert_eq!(log10(100.0_f64), 2.0);\n```"]
106pub fn log10<S: ScalarAd>(x: S) -> S {
107    x.log10()
108}
109#[doc = "Forward rule for `log10`.\n\n# Examples\n```rust\nuse chainrules::log10_frule;\n\nlet (y, dy) = log10_frule(100.0_f64, 2.0);\nassert!((y - 2.0).abs() < 1e-12);\nassert!((dy - (2.0_f64 / (100.0_f64 * std::f64::consts::LN_10))).abs() < 1e-12);\n```"]
110pub fn log10_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
111    let y = x.log10();
112    let scale = one::<S>() / (x * ln_10::<S>());
113    (y, dx * scale)
114}
115#[doc = "Reverse rule for `log10`.\n\n# Examples\n```rust\nuse chainrules::log10_rrule;\n\nlet dy = log10_rrule(100.0_f64, 2.0);\nassert!((dy - (2.0_f64 / (100.0_f64 * std::f64::consts::LN_10))).abs() < 1e-12);\n```"]
116pub fn log10_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
117    cotangent * (one::<S>() / (x * ln_10::<S>())).conj()
118}