mathhook_core/algebra/simplification/
trigonometric.rs1use super::strategy::SimplificationStrategy;
6use crate::core::Expression;
7
8pub struct SinSimplificationStrategy;
10
11impl SimplificationStrategy for SinSimplificationStrategy {
12 fn simplify(&self, args: &[Expression]) -> Expression {
13 if args.len() == 1 {
14 let arg = &args[0];
15
16 if arg.is_zero() {
17 Expression::integer(0)
18 } else {
19 Expression::function("sin", args.to_vec())
20 }
21 } else {
22 Expression::function("sin", args.to_vec())
23 }
24 }
25
26 fn applies_to(&self, args: &[Expression]) -> bool {
27 args.len() == 1
28 }
29
30 fn name(&self) -> &str {
31 "SinSimplificationStrategy"
32 }
33}
34
35pub struct CosSimplificationStrategy;
37
38impl SimplificationStrategy for CosSimplificationStrategy {
39 fn simplify(&self, args: &[Expression]) -> Expression {
40 if args.len() == 1 {
41 let arg = &args[0];
42
43 if arg.is_zero() {
44 Expression::integer(1)
45 } else {
46 Expression::function("cos", args.to_vec())
47 }
48 } else {
49 Expression::function("cos", args.to_vec())
50 }
51 }
52
53 fn applies_to(&self, args: &[Expression]) -> bool {
54 args.len() == 1
55 }
56
57 fn name(&self) -> &str {
58 "CosSimplificationStrategy"
59 }
60}
61
62pub struct TanSimplificationStrategy;
64
65impl SimplificationStrategy for TanSimplificationStrategy {
66 fn simplify(&self, args: &[Expression]) -> Expression {
67 if args.len() == 1 {
68 let arg = &args[0];
69
70 if arg.is_zero() {
71 Expression::integer(0)
72 } else {
73 Expression::function("tan", args.to_vec())
74 }
75 } else {
76 Expression::function("tan", args.to_vec())
77 }
78 }
79
80 fn applies_to(&self, args: &[Expression]) -> bool {
81 args.len() == 1
82 }
83
84 fn name(&self) -> &str {
85 "TanSimplificationStrategy"
86 }
87}
88
89pub struct GenericTrigSimplificationStrategy {
93 function_name: String,
94}
95
96impl GenericTrigSimplificationStrategy {
97 pub fn new(function_name: &str) -> Self {
98 Self {
99 function_name: function_name.to_owned(),
100 }
101 }
102}
103
104impl SimplificationStrategy for GenericTrigSimplificationStrategy {
105 fn simplify(&self, args: &[Expression]) -> Expression {
106 Expression::function(&self.function_name, args.to_vec())
107 }
108
109 fn applies_to(&self, args: &[Expression]) -> bool {
110 args.len() == 1
111 }
112
113 fn name(&self) -> &str {
114 &self.function_name
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use crate::{expr, symbol};
122
123 #[test]
124 fn test_sin_of_zero() {
125 let strategy = SinSimplificationStrategy;
126 let result = strategy.simplify(&[expr!(0)]);
127 assert_eq!(result, expr!(0));
128 }
129
130 #[test]
131 fn test_sin_of_x() {
132 let strategy = SinSimplificationStrategy;
133 let x = symbol!(x);
134 let result = strategy.simplify(&[x.clone().into()]);
135
136 if let Expression::Function { name, args } = result {
137 assert_eq!(name.as_ref(), "sin");
138 assert_eq!(args.len(), 1);
139 assert_eq!(args[0], x.into());
140 } else {
141 panic!("Expected function call");
142 }
143 }
144
145 #[test]
146 fn test_cos_of_zero() {
147 let strategy = CosSimplificationStrategy;
148 let result = strategy.simplify(&[expr!(0)]);
149 assert_eq!(result, expr!(1));
150 }
151
152 #[test]
153 fn test_cos_of_x() {
154 let strategy = CosSimplificationStrategy;
155 let x = symbol!(x);
156 let result = strategy.simplify(&[x.clone().into()]);
157
158 if let Expression::Function { name, args } = result {
159 assert_eq!(name.as_ref(), "cos");
160 assert_eq!(args.len(), 1);
161 assert_eq!(args[0], x.into());
162 } else {
163 panic!("Expected function call");
164 }
165 }
166
167 #[test]
168 fn test_tan_of_zero() {
169 let strategy = TanSimplificationStrategy;
170 let result = strategy.simplify(&[expr!(0)]);
171 assert_eq!(result, expr!(0));
172 }
173
174 #[test]
175 fn test_tan_of_x() {
176 let strategy = TanSimplificationStrategy;
177 let x = symbol!(x);
178 let result = strategy.simplify(&[x.clone().into()]);
179
180 if let Expression::Function { name, args } = result {
181 assert_eq!(name.as_ref(), "tan");
182 assert_eq!(args.len(), 1);
183 assert_eq!(args[0], x.into());
184 } else {
185 panic!("Expected function call");
186 }
187 }
188
189 #[test]
190 fn test_generic_trig() {
191 let strategy = GenericTrigSimplificationStrategy::new("sinh");
192 let x = symbol!(x);
193 let result = strategy.simplify(&[x.clone().into()]);
194
195 if let Expression::Function { name, args } = result {
196 assert_eq!(name.as_ref(), "sinh");
197 assert_eq!(args.len(), 1);
198 assert_eq!(args[0], x.into());
199 } else {
200 panic!("Expected function call");
201 }
202 }
203}