mathhook_core/algebra/simplification/
special.rs1use super::strategy::SimplificationStrategy;
6use crate::core::{Expression, Number};
7use num_bigint::BigInt;
8use num_traits::{One, ToPrimitive};
9
10pub struct GammaSimplificationStrategy;
12
13impl GammaSimplificationStrategy {
14 fn factorial_i64(&self, n: u64) -> BigInt {
15 if n <= 1 {
16 BigInt::one()
17 } else {
18 let mut result = BigInt::one();
19 for i in 2..=n {
20 result *= BigInt::from(i);
21 }
22 result
23 }
24 }
25}
26
27impl SimplificationStrategy for GammaSimplificationStrategy {
28 fn simplify(&self, args: &[Expression]) -> Expression {
29 if args.len() == 1 {
30 match &args[0] {
31 Expression::Number(Number::Integer(n)) => {
32 if let Some(val) = n.to_i64() {
33 if val > 0 && val <= 10 {
34 let factorial_result = self.factorial_i64((val - 1) as u64);
35 Expression::big_integer(factorial_result)
36 } else {
37 Expression::function("gamma", args.to_vec())
38 }
39 } else {
40 Expression::function("gamma", args.to_vec())
41 }
42 }
43 _ => Expression::function("gamma", args.to_vec()),
44 }
45 } else {
46 Expression::function("gamma", args.to_vec())
47 }
48 }
49
50 fn applies_to(&self, args: &[Expression]) -> bool {
51 args.len() == 1
52 }
53
54 fn name(&self) -> &str {
55 "GammaSimplificationStrategy"
56 }
57}
58
59pub struct FactorialSimplificationStrategy;
63
64impl SimplificationStrategy for FactorialSimplificationStrategy {
65 fn simplify(&self, args: &[Expression]) -> Expression {
66 if args.len() == 1 {
67 crate::functions::special::factorial(&args[0])
68 } else {
69 Expression::function("factorial", args.to_vec())
70 }
71 }
72
73 fn applies_to(&self, args: &[Expression]) -> bool {
74 args.len() == 1
75 }
76
77 fn name(&self) -> &str {
78 "FactorialSimplificationStrategy"
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::expr;
86
87 #[test]
88 fn test_gamma_of_one() {
89 let strategy = GammaSimplificationStrategy;
90 let result = strategy.simplify(&[expr!(1)]);
91 assert_eq!(result, expr!(1));
92 }
93
94 #[test]
95 fn test_gamma_of_two() {
96 let strategy = GammaSimplificationStrategy;
97 let result = strategy.simplify(&[expr!(2)]);
98 assert_eq!(result, expr!(1));
99 }
100
101 #[test]
102 fn test_gamma_of_three() {
103 let strategy = GammaSimplificationStrategy;
104 let result = strategy.simplify(&[expr!(3)]);
105 assert_eq!(result, expr!(2));
106 }
107
108 #[test]
109 fn test_gamma_of_four() {
110 let strategy = GammaSimplificationStrategy;
111 let result = strategy.simplify(&[expr!(4)]);
112 assert_eq!(result, expr!(6));
113 }
114
115 #[test]
116 fn test_gamma_of_five() {
117 let strategy = GammaSimplificationStrategy;
118 let result = strategy.simplify(&[expr!(5)]);
119 assert_eq!(result, expr!(24));
120 }
121
122 #[test]
123 fn test_factorial_of_zero() {
124 let strategy = FactorialSimplificationStrategy;
125 let result = strategy.simplify(&[expr!(0)]);
126 assert_eq!(result, expr!(1));
127 }
128
129 #[test]
130 fn test_factorial_of_one() {
131 let strategy = FactorialSimplificationStrategy;
132 let result = strategy.simplify(&[expr!(1)]);
133 assert_eq!(result, expr!(1));
134 }
135
136 #[test]
137 fn test_factorial_of_five() {
138 let strategy = FactorialSimplificationStrategy;
139 let result = strategy.simplify(&[expr!(5)]);
140 assert_eq!(result, expr!(120));
141 }
142
143 #[test]
144 fn test_factorial_of_ten() {
145 let strategy = FactorialSimplificationStrategy;
146 let result = strategy.simplify(&[expr!(10)]);
147 assert_eq!(result, expr!(3628800));
148 }
149}