-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMultiplyOperator.cs
More file actions
143 lines (123 loc) · 4.74 KB
/
MultiplyOperator.cs
File metadata and controls
143 lines (123 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
namespace SymSharp;
/// <summary>
/// Represents binary multiplication between two expressions.
/// </summary>
public class MultiplyOperator : IBinaryOperator
{
/// <summary>
/// The left operand.
/// </summary>
private readonly IMathExpression left;
/// <summary>
/// The right operand.
/// </summary>
private readonly IMathExpression right;
/// <summary>
/// Gets the left operand.
/// </summary>
public IMathExpression Left => left;
/// <summary>
/// Gets the right operand.
/// </summary>
public IMathExpression Right => right;
/// <summary>
/// Constructs a multiplication operator with the specified operands.
/// </summary>
/// <param name="left">Left operand.</param>
/// <param name="right">Right operand.</param>
public MultiplyOperator(IMathExpression left, IMathExpression right)
{
this.left = left;
this.right = right;
}
/// <summary>
/// Returns a textual representation of the multiplication.
/// </summary>
public override string ToString()
{
return $"({Left} * {Right})";
}
/// <summary>
/// Simplifies the multiplication expression by applying algebraic and constant-folding rules.
/// </summary>
public IMathExpression Simplified()
{
IMathExpression simplifiedLeft = Left.Simplified();
IMathExpression simplifiedRight = Right.Simplified();
IMathExpression combinedExpression = new MultiplyOperator(simplifiedLeft, simplifiedRight);
// Case: both scalars → collapse into one scalar
if (simplifiedLeft is Scalar leftScalar && simplifiedRight is Scalar rightScalar)
{
double leftValue = leftScalar.ToDouble();
double rightValue = rightScalar.ToDouble();
double product = leftValue * rightValue;
if (double.IsFinite(leftValue) && double.IsFinite(rightValue) && !double.IsFinite(product))
{
return combinedExpression;
}
return new Scalar(product);
}
// Case: x * 1 → x
if (simplifiedRight is Scalar oneRight && oneRight.ToDouble() == 1.0)
{
return simplifiedLeft;
}
// Case: 1 * x → x
if (simplifiedLeft is Scalar oneLeft && oneLeft.ToDouble() == 1.0)
{
return simplifiedRight;
}
// Case: x * 0 → 0
if (simplifiedRight is Scalar zeroRight && zeroRight.ToDouble() == 0.0)
{
return new Scalar(0);
}
// Case: 0 * x → 0
if (simplifiedLeft is Scalar zeroLeft && zeroLeft.ToDouble() == 0.0)
{
return new Scalar(0);
}
// Case: reorder Variable * Scalar → Scalar * Variable
if (simplifiedLeft is Variable && simplifiedRight is Scalar)
{
return new MultiplyOperator(simplifiedRight, simplifiedLeft);
}
// Distribution!!!
if (simplifiedLeft is AddOperator a && (simplifiedRight is Scalar || simplifiedRight is Variable))
{
return new AddOperator(new MultiplyOperator(a.Left, simplifiedRight), new MultiplyOperator(a.Right, simplifiedRight)).Simplified();
}
// Distribution!!!
if (simplifiedRight is AddOperator b && (simplifiedLeft is Scalar || simplifiedLeft is Variable))
{
return new AddOperator(new MultiplyOperator(b.Left, simplifiedLeft), new MultiplyOperator(b.Right, simplifiedLeft)).Simplified();
}
// Defactor!!
if (simplifiedLeft is AddOperator c && simplifiedRight is AddOperator d)
{
// (c1 + c2)(d1 + d2) = (c1 + c2)d1 + (c1 + c2)d2 = c1d1 + c2d1 + c2d2 + c1d2
return new AddOperator(
new AddOperator(
new MultiplyOperator(c.Left, d.Left),
new MultiplyOperator(c.Right, d.Left)
), new AddOperator(
new MultiplyOperator(c.Left, d.Right),
new MultiplyOperator(c.Right, d.Right)
)
).Simplified();
}
return combinedExpression;
}
/// <summary>
/// Applies the product rule for derivatives: (uv)' = u'v + uv'.
/// </summary>
/// <param name="varname">The variable name to differentiate with respect to.</param>
public IMathExpression Derivative(string varname)
{
// Product rule: (uv)' = u'v + uv'
return new AddOperator(
new MultiplyOperator(Right, Left.Derivative(varname)),
new MultiplyOperator(Left, Right.Derivative(varname))
).Simplified();
}
}