Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Complex arithmetic operators and math functions now produce the special-value results (for signed zeros, infinities, and NaNs) required by C23 Annex G (IEC 60559-compatible complex arithmetic). Because Complex now delegates most of its implementation to the new Complex<double> type, the conformant special-value handling flows through to it.
Version introduced
.NET 11 Preview 7
Previous behavior
Previously, for non-finite (and some overflowing) inputs, Complex arithmetic and elementary functions frequently returned (NaN, NaN) even when a directed infinity or signed result was mathematically appropriate.
using System.Numerics;
Complex.Atan(new Complex(double.PositiveInfinity, 1.0)); // (NaN, NaN)
Complex.Acos(new Complex(double.NegativeInfinity, double.NaN)); // (NaN, NaN)
Complex.Cosh(new Complex(double.PositiveInfinity, double.PositiveInfinity)); // (NaN, NaN)
// An infinite operand could collapse the product to NaN:
new Complex(double.PositiveInfinity, double.PositiveInfinity) * new Complex(1.0, 0.0); // (NaN, NaN)
New behavior
Starting in .NET 11, the same inputs return the C23 Annex G special values.
using System.Numerics;
Complex.Atan(new Complex(double.PositiveInfinity, 1.0)); // (π/2, 0)
Complex.Acos(new Complex(double.NegativeInfinity, double.NaN)); // (NaN, +∞)
Complex.Cosh(new Complex(double.PositiveInfinity, double.PositiveInfinity)); // (+∞, NaN)
// An infinite operand now yields a directed infinity (Annex G.5.1 recovery):
new Complex(double.PositiveInfinity, double.PositiveInfinity) * new Complex(1.0, 0.0); // (+∞, +∞)
Division by a zero divisor is likewise governed by Annex G: the result is a directed infinity, or NaN for 0/0. For example, (1, 0) / (0, 0) yields an infinite real component rather than a fully NaN result.
The change spans operator *, operator /, Multiply, Divide, Reciprocal, Abs, Pow, and the elementary functions (Sqrt, Exp, Log, Log10, and the trigonometric, hyperbolic, and inverse-trigonometric functions). One case Annex G leaves explicitly unspecified, that is, the sign of a zero-valued quotient component from operator /, might also differ.
Type of breaking change
This change is a behavioral change.
Reason for change
Complex numbers are outside the scope of IEEE 754 itself, so C23 Annex G is the relevant specification of the special-value behavior IEEE 754 otherwise implies for the scalar operations complex arithmetic is built on. The previous implementation returned NaN for many inputs where Annex G requires a directed infinity or a signed result, which is both non-conformant and less useful for downstream numerical code, because it lost the sign or direction information that an infinite intermediate value carries. The new generic Complex<T> type was made conformant, and the shipped Complex type inherits that conformance by delegation.
For more information, see dotnet/runtime#131132.
Recommended action
Most code benefits from the more accurate results and needs no change. If your code explicitly depends on the previous (NaN, NaN) results for special-value inputs, update it to expect the Annex G values. Such code might be tests that assert NaN for Complex operations on infinities, or logic that treats any non-finite input as producing NaN.
There's no compatibility switch to restore the previous behavior.
Affected APIs
- Complex.Multiply(Complex, Complex)
- Complex.Division(Complex, Complex)
- Complex.Multiply(Complex, Complex)
- Complex.Divide(Complex, Complex)
- Complex.Reciprocal(Complex)
- Complex.Abs(Complex)
- Complex.Pow(Complex, Complex) and Complex.Pow(Complex, Double)
- Complex.Sqrt(Complex)
- Complex.Exp(Complex)
- Complex.Log(Complex) (all overloads) and Complex.Log10(Complex)
- Complex.Sin(Complex), Complex.Cos(Complex), Complex.Tan(Complex), Complex.Sinh(Complex), Complex.Cosh(Complex), Complex.Tanh(Complex)
- Complex.Asin(Complex), Complex.Acos(Complex), Complex.Atan(Complex)