1use crate::dual::dual::{Dual, Dual2};
2use crate::dual::enums::Number;
3use auto_ops::impl_op_ex;
4use std::sync::Arc;
5
6impl_op_ex!(% |a: &Dual, b: &f64| -> Dual { Dual {vars: Arc::clone(&a.vars), real: a.real % b, dual: a.dual.clone()} });
7impl_op_ex!(% |a: &f64, b: &Dual| -> Dual { Dual::new(*a, Vec::new()) % b });
8impl_op_ex!(% |a: &Dual2, b: &f64| -> Dual2 {
9 Dual2 {vars: Arc::clone(&a.vars), real: a.real % b, dual: a.dual.clone(), dual2: a.dual2.clone()}
10});
11impl_op_ex!(% |a: &f64, b: &Dual2| -> Dual2 {
12 Dual2::new(*a, Vec::new()) % b }
13);
14
15impl_op_ex!(% |a: &Dual, b: &Dual| -> Dual {
17 let d = f64::trunc(a.real / b.real);
18 a - d * b
19});
20
21impl_op_ex!(% |a: &Dual2, b: &Dual2| -> Dual2 {
23 let d = f64::trunc(a.real / b.real);
24 a - d * b
25});
26
27impl_op_ex!(% |a: &Number, b: &Number| -> Number {
29 match (a,b) {
30 (Number::F64(f), Number::F64(f2)) => Number::F64(f % f2),
31 (Number::F64(f), Number::Dual(d2)) => Number::Dual(f % d2),
32 (Number::F64(f), Number::Dual2(d2)) => Number::Dual2(f % d2),
33 (Number::Dual(d), Number::F64(f2)) => Number::Dual(d % f2),
34 (Number::Dual(d), Number::Dual(d2)) => Number::Dual(d % d2),
35 (Number::Dual(_), Number::Dual2(_)) => panic!("Cannot mix dual types: Dual % Dual2"),
36 (Number::Dual2(d), Number::F64(f2)) => Number::Dual2(d % f2),
37 (Number::Dual2(_), Number::Dual(_)) => panic!("Cannot mix dual types: Dual2 % Dual"),
38 (Number::Dual2(d), Number::Dual2(d2)) => Number::Dual2(d % d2),
39 }
40});
41
42impl_op_ex!(% |a: &Number, b: &f64| -> Number {
44 match a {
45 Number::F64(f) => Number::F64(f % b),
46 Number::Dual(d) => Number::Dual(d % b),
47 Number::Dual2(d) => Number::Dual2(d % b),
48 }
49});
50
51impl_op_ex!(% |a: &f64, b: &Number| -> Number {
53 match b {
54 Number::F64(f) => Number::F64(a % f),
55 Number::Dual(d) => Number::Dual(a % d),
56 Number::Dual2(d) => Number::Dual2(a % d),
57 }
58});
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn rem_() {
66 let d1 = Dual::try_new(10.0, vec!["x".to_string()], vec![2.0]).unwrap();
67 let d2 = Dual::new(3.0, vec!["x".to_string()]);
68 let result = d1 % d2;
69 let expected = Dual::try_new(1.0, vec!["x".to_string()], vec![-1.0]).unwrap();
70 assert_eq!(result, expected);
71 }
72
73 #[test]
74 fn rem_f64_() {
75 let d1 = Dual::try_new(10.0, vec!["x".to_string()], vec![2.0]).unwrap();
76 let result = &d1 % 3.0_f64;
77 assert_eq!(
78 result,
79 Dual::try_new(1.0, vec!["x".to_string()], vec![2.0]).unwrap()
80 );
81
82 let result = 11.0_f64 % d1;
83 assert_eq!(
84 result,
85 Dual::try_new(1.0, vec!["x".to_string()], vec![-2.0]).unwrap()
86 );
87 }
88
89 #[test]
90 fn rem_2() {
91 let d1 = Dual2::try_new(10.0, vec!["x".to_string()], vec![2.0], vec![]).unwrap();
92 let d2 = Dual2::new(3.0, vec!["x".to_string()]);
93 let result = d1 % d2;
94 let expected = Dual2::try_new(1.0, vec!["x".to_string()], vec![-1.0], vec![]).unwrap();
95 assert_eq!(result, expected);
96 }
97
98 #[test]
99 fn rem_f64_2() {
100 let d1 = Dual2::try_new(10.0, vec!["x".to_string()], vec![2.0], vec![]).unwrap();
101 let result = &d1 % 3.0_f64;
102 assert_eq!(
103 result,
104 Dual2::try_new(1.0, vec!["x".to_string()], vec![2.0], vec![]).unwrap()
105 );
106
107 let result = 11.0_f64 % d1;
108 assert_eq!(
109 result,
110 Dual2::try_new(1.0, vec!["x".to_string()], vec![-2.0], vec![]).unwrap()
111 );
112 }
113
114 #[test]
115 fn test_enum() {
116 let f = Number::F64(4.0);
117 let d = Number::Dual(Dual::new(3.0, vec!["x".to_string()]));
118 assert_eq!(
119 &f % &d,
120 Number::Dual(Dual::try_new(1.0, vec!["x".to_string()], vec![-1.0]).unwrap())
121 );
122
123 assert_eq!(
124 &d % &d,
125 Number::Dual(Dual::try_new(0.0, vec!["x".to_string()], vec![0.0]).unwrap())
126 );
127 }
128
129 #[test]
130 #[should_panic]
131 fn test_enum_panic() {
132 let d = Number::Dual2(Dual2::new(2.0, vec!["y".to_string()]));
133 let d2 = Number::Dual(Dual::new(3.0, vec!["x".to_string()]));
134 let _ = d % d2;
135 }
136
137 #[test]
138 fn test_enum_f64() {
139 let d = Number::Dual(Dual::new(3.0, vec!["x".to_string()]));
140 let res = 2.0_f64 % d;
141 assert_eq!(
142 res,
143 Number::Dual(2.0 % Dual::new(3.0, vec!["x".to_string()]))
144 );
145
146 let d = Number::Dual(Dual::new(3.0, vec!["x".to_string()]));
147 let res = d % 2.0_f64;
148 assert_eq!(
149 res,
150 Number::Dual(Dual::new(3.0, vec!["x".to_string()]) % 2.0)
151 );
152 }
153}