rateslib/dual/dual_ops/
neg.rs1use crate::dual::dual::{Dual, Dual2};
2use crate::dual::enums::Number;
3use auto_ops::impl_op;
4use std::sync::Arc;
5
6impl_op!(-|a: Dual| -> Dual {
7 Dual {
8 vars: a.vars,
9 real: -a.real,
10 dual: -a.dual,
11 }
12});
13impl_op!(-|a: &Dual| -> Dual {
14 Dual {
15 vars: Arc::clone(&a.vars),
16 real: -a.real,
17 dual: &a.dual * -1.0,
18 }
19});
20
21impl_op!(-|a: Dual2| -> Dual2 {
22 Dual2 {
23 vars: a.vars,
24 real: -a.real,
25 dual: -a.dual,
26 dual2: -a.dual2,
27 }
28});
29
30impl_op!(-|a: &Dual2| -> Dual2 {
31 Dual2 {
32 vars: Arc::clone(&a.vars),
33 real: -a.real,
34 dual: &a.dual * -1.0,
35 dual2: &a.dual2 * -1.0,
36 }
37});
38
39impl_op!(-|a: &Number| -> Number {
41 match a {
42 Number::F64(f) => Number::F64(-f),
43 Number::Dual(d) => Number::Dual(-d),
44 Number::Dual2(d) => Number::Dual2(-d),
45 }
46});
47
48impl_op!(-|a: Number| -> Number {
50 match a {
51 Number::F64(f) => Number::F64(-f),
52 Number::Dual(d) => Number::Dual(-d),
53 Number::Dual2(d) => Number::Dual2(-d),
54 }
55});
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use ndarray::Array1;
61
62 #[test]
63 fn negate() {
64 let d = Dual::try_new(
65 2.3,
66 Vec::from([String::from("a"), String::from("b")]),
67 Vec::from([2., -1.4]),
68 )
69 .unwrap();
70 let d2 = -d.clone();
71 assert!(d2.real == -2.3);
72 assert!(Arc::ptr_eq(&d.vars, &d2.vars));
73 assert!(d2.dual[0] == -2.0);
74 assert!(d2.dual[1] == 1.4);
75 }
76
77 #[test]
78 fn neg_ref() {
79 let d1 =
80 Dual::try_new(2.5, vec!["x".to_string(), "y".to_string()], vec![1.1, 2.2]).unwrap();
81 let d2 = -&d1;
82 assert_eq!(d2.real, -2.5);
83 assert_eq!(d2.dual, Array1::from_vec(vec![-1.1, -2.2]));
84 }
85
86 #[test]
87 fn negate2() {
88 let d = Dual2::try_new(
89 2.3,
90 Vec::from([String::from("a"), String::from("b")]),
91 Vec::from([2., -1.4]),
92 Vec::from([1.0, -1.0, -1.0, 2.0]),
93 )
94 .unwrap();
95 let d2 = -d.clone();
96 assert!(d2.real == -2.3);
97 assert!(Arc::ptr_eq(&d.vars, &d2.vars));
98 assert!(d2.dual[0] == -2.0);
99 assert!(d2.dual[1] == 1.4);
100 assert!(d2.dual2[[1, 0]] == 1.0);
101 }
102
103 #[test]
104 fn negate_ref2() {
105 let d = Dual2::try_new(
106 2.3,
107 Vec::from([String::from("a"), String::from("b")]),
108 Vec::from([2., -1.4]),
109 Vec::from([1.0, -1.0, -1.0, 2.0]),
110 )
111 .unwrap();
112 let d2 = -&d;
113 assert!(d2.real == -2.3);
114 assert!(Arc::ptr_eq(&d.vars, &d2.vars));
115 assert!(d2.dual[0] == -2.0);
116 assert!(d2.dual[1] == 1.4);
117 assert!(d2.dual2[[1, 0]] == 1.0);
118 }
119
120 #[test]
121 fn test_enum() {
122 let f = Number::F64(2.0);
123 let d = Number::Dual(Dual::new(3.0, vec!["x".to_string()]));
124 assert_eq!(-f, Number::F64(-2.0));
125 assert_eq!(
126 -d,
127 Number::Dual(Dual::try_new(-3.0, vec!["x".to_string()], vec![-1.0]).unwrap())
128 );
129 }
130}