chainrules/unary/
exp_log.rs1use 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}
10pub fn exp<S: ScalarAd>(x: S) -> S {
12 x.exp()
13}
14pub fn exp_frule<S: ScalarAd>(x: S, dx: S) -> (S, S) {
16 let y = x.exp();
17 (y, dx * y)
18}
19pub fn exp_rrule<S: ScalarAd>(result: S, cotangent: S) -> S {
21 cotangent * result.conj()
22}
23pub fn expm1<S: ScalarAd>(x: S) -> S {
25 x.expm1()
26}
27pub 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}
33pub 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}
63pub fn log<S: ScalarAd>(x: S) -> S {
65 x.ln()
66}
67pub 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}
73pub fn log_rrule<S: ScalarAd>(x: S, cotangent: S) -> S {
75 cotangent * (one::<S>() / x).conj()
76}
77pub fn log1p<S: ScalarAd>(x: S) -> S {
79 x.log1p()
80}
81pub 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}
87pub 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}