Open Dr-Wizard opened 6 months ago
This is a deliberate design choice, see the documentation for these properties:
If
z
is not finite,z.real
is.nan
. Ifz
is not finite,z.imaginary
is.nan
.
and README.md for Complex:
C and C++ attempt to define semantics that interpret the signs of infinity and zero. This is occasionally useful, but it also results in a lot of extra work. The Swift Numerics Complex type does not assign any semantic meaning to the sign of zero and infinity; (±0,±0), are all considered to be encodings of the value zero. Similarly, (±inf, y), (x, ±inf), (nan, y) and (x, nan) are all considered to be encodings of a single exceptional value with infinite magnitude and undefined phase.
Because the phase is undefined, the real and imaginary properties return .nan for non-finite values.
If you have a specific use for the raw values in mind, we can consider removing the underscore for the existing _rawX
and _rawY
properties or otherwise exposing those values as API.
I understand the simplification. Mathematically, however, it must be possible to distinguish between NaN and Inf and also between the real and imaginary parts of these two exceptions. For example, the angle of (Inf,y) is by definition 0, of (-Inf,y) equal to -pi. The angle of (Inf,Inf) is pi/4, so the simplification is not allowed and Swift handles these exceptions (NaN, Inf) correctly. For example, sin(inf)=NaN. The distinction between +/-0 is mandatory in my opinion. Access to the raw values (x and y) can be a step in the right direction and help. However, it must be ensured that the functions within the library also use them correctly.
For example, the angle of (inf,y) is by definition 0, of (-inf,y) equal to -pi.
No; a type defines its semantics. The angle of (inf, y) is undefined, because the type specifies it as such.
There is no unique "mathematical" definition to appeal to here. In the traditional complex plane, points at infinity simply do not exist. For the Alexandroff compactification (aka Riemann sphere) of the complex plane, there is a single point at infinity with undefined phase (because it sits at the limit of every ray from the origin). C's complex type attempts to extend IEEE 754's two-point compactification of the reals to the complex plane with mixed results (it preserves more information, but the resulting arithmetic is not really consistent in a way that you can make useful claims about). Fortran mostly pretends that complex infinities don't exist.
I agree, that infinity does not exist for complex numbers in the gaussian complex plane and that you cannot conclude the real and imaginary part for extended complex numbers on the Riemann sphere. Anyhow, setting both real and imaginary part to nan if the complex number is not finite hides important information about what the complex number to not be finite. In engineering and system theory complex numbers are commonly interpreted as two vectors, one on the real axis and one on the imaginary axis. Consider for example the rotating pointer of a three-phase-current system, a Laplace transform or a transfer function in control systems. They all are based on complex numbers and in that context it is important to know, if either the real or the imagiary part or both reached infinity. That's the reasons, why numerical software packages like Matlab or Octave return this information and let the interpretation up to the user.
The real and imaginary part of a complex number are extracted as follows:
public var real: RealType { @_transparent get { isFinite ? x : .nan }
}
public var imaginary: RealType { @_transparent get { isFinite ? y : .nan }
}
By checking for isFinite can give wrong values, since infinity is not returned correctly as eg. 1/0 is not .nan but .inf. In a complex number, one part can have a regular value while the other is infinite or nan. With the isFinite check, nan is returned for both parts as soon as one of the two parts is not a regular number. (inf or nan) I suggest returning x and y without the isFinite check.