That's not quite what I'm suggesting. I'm advocating for (essentially) two additional types on top of the existing Double
type: an Imaginary
type and a Complex
type. (I'm roughly thinking of Double
and Real
as being the same thing for the moment.) The idea here is that Real
and Imaginary
are both backed by a single floating point value, while the Complex
type is a structure containing a Real
and Imaginary
value.
The advantage to having an Imaginary
type separate from Complex
type is two-fold:
- fewer floating point operations, and
- smaller memory footprint.
This may also have another advantage. There are two-standard data structures for storing complex types that mimic DSPComplex
(as mentioned by Howard Lovatt) and DSPSplitComplex
. In the first case, the real part and imaginary part are interleaved, with a stride of 1 separating them. In the second case, the there is a pointer to the real array and a pointer the imaginary array. So now, if you want to mimic the equivalent of DSPComplex
and DSPSplitComplex
with Swift, you'd do
let interleavedArray : Array<Complex> = [Complex(1.0,1.0),Complex(2.0,1.0)]
let realArray : Array<Real> = [Real(1.0),Real(2.0)]
let imagArray : Array<Imaginary> = [Imaginary(1.0),Imaginary(1.0)]
So this has the advantage of reproducing both standard data structures, and not losing any information about the underlying type, by which I mean the array of Imaginary
numbers has the right data structure for use in these algorithms, but also behaves correctly mathematically. I don't think you can achieve this if you only have a Complex
type.
My earlier idea was that the squareRoot
function on Real
numbers would then only return a Real
or an Imaginary
---never a Complex
. Thus, any current check to .isNaN
can simply be replaced by .isImaginary
.
I don't understand the implications of this---would this make things worse?