Skip to content

Commit

Permalink
#489 - Add basic simplification rules for Power and Temperature units.
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Dec 13, 2021
1 parent bedf784 commit 84d491a
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 287 deletions.
48 changes: 44 additions & 4 deletions xFunc.Maths/Analyzers/Simplifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,28 @@ public override IExpression Analyze(Add exp)
// const + const
(Number left, Number right)
=> new Number(left.Value + right.Value),

(Number left, Angle right)
=> (left.Value + right.Value).AsExpression(),
(Angle left, Number right)
=> (left.Value + right.Value).AsExpression(),
(Angle left, Angle right)
=> (left.Value + right.Value).AsExpression(),

(Number left, Power right)
=> (left.Value + right.Value).AsExpression(),
(Power left, Number right)
=> (left.Value + right.Value).AsExpression(),
(Power left, Power right)
=> (left.Value + right.Value).AsExpression(),

(Number left, Temperature right)
=> (left.Value + right.Value).AsExpression(),
(Temperature left, Number right)
=> (left.Value + right.Value).AsExpression(),
(Temperature left, Temperature right)
=> (left.Value + right.Value).AsExpression(),

// x + x
(Variable left, Variable right) when left.Name == right.Name
=> new Mul(Number.Two, left),
Expand Down Expand Up @@ -292,11 +307,12 @@ public override IExpression Analyze(Div exp)
// const / const
(Number left, Number right)
=> new Number(left.Value / right.Value),
(Number left, Angle right)
=> (left.Value / right.Value).AsExpression(),

(Angle left, Number right)
=> (left.Value / right.Value).AsExpression(),
(Angle left, Angle right)
(Power left, Number right)
=> (left.Value / right.Value).AsExpression(),
(Temperature left, Number right)
=> (left.Value / right.Value).AsExpression(),

// x / x
Expand Down Expand Up @@ -474,11 +490,20 @@ public override IExpression Analyze(Mul exp)
// const * const
(Number left, Number right)
=> new Number(left.Value * right.Value),

(Number left, Angle right)
=> (left.Value * right.Value).AsExpression(),
(Angle left, Number right)
=> (left.Value * right.Value).AsExpression(),
(Angle left, Angle right)

(Number left, Power right)
=> (left.Value * right.Value).AsExpression(),
(Power left, Number right)
=> (left.Value * right.Value).AsExpression(),

(Number left, Temperature right)
=> (left.Value * right.Value).AsExpression(),
(Temperature left, Number right)
=> (left.Value * right.Value).AsExpression(),

// x * -y
Expand Down Expand Up @@ -700,13 +725,28 @@ public override IExpression Analyze(Sub exp)
// const - const
(Number left, Number right)
=> new Number(left.Value - right.Value),

(Number left, Angle right)
=> (left.Value - right.Value).AsExpression(),
(Angle left, Number right)
=> (left.Value - right.Value).AsExpression(),
(Angle left, Angle right)
=> (left.Value - right.Value).AsExpression(),

(Number left, Power right)
=> (left.Value - right.Value).AsExpression(),
(Power left, Number right)
=> (left.Value - right.Value).AsExpression(),
(Power left, Power right)
=> (left.Value - right.Value).AsExpression(),

(Number left, Temperature right)
=> (left.Value - right.Value).AsExpression(),
(Temperature left, Number right)
=> (left.Value - right.Value).AsExpression(),
(Temperature left, Temperature right)
=> (left.Value - right.Value).AsExpression(),

// x + x
(Variable left, Variable right) when left.Name == right.Name
=> Number.Zero,
Expand Down
21 changes: 6 additions & 15 deletions xFunc.Maths/Analyzers/TypeAnalyzers/TypeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,19 +435,13 @@ public virtual ResultTypes Analyze(Div exp)

(ResultTypes.Number, ResultTypes.Number) => ResultTypes.Number,

(ResultTypes.Number, ResultTypes.AngleNumber) or
(ResultTypes.AngleNumber, ResultTypes.Number) or
(ResultTypes.AngleNumber, ResultTypes.AngleNumber)
(ResultTypes.AngleNumber, ResultTypes.Number)
=> ResultTypes.AngleNumber,

(ResultTypes.Number, ResultTypes.PowerNumber) or
(ResultTypes.PowerNumber, ResultTypes.Number) or
(ResultTypes.PowerNumber, ResultTypes.PowerNumber)
(ResultTypes.PowerNumber, ResultTypes.Number)
=> ResultTypes.PowerNumber,

(ResultTypes.Number, ResultTypes.TemperatureNumber) or
(ResultTypes.TemperatureNumber, ResultTypes.Number) or
(ResultTypes.TemperatureNumber, ResultTypes.TemperatureNumber)
(ResultTypes.TemperatureNumber, ResultTypes.Number)
=> ResultTypes.TemperatureNumber,

(ResultTypes.Number, ResultTypes.ComplexNumber) or
Expand Down Expand Up @@ -705,18 +699,15 @@ public virtual ResultTypes Analyze(Mul exp)
(ResultTypes.Number, ResultTypes.Number) => ResultTypes.Number,

(ResultTypes.Number, ResultTypes.AngleNumber) or
(ResultTypes.AngleNumber, ResultTypes.Number) or
(ResultTypes.AngleNumber, ResultTypes.AngleNumber)
(ResultTypes.AngleNumber, ResultTypes.Number)
=> ResultTypes.AngleNumber,

(ResultTypes.Number, ResultTypes.PowerNumber) or
(ResultTypes.PowerNumber, ResultTypes.Number) or
(ResultTypes.PowerNumber, ResultTypes.PowerNumber)
(ResultTypes.PowerNumber, ResultTypes.Number)
=> ResultTypes.PowerNumber,

(ResultTypes.Number, ResultTypes.TemperatureNumber) or
(ResultTypes.TemperatureNumber, ResultTypes.Number) or
(ResultTypes.TemperatureNumber, ResultTypes.TemperatureNumber)
(ResultTypes.TemperatureNumber, ResultTypes.Number)
=> ResultTypes.TemperatureNumber,

(ResultTypes.Number, ResultTypes.ComplexNumber) or
Expand Down
8 changes: 0 additions & 8 deletions xFunc.Maths/Expressions/Div.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,9 @@ public override object Execute(ExpressionParameters? parameters)
{
(NumberValue left, NumberValue right) => left / right,

(NumberValue left, AngleValue right) => left / right,
(AngleValue left, NumberValue right) => left / right,
(AngleValue left, AngleValue right) => left / right,

(NumberValue left, PowerValue right) => left / right,
(PowerValue left, NumberValue right) => left / right,
(PowerValue left, PowerValue right) => left / right,

(NumberValue left, TemperatureValue right) => left / right,
(TemperatureValue left, NumberValue right) => left / right,
(TemperatureValue left, TemperatureValue right) => left / right,

(NumberValue left, Complex right) => left / right,
(Complex left, NumberValue right) => left / right,
Expand Down
3 changes: 0 additions & 3 deletions xFunc.Maths/Expressions/Mul.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,12 @@ public override object Execute(ExpressionParameters? parameters)

(NumberValue left, AngleValue right) => left * right,
(AngleValue left, NumberValue right) => left * right,
(AngleValue left, AngleValue right) => left * right,

(NumberValue left, PowerValue right) => left * right,
(PowerValue left, NumberValue right) => left * right,
(PowerValue left, PowerValue right) => left * right,

(NumberValue left, TemperatureValue right) => left * right,
(TemperatureValue left, NumberValue right) => left * right,
(TemperatureValue left, TemperatureValue right) => left * right,

(NumberValue left, Complex right) => left * right,
(Complex left, NumberValue right) => left * right,
Expand Down
72 changes: 72 additions & 0 deletions xFunc.Tests/Analyzers/SimplifierTests/AddSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,78 @@ public void AddTwoAngles()
SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 + 10 W")]
public void AddNumberAndPower()
{
var add = new Add(
new Number(10),
PowerValue.Watt(10).AsExpression()
);
var expected = PowerValue.Watt(20).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 W + 10")]
public void AddPowerAndNumber()
{
var add = new Add(
PowerValue.Watt(10).AsExpression(),
new Number(10)
);
var expected = PowerValue.Watt(20).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 W + 10 kW")]
public void AddTwoPowers()
{
var add = new Add(
PowerValue.Watt(10).AsExpression(),
PowerValue.Kilowatt(10).AsExpression()
);
var expected = PowerValue.Watt(10010).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 + 10 C°")]
public void AddNumberAndTemperature()
{
var add = new Add(
new Number(10),
TemperatureValue.Celsius(10).AsExpression()
);
var expected = TemperatureValue.Celsius(20).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 C° + 10")]
public void AddTemperatureAndNumber()
{
var add = new Add(
TemperatureValue.Celsius(10).AsExpression(),
new Number(10)
);
var expected = TemperatureValue.Celsius(20).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "10 C° + 10 K")]
public void AddTwoTemperatures()
{
var add = new Add(
TemperatureValue.Celsius(10).AsExpression(),
TemperatureValue.Kelvin(10).AsExpression()
);
var expected = TemperatureValue.Celsius(10 - 263.15).AsExpression();

SimplifyTest(add, expected);
}

[Fact(DisplayName = "-x + 2")]
public void AddFirstUnaryMinus()
{
Expand Down
26 changes: 13 additions & 13 deletions xFunc.Tests/Analyzers/SimplifierTests/DivSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,38 @@ public void DivTwoNumbers()
SimplifyTest(div, expected);
}

[Fact(DisplayName = "90 / 2 deg")]
public void DivNumberAngle()
[Fact(DisplayName = "90 deg / 2")]
public void DivAngleNumber()
{
var div = new Div(
new Number(90),
AngleValue.Degree(2).AsExpression()
AngleValue.Degree(90).AsExpression(),
new Number(2)
);
var expected = AngleValue.Degree(45).AsExpression();

SimplifyTest(div, expected);
}

[Fact(DisplayName = "90 deg / 2")]
public void DivAngleNumber()
[Fact(DisplayName = "90 W / 2")]
public void DivPowerByNumber()
{
var div = new Div(
AngleValue.Degree(90).AsExpression(),
PowerValue.Watt(90).AsExpression(),
new Number(2)
);
var expected = AngleValue.Degree(45).AsExpression();
var expected = PowerValue.Watt(45).AsExpression();

SimplifyTest(div, expected);
}

[Fact(DisplayName = "2 rad / 90 deg")]
public void DivTwoAngles()
[Fact(DisplayName = "90 C° / 2")]
public void DivTemperatureByNumber()
{
var div = new Div(
AngleValue.Radian(2).AsExpression(),
AngleValue.Degree(90).AsExpression()
PowerValue.Watt(90).AsExpression(),
new Number(2)
);
var expected = AngleValue.Degree(114.59155902616465 / 90).AsExpression();
var expected = PowerValue.Watt(45).AsExpression();

SimplifyTest(div, expected);
}
Expand Down
46 changes: 41 additions & 5 deletions xFunc.Tests/Analyzers/SimplifierTests/MulSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,50 @@ public void MulAngleNumber()
SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2 rad * 90 deg")]
public void MulTwoAngles()
[Fact(DisplayName = "10 * 2 W")]
public void MulNumberByPower()
{
var mul = new Mul(
AngleValue.Radian(2).AsExpression(),
AngleValue.Degree(90).AsExpression()
new Number(10),
PowerValue.Watt(2).AsExpression()
);
var expected = AngleValue.Degree(114.59155902616465 * 90).AsExpression();
var expected = PowerValue.Watt(20).AsExpression();

SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2 W * 10")]
public void MulPowerByNumber()
{
var mul = new Mul(
PowerValue.Watt(2).AsExpression(),
new Number(10)
);
var expected = PowerValue.Watt(20).AsExpression();

SimplifyTest(mul, expected);
}

[Fact(DisplayName = "10 * 2 C°")]
public void MulNumberByTemperature()
{
var mul = new Mul(
new Number(10),
TemperatureValue.Celsius(2).AsExpression()
);
var expected = TemperatureValue.Celsius(20).AsExpression();

SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2 C° * 10")]
public void MulTemperatureByNumber()
{
var mul = new Mul(
TemperatureValue.Celsius(2).AsExpression(),
new Number(10)
);
var expected = TemperatureValue.Celsius(20).AsExpression();

SimplifyTest(mul, expected);
}
Expand Down

0 comments on commit 84d491a

Please sign in to comment.