Skip to content

Commit

Permalink
Close #289 - Implement 'Sign', '==', '!=', '<', '>', '<=', '>=' for A…
Browse files Browse the repository at this point in the history
…ngle Numbers
  • Loading branch information
sys27 committed Aug 30, 2020
1 parent da22000 commit 7ea05fe
Show file tree
Hide file tree
Showing 32 changed files with 1,037 additions and 700 deletions.
53 changes: 48 additions & 5 deletions xFunc.Maths/Analyzers/TypeAnalyzers/TypeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,18 @@ private ResultTypes AnalyzeForNumber(BinaryExpression exp)
(ResultTypes.Undefined, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Number, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Undefined, ResultTypes.Number) => ResultTypes.Boolean,
(ResultTypes.AngleNumber, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Undefined, ResultTypes.AngleNumber) => ResultTypes.Boolean,

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

(_, ResultTypes.Number) => ResultTypes.Number.ThrowForLeft(leftResult),
(ResultTypes.Number, _) => ResultTypes.Number.ThrowForRight(rightResult),

(_, ResultTypes.AngleNumber) => ResultTypes.AngleNumber.ThrowForLeft(leftResult),
(ResultTypes.AngleNumber, _) => ResultTypes.AngleNumber.ThrowForRight(rightResult),

_ => throw new ParameterTypeMismatchException(),
};
}
Expand Down Expand Up @@ -147,6 +154,38 @@ private ResultTypes AnalyzeLogicalAndBitwise(BinaryExpression exp)
};
}

private ResultTypes AnalyzeEquality(BinaryExpression exp)
{
var leftResult = exp.Left.Analyze(this);
var rightResult = exp.Right.Analyze(this);

return (leftResult, rightResult) switch
{
(ResultTypes.Undefined, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Number, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Undefined, ResultTypes.Number) => ResultTypes.Boolean,
(ResultTypes.Boolean, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Undefined, ResultTypes.Boolean) => ResultTypes.Boolean,
(ResultTypes.AngleNumber, ResultTypes.Undefined) => ResultTypes.Boolean,
(ResultTypes.Undefined, ResultTypes.AngleNumber) => ResultTypes.Boolean,

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

(_, ResultTypes.Number) => ResultTypes.Number.ThrowForLeft(leftResult),
(ResultTypes.Number, _) => ResultTypes.Number.ThrowForRight(rightResult),

(_, ResultTypes.Boolean) => ResultTypes.Boolean.ThrowForLeft(leftResult),
(ResultTypes.Boolean, _) => ResultTypes.Boolean.ThrowForRight(rightResult),

(_, ResultTypes.AngleNumber) => ResultTypes.AngleNumber.ThrowForLeft(leftResult),
(ResultTypes.AngleNumber, _) => ResultTypes.AngleNumber.ThrowForRight(rightResult),

_ => throw new ParameterTypeMismatchException(),
};
}

#region Standard

/// <summary>
Expand Down Expand Up @@ -840,10 +879,14 @@ public ResultTypes Analyze(UnaryMinus exp)
public ResultTypes Analyze(Sign exp)
{
var result = exp.Argument.Analyze(this);
if (result == ResultTypes.Undefined || result == ResultTypes.Number)
return ResultTypes.Number;

return ResultTypes.Number.ThrowFor(result);
return result switch
{
ResultTypes.Undefined => ResultTypes.Undefined,
ResultTypes.Number => ResultTypes.Number,
ResultTypes.AngleNumber => ResultTypes.AngleNumber,
_ => ResultTypes.Number.ThrowFor(result),
};
}

#endregion Standard
Expand Down Expand Up @@ -1437,7 +1480,7 @@ public ResultTypes Analyze(DivAssign exp)
/// </summary>
/// <param name="exp">The expression.</param>
/// <returns>The result of analysis.</returns>
public ResultTypes Analyze(Equal exp) => AnalyzeLogicalAndBitwise(exp);
public ResultTypes Analyze(Equal exp) => AnalyzeEquality(exp);

/// <summary>
/// Analyzes the specified expression.
Expand Down Expand Up @@ -1525,7 +1568,7 @@ public ResultTypes Analyze(MulAssign exp)
/// </summary>
/// <param name="exp">The expression.</param>
/// <returns>The result of analysis.</returns>
public ResultTypes Analyze(NotEqual exp) => AnalyzeLogicalAndBitwise(exp);
public ResultTypes Analyze(NotEqual exp) => AnalyzeEquality(exp);

/// <summary>
/// Analyzes the specified expression.
Expand Down
62 changes: 61 additions & 1 deletion xFunc.Maths/Expressions/Angles/Angle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace xFunc.Maths.Expressions.Angles
/// <summary>
/// Represents a number with angle measurement unit.
/// </summary>
public readonly struct Angle : IEquatable<Angle>
public readonly struct Angle : IEquatable<Angle>, IComparable<Angle>
{
/// <summary>
/// Initializes a new instance of the <see cref="Angle"/> struct.
Expand Down Expand Up @@ -74,6 +74,25 @@ public bool Equals(Angle other)
public override bool Equals(object obj)
=> obj is Angle other && Equals(other);

/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared. The return value has the following meanings:
/// Less than zero - This object is less than the other parameter.
/// Zero - This object is equal to other.
/// Greater than zero - This object is greater than other.
/// </returns>
public int CompareTo(Angle other)
{
var valueComparison = Value.CompareTo(other.Value);
if (valueComparison != 0)
return valueComparison;

return Unit.CompareTo(other.Unit);
}

/// <summary>
/// Returns a hash code for this instance.
/// </summary>
Expand Down Expand Up @@ -115,6 +134,42 @@ public override int GetHashCode()
public static bool operator !=(Angle left, Angle right)
=> !left.Equals(right);

/// <summary>
/// Indicates whether <paramref name="left"/> parameter is less than the <paramref name="right"/> parameter.
/// </summary>
/// <param name="left">The left angle.</param>
/// <param name="right">The right angle.</param>
/// <returns><c>true</c> if the <paramref name="left"/> parameter is less than the <paramref name="right"/> parameter; otherwise, <c>false</c>.</returns>
public static bool operator <(Angle left, Angle right)
=> left.CompareTo(right) < 0;

/// <summary>
/// Indicates whether <paramref name="left"/> parameter is greater than the <paramref name="right"/> parameter.
/// </summary>
/// <param name="left">The left angle.</param>
/// <param name="right">The right angle.</param>
/// <returns><c>true</c> if the <paramref name="left"/> parameter is greater than the <paramref name="right"/> parameter; otherwise, <c>false</c>.</returns>
public static bool operator >(Angle left, Angle right)
=> left.CompareTo(right) > 0;

/// <summary>
/// Indicates whether <paramref name="left"/> parameter is less than or equal to the <paramref name="right"/> parameter.
/// </summary>
/// <param name="left">The left angle.</param>
/// <param name="right">The right angle.</param>
/// <returns><c>true</c> if the <paramref name="left"/> parameter is less than or equal to the <paramref name="right"/> parameter; otherwise, <c>false</c>.</returns>
public static bool operator <=(Angle left, Angle right)
=> left.CompareTo(right) <= 0;

/// <summary>
/// Indicates whether <paramref name="left"/> parameter is greater than or equal to the <paramref name="right"/> parameter.
/// </summary>
/// <param name="left">The left angle.</param>
/// <param name="right">The right angle.</param>
/// <returns><c>true</c> if the <paramref name="left"/> parameter is greater than or equal to the <paramref name="right"/> parameter; otherwise, <c>false</c>.</returns>
public static bool operator >=(Angle left, Angle right)
=> left.CompareTo(right) >= 0;

/// <summary>
/// Adds two objects of <see cref="Angle"/>.
/// </summary>
Expand Down Expand Up @@ -402,5 +457,10 @@ public static Angle Frac(Angle angle)
/// Gets a unit.
/// </summary>
public AngleUnit Unit { get; }

/// <summary>
/// Gets an integer that indicates the sign of a double-precision floating-point number.
/// </summary>
public int Sign => Math.Sign(Value);
}
}
14 changes: 8 additions & 6 deletions xFunc.Maths/Expressions/Programming/Equal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,14 +43,15 @@ public Equal(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => MathExtensions.Equals(leftDouble, rightDouble),
(bool leftBool, bool rightBool) => leftBool == rightBool,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => MathExtensions.Equals(left, right),
(bool left, bool right) => left == right,
(Angle left, Angle right) => left == right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down
12 changes: 7 additions & 5 deletions xFunc.Maths/Expressions/Programming/GreaterOrEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,13 +43,14 @@ public GreaterOrEqual(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => leftDouble >= rightDouble,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => left >= right,
(Angle left, Angle right) => left >= right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down
12 changes: 7 additions & 5 deletions xFunc.Maths/Expressions/Programming/GreaterThan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,13 +43,14 @@ public GreaterThan(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => leftDouble > rightDouble,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => left > right,
(Angle left, Angle right) => left > right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down
12 changes: 7 additions & 5 deletions xFunc.Maths/Expressions/Programming/LessOrEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,13 +43,14 @@ public LessOrEqual(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => leftDouble <= rightDouble,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => left <= right,
(Angle left, Angle right) => left <= right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down
12 changes: 7 additions & 5 deletions xFunc.Maths/Expressions/Programming/LessThan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,13 +43,14 @@ public LessThan(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => leftDouble < rightDouble,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => left < right,
(Angle left, Angle right) => left < right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down
18 changes: 10 additions & 8 deletions xFunc.Maths/Expressions/Programming/NotEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions.Angles;

namespace xFunc.Maths.Expressions.Programming
{
Expand Down Expand Up @@ -42,14 +43,15 @@ public NotEqual(IExpression left, IExpression right)
/// <seealso cref="ExpressionParameters" />
public override object Execute(ExpressionParameters parameters)
{
var left = Left.Execute(parameters);
var right = Right.Execute(parameters);
var leftResult = Left.Execute(parameters);
var rightResult = Right.Execute(parameters);

return (left, right) switch
return (leftResult, rightResult) switch
{
(double leftDouble, double rightDouble) => !MathExtensions.Equals(leftDouble, rightDouble),
(bool leftBool, bool rightBool) => leftBool != rightBool,
_ => throw new ResultIsNotSupportedException(this, left, right),
(double left, double right) => !MathExtensions.Equals(left, right),
(bool left, bool right) => left != right,
(Angle left, Angle right) => left != right,
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}

Expand Down Expand Up @@ -83,7 +85,7 @@ private protected override TResult AnalyzeInternal<TResult>(IAnalyzer<TResult> a
/// <returns>
/// Returns the new instance of <see cref="NotEqual" /> that is a clone of this instance.
/// </returns>
public override IExpression Clone() =>
new NotEqual(Left.Clone(), Right.Clone());
public override IExpression Clone()
=> new NotEqual(Left.Clone(), Right.Clone());
}
}

0 comments on commit 7ea05fe

Please sign in to comment.