Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Sources/AngouriMath/Numerics/ComplexParts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ internal static class ComplexParts
private static double Arg(double re, double im)
=> re == 0 && im == 0 ? double.NaN : Math.Atan2(im == 0 ? 0.0 : im, re == 0 ? 0.0 : re);

public static NumericsComplex Re(NumericsComplex z) => z.Real;
/// <summary>
/// The real and the imaginary part, which a number with no value does not have either: a
/// NaN in one part is the whole number's, as a NaN over the doubles has an imaginary part
/// of NaN. Taking only the other part gave <c>Im(Im(x / x))</c> the value 0 at 0, where
/// <c>x / x</c> has none.
/// </summary>
public static NumericsComplex Re(NumericsComplex z) => double.IsNaN(z.Imaginary) ? double.NaN : z.Real;
public static double Re(double x) => x;
public static NumericsComplex Im(NumericsComplex z) => z.Imaginary;
public static NumericsComplex Im(NumericsComplex z) => double.IsNaN(z.Real) ? double.NaN : z.Imaginary;
public static double Im(double x) => double.IsNaN(x) ? double.NaN : 0;
}
}
28 changes: 28 additions & 0 deletions Sources/Tests/UnitTests/Convenience/ComplexPartsCompilationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ public void TheArgumentOfZeroHasNoValue()
Assert.Equal(MathS.NaN, "arg(0)".ToEntity().Evaled);
}

/// <summary>
/// The parts of a value that is not there are not there either. <c>x / x</c> at 0 compiles
/// to <c>NaN + NaN i</c>, its imaginary part to <c>NaN</c>, and the imaginary part of that
/// was <c>0</c>, a value where the interpreter has none.
/// </summary>
[Theory]
[InlineData("Im(Im(x / x))")]
[InlineData("Im(Re(x / x))")]
[InlineData("Re(Im(x / x))")]
[InlineData("Im(Im(sqrt(x) / sqrt(x)))")]
public void APartOfNoValueHasNoValue(string expression)
{
Assert.True(expression.ToEntity().Substitute("x", 0).Evaled.IsNaN);
Assert.True(double.IsNaN(expression.ToEntity().Compile("x").Call(0).Real), $"FastExpression gives {expression.ToEntity().Compile("x").Call(0)}");
Assert.True(double.IsNaN(expression.ToEntity().Compile<NumericsComplex, NumericsComplex>("x")(0).Real),
$"LINQ gives {expression.ToEntity().Compile<NumericsComplex, NumericsComplex>("x")(0)}");
}

/// <summary>A NaN in either part of an argument is the whole argument's.</summary>
[Theory]
[InlineData("Re(x)", 1, double.NaN)]
[InlineData("Im(x)", double.NaN, 1)]
public void ANaNInOnePartIsTheWholeNumbers(string expression, double re, double im)
{
Assert.True(double.IsNaN(expression.ToEntity().Compile("x").Call(new NumericsComplex(re, im)).Real));
Assert.True(double.IsNaN(expression.ToEntity().Compile<NumericsComplex, NumericsComplex>("x")(new NumericsComplex(re, im)).Real));
}

/// <summary>Over doubles, the argument of a negative number is pi, and the imaginary part is 0.</summary>
[Theory]
[InlineData("arg(x)", -2, System.Math.PI)]
Expand Down
Loading