diff --git a/Sources/AngouriMath/Numerics/ComplexParts.cs b/Sources/AngouriMath/Numerics/ComplexParts.cs
index 147884535..72a5f9b1a 100644
--- a/Sources/AngouriMath/Numerics/ComplexParts.cs
+++ b/Sources/AngouriMath/Numerics/ComplexParts.cs
@@ -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;
+ ///
+ /// 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 Im(Im(x / x)) the value 0 at 0, where
+ /// x / x has none.
+ ///
+ 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;
}
}
diff --git a/Sources/Tests/UnitTests/Convenience/ComplexPartsCompilationTest.cs b/Sources/Tests/UnitTests/Convenience/ComplexPartsCompilationTest.cs
index 96ee8e09c..099825f7f 100644
--- a/Sources/Tests/UnitTests/Convenience/ComplexPartsCompilationTest.cs
+++ b/Sources/Tests/UnitTests/Convenience/ComplexPartsCompilationTest.cs
@@ -59,6 +59,34 @@ public void TheArgumentOfZeroHasNoValue()
Assert.Equal(MathS.NaN, "arg(0)".ToEntity().Evaled);
}
+ ///
+ /// The parts of a value that is not there are not there either. x / x at 0 compiles
+ /// to NaN + NaN i, its imaginary part to NaN, and the imaginary part of that
+ /// was 0, a value where the interpreter has none.
+ ///
+ [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("x")(0).Real),
+ $"LINQ gives {expression.ToEntity().Compile("x")(0)}");
+ }
+
+ /// A NaN in either part of an argument is the whole argument's.
+ [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("x")(new NumericsComplex(re, im)).Real));
+ }
+
/// Over doubles, the argument of a negative number is pi, and the imaginary part is 0.
[Theory]
[InlineData("arg(x)", -2, System.Math.PI)]