Skip to content

Commit

Permalink
Merge pull request #693 from sys27/feature/rational-number
Browse files Browse the repository at this point in the history
#175 - Support rational numbers
  • Loading branch information
sys27 committed Aug 27, 2023
2 parents e93f13e + 44396df commit ff712e6
Show file tree
Hide file tree
Showing 61 changed files with 2,152 additions and 261 deletions.
1 change: 1 addition & 0 deletions docs/articles/change-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [#680](https://github.com/sys27/xFunc/issues/680) - Remove Moq. ([#651](https://github.com/sys27/xFunc/pull/651)).
* [#688](https://github.com/sys27/xFunc/issues/688) - DocFx Documentation.
* [#175](https://github.com/sys27/xFunc/pull/175) - Support rational numbers ([#693](https://github.com/sys27/xFunc/pull/693)).

## xFunc v4.3.0

Expand Down
217 changes: 109 additions & 108 deletions docs/articles/supported-functions-and-operations.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions xFunc.Maths/Analyzers/Analyzer{TResult,TContext}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ public virtual TResult Analyze(StringExpression exp, TContext context)
public virtual TResult Analyze(Expressions.Units.Convert exp, TContext context)
=> Analyze(exp as IExpression, context);

/// <inheritdoc />
public virtual TResult Analyze(Rational exp, TContext context)
=> Analyze(exp as IExpression, context);

/// <inheritdoc />
public virtual TResult Analyze(ToRational exp, TContext context)
=> Analyze(exp as IExpression, context);

#endregion Standard

#region Matrix
Expand Down
8 changes: 8 additions & 0 deletions xFunc.Maths/Analyzers/Analyzer{TResult}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ public virtual TResult Analyze(StringExpression exp)
public virtual TResult Analyze(Expressions.Units.Convert exp)
=> Analyze(exp as IExpression);

/// <inheritdoc />
public virtual TResult Analyze(Rational exp)
=> Analyze(exp as IExpression);

/// <inheritdoc />
public virtual TResult Analyze(ToRational exp)
=> Analyze(exp as IExpression);

#endregion Standard

#region Matrix
Expand Down
8 changes: 8 additions & 0 deletions xFunc.Maths/Analyzers/Formatters/CommonFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,14 @@ public virtual string Analyze(Expressions.Units.Convert exp)
return $"convert({value}, {unit})";
}

/// <inheritdoc />
public virtual string Analyze(Rational exp)
=> ToString(exp, "{0} // {1}");

/// <inheritdoc />
public virtual string Analyze(ToRational exp)
=> ToString(exp, "torational({0})");

#endregion Standard

#region Matrix
Expand Down
16 changes: 16 additions & 0 deletions xFunc.Maths/Analyzers/IAnalyzer{TResult,TContext}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,22 @@ public interface IAnalyzer<out TResult, in TContext>
/// <returns>The result of analysis.</returns>
TResult Analyze(Expressions.Units.Convert exp, TContext context);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <param name="context">The context.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(Rational exp, TContext context);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <param name="context">The context.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(ToRational exp, TContext context);

#endregion Standard

#region Matrix
Expand Down
14 changes: 14 additions & 0 deletions xFunc.Maths/Analyzers/IAnalyzer{TResult}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,20 @@ public interface IAnalyzer<out TResult>
/// <returns>The result of analysis.</returns>
TResult Analyze(Expressions.Units.Convert exp);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(Rational exp);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(ToRational exp);

#endregion Standard

#region Matrix
Expand Down
5 changes: 5 additions & 0 deletions xFunc.Maths/Analyzers/TypeAnalyzers/ResultTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ public enum ResultTypes
/// The expression returns a volume number.
/// </summary>
VolumeNumber = 1 << 15,

/// <summary>
/// The returns a rational number.
/// </summary>
RationalNumber = 1 << 16,
}
81 changes: 78 additions & 3 deletions xFunc.Maths/Analyzers/TypeAnalyzers/TypeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ public virtual ResultTypes Analyze(Abs exp)
ResultTypes.TimeNumber => ResultTypes.TimeNumber,
ResultTypes.AreaNumber => ResultTypes.AreaNumber,
ResultTypes.VolumeNumber => ResultTypes.VolumeNumber,
ResultTypes.RationalNumber => ResultTypes.RationalNumber,
_ => NumbersOrComplexOrVector.ThrowFor(result),
};
}
Expand Down Expand Up @@ -488,6 +489,11 @@ public virtual ResultTypes Analyze(Add exp)
(ResultTypes.ComplexNumber, ResultTypes.ComplexNumber)
=> ResultTypes.ComplexNumber,

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

(ResultTypes.Vector, ResultTypes.Vector) => ResultTypes.Vector,
(ResultTypes.Matrix, ResultTypes.Matrix) => ResultTypes.Matrix,

Expand Down Expand Up @@ -631,6 +637,11 @@ public virtual ResultTypes Analyze(Div exp)
(ResultTypes.ComplexNumber, ResultTypes.ComplexNumber)
=> ResultTypes.ComplexNumber,

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

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

Expand Down Expand Up @@ -779,10 +790,10 @@ public virtual ResultTypes Analyze(Lb exp)
throw new ArgumentNullException(nameof(exp));

var result = exp.Argument.Analyze(this);
if (result is ResultTypes.Undefined or ResultTypes.Number)
if (result is ResultTypes.Undefined or ResultTypes.Number or ResultTypes.RationalNumber)
return ResultTypes.Number;

return ResultTypes.Number.ThrowFor(result);
return (ResultTypes.Number | ResultTypes.RationalNumber).ThrowFor(result);
}

/// <inheritdoc />
Expand Down Expand Up @@ -817,6 +828,8 @@ public virtual ResultTypes Analyze(Lg exp)
ResultTypes.Undefined => ResultTypes.Undefined,
ResultTypes.Number => ResultTypes.Number,
ResultTypes.ComplexNumber => ResultTypes.ComplexNumber,
ResultTypes.RationalNumber => ResultTypes.Number,

_ => NumberOrComplex.ThrowFor(result),
};
}
Expand All @@ -834,6 +847,8 @@ public virtual ResultTypes Analyze(Ln exp)
ResultTypes.Undefined => ResultTypes.Undefined,
ResultTypes.Number => ResultTypes.Number,
ResultTypes.ComplexNumber => ResultTypes.ComplexNumber,
ResultTypes.RationalNumber => ResultTypes.Number,

_ => NumberOrComplex.ThrowFor(result),
};
}
Expand All @@ -855,6 +870,7 @@ public virtual ResultTypes Analyze(Log exp)

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

(ResultTypes.Number, _) => NumberOrComplex.ThrowForRight(rightResult),

Expand Down Expand Up @@ -949,6 +965,11 @@ public virtual ResultTypes Analyze(Mul exp)
(ResultTypes.ComplexNumber, ResultTypes.ComplexNumber)
=> ResultTypes.ComplexNumber,

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

(ResultTypes.Vector, ResultTypes.Number) or
(ResultTypes.Number, ResultTypes.Vector) or
(ResultTypes.Vector, ResultTypes.Vector)
Expand Down Expand Up @@ -1071,7 +1092,8 @@ ResultTypes.MassNumber or
ResultTypes.LengthNumber or
ResultTypes.TimeNumber or
ResultTypes.AreaNumber or
ResultTypes.VolumeNumber
ResultTypes.VolumeNumber or
ResultTypes.RationalNumber
=> ResultTypes.Number,
_ => Units.ThrowFor(result),
};
Expand Down Expand Up @@ -1101,6 +1123,9 @@ public virtual ResultTypes Analyze(Pow exp)
(ResultTypes.Number, ResultTypes.Number)
=> ResultTypes.Undefined,

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

_ => ResultTypes.Number.ThrowForLeft(leftResult),
};
}
Expand Down Expand Up @@ -1237,6 +1262,11 @@ public virtual ResultTypes Analyze(Sub exp)
(ResultTypes.ComplexNumber, ResultTypes.ComplexNumber)
=> ResultTypes.ComplexNumber,

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

(ResultTypes.Vector, ResultTypes.Vector) => ResultTypes.Vector,
(ResultTypes.Matrix, ResultTypes.Matrix) => ResultTypes.Matrix,

Expand Down Expand Up @@ -1301,6 +1331,7 @@ public virtual ResultTypes Analyze(UnaryMinus exp)
ResultTypes.AreaNumber => ResultTypes.AreaNumber,
ResultTypes.VolumeNumber => ResultTypes.VolumeNumber,
ResultTypes.ComplexNumber => ResultTypes.ComplexNumber,
ResultTypes.RationalNumber => ResultTypes.RationalNumber,
_ => NumberOrComplex.ThrowFor(result),
};
}
Expand Down Expand Up @@ -1392,6 +1423,50 @@ ResultTypes.Undefined or
};
}

/// <inheritdoc />
public virtual ResultTypes Analyze(Rational exp)
{
if (exp is null)
throw new ArgumentNullException(nameof(exp));

var leftResult = exp.Left.Analyze(this);
var rightResult = exp.Right.Analyze(this);

return (leftResult, rightResult) switch
{
(ResultTypes.Undefined, _) or (_, ResultTypes.Undefined)
=> ResultTypes.Undefined,

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

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

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

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

/// <inheritdoc />
public virtual ResultTypes Analyze(ToRational exp)
{
if (exp is null)
throw new ArgumentNullException(nameof(exp));

var argumentResult = exp.Argument.Analyze(this);

return argumentResult switch
{
ResultTypes.Undefined => ResultTypes.Undefined,
ResultTypes.Number => ResultTypes.RationalNumber,

_ => throw new ParameterTypeMismatchException(ResultTypes.Number, argumentResult),
};
}

#endregion Standard

#region Matrix
Expand Down
1 change: 1 addition & 0 deletions xFunc.Maths/Expressions/Abs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public override object Execute(ExpressionParameters? parameters)
VolumeValue volume => VolumeValue.Abs(volume),
Complex complex => Complex.Abs(complex),
VectorValue vector => VectorValue.Abs(vector),
RationalValue rationalValue => RationalValue.Abs(rationalValue),
_ => throw new ResultIsNotSupportedException(this, result),
};
}
Expand Down
4 changes: 4 additions & 0 deletions xFunc.Maths/Expressions/Add.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public override object Execute(ExpressionParameters? parameters)
(Complex left, NumberValue right) => left + right,
(Complex left, Complex right) => left + right,

(NumberValue left, RationalValue right) => left + right,
(RationalValue left, NumberValue right) => left + right,
(RationalValue left, RationalValue right) => left + right,

(VectorValue left, VectorValue right) => left + right,
(MatrixValue left, MatrixValue right) => left + right,

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

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

_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}
Expand Down
2 changes: 2 additions & 0 deletions xFunc.Maths/Expressions/Lb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public override object Execute(ExpressionParameters? parameters)
return result switch
{
NumberValue number => NumberValue.Lb(number),
RationalValue rationalValue => RationalValue.Lb(rationalValue),

_ => throw new ResultIsNotSupportedException(this, result),
};
}
Expand Down
2 changes: 2 additions & 0 deletions xFunc.Maths/Expressions/Lg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public override object Execute(ExpressionParameters? parameters)
{
NumberValue number => NumberValue.Lg(number),
Complex complex => Complex.Log10(complex),
RationalValue rationalValue => RationalValue.Lg(rationalValue),

_ => throw new ResultIsNotSupportedException(this, result),
};
}
Expand Down
2 changes: 2 additions & 0 deletions xFunc.Maths/Expressions/Ln.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public override object Execute(ExpressionParameters? parameters)
{
NumberValue number => NumberValue.Ln(number),
Complex complex => Complex.Log(complex),
RationalValue rationalValue => RationalValue.Ln(rationalValue),

_ => throw new ResultIsNotSupportedException(this, result),
};
}
Expand Down
1 change: 1 addition & 0 deletions xFunc.Maths/Expressions/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public override object Execute(ExpressionParameters? parameters)
{
(NumberValue left, NumberValue right) => NumberValue.Log(right, left),
(NumberValue left, Complex complex) => NumberValue.Log(complex, left),
(NumberValue left, RationalValue right) => RationalValue.Log(right, left),
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}
Expand Down
4 changes: 4 additions & 0 deletions xFunc.Maths/Expressions/Mul.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ public override object Execute(ExpressionParameters? parameters)
(Complex left, NumberValue right) => left * right,
(Complex left, Complex right) => left * right,

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

(VectorValue left, VectorValue right) => left * right,
(NumberValue left, VectorValue right) => right * left,
(VectorValue left, NumberValue right) => left * right,
Expand Down
13 changes: 12 additions & 1 deletion xFunc.Maths/Expressions/Parameters/ParameterValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ public ParameterValue(Lambda lambda)
{
}

/// <inheritdoc cref="ParameterValue(object)"/>
public ParameterValue(RationalValue rationalValue)
: this(rationalValue as object)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ParameterValue" /> struct.
/// </summary>
Expand All @@ -131,7 +137,8 @@ or bool
or VectorValue
or MatrixValue
or string
or Lambda,
or Lambda
or RationalValue,
"Unsupported parameter value.");

Value = value;
Expand Down Expand Up @@ -205,6 +212,10 @@ or string
public static implicit operator ParameterValue(Lambda value)
=> new ParameterValue(value);

/// <inheritdoc cref="ParameterValue.op_Implicit(double)"/>
public static implicit operator ParameterValue(RationalValue value)
=> new ParameterValue(value);

/// <inheritdoc />
public bool Equals(ParameterValue other)
=> Value.Equals(other.Value);
Expand Down
1 change: 1 addition & 0 deletions xFunc.Maths/Expressions/Pow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public override object Execute(ExpressionParameters? parameters)
(NumberValue left, Complex right) => Complex.Pow(left.Number, right),
(Complex left, NumberValue right) => NumberValue.Pow(left, right),
(Complex left, Complex right) => Complex.Pow(left, right),
(RationalValue left, NumberValue right) => RationalValue.Pow(left, right),
_ => throw new ResultIsNotSupportedException(this, leftResult, rightResult),
};
}
Expand Down

0 comments on commit ff712e6

Please sign in to comment.