# [Libre-soc-dev] complex numbers as matrices

Richard Wilbur richard.wilbur at gmail.com
Wed Jun 30 20:52:45 BST 2021

```
> On Jun 30, 2021, at 12:58 PM, Jacob Lifshay <programmerjake at gmail.com> wrote:
>
> On Wed, Jun 30, 2021, 11:07 Richard Wilbur <richard.wilbur at gmail.com <mailto:richard.wilbur at gmail.com>> wrote:
>
>> complex - complex = 2 scalar negations, 2 scalar additions (covered by
>> vector operations)
>>
>
> wouldn't this just be a vec2 subtraction? no need for separate negation and

You are correct.  Hence my note above, “(covered by vector operations)”.

>> reciprocal(complex) = (1/abs(complex)) x conjugate(complex)
>>
>
> that's wrong, the correct expression is:
> z = re+i*im
> reciprocal(z) = conjugate(z) / (re^2 + im^2)

You are correct.  The happy situation then is simpler because in my formulation I forgot the exponent 2 on the abs(complex).  This greatly simplifies the calculation (removing the need of a square root)!

>>
>> equality (for z1 = a1 + jb1, z2 = a2 + jb2)
>> z1 == z2 <=> ((a1 == a2) and (b1 == b2)) (this is the same as vectors)
>>
>> ordering is more complicated than normal scalars:  Two fairly simple
>> possible schemas come to mind and both involve the polar form.  z1 = (r1,
>> θ1), z2 = (r2, θ2)
>> r-major:  z1 < z2 <=> ((r1 < r2) or ((r1 == r2) and (θ1 < θ2))),
>> θ-major:  z1 < z2 <=> ((θ1 < θ2) or ((θ1 == θ2) and (r1 < r2)))
>>
>
> I would argue that, if we provide ordering for complex numbers, we should
> use real-major form since it's much simpler to compute and since complex
> numbers don't normally have an ordering defined.
> z1 = r1 + i*i1, z2 = r2 + i*i2
> z1 < z2 <=> (r1 < r2) || (r1 == r2 && i1 < i2)

You beat me to it!  After I sent the original proposal I was tending to other things and the obvious hit me:  if we don’t care about a particular geometric interpretation, resorting to a real-major ordering based directly on comparisons of the components would be computationally far simpler and still upholds the traditional equality condition stated above.  This also bears out an important correspondence, when the imaginary parts are 0 the comparison matches what we would expect from a pair of normal real numbers.  My other proposals would not have matched this without a flip in the condition because of the properties of atan2:  arg(-r + j0) = pi,  arg(r + j0) = 0.

> This is the same order you would get in Rust for:
> #[derive(PartialEq, PartialOrd)]
> pub struct MyComplex {
>    real: f32,
>    imag: f32,
> }
> or:
> pub type MyComplex = (f32, f32);
>
> or in C++ for:
> struct MyComplex {
>    float real, imag;
>    auto operator <=>(const MyComplex &) const = default;
> };

Sounds like it would be a side-effect of the order of declaration and the properties of Rust and C++ as programming languages.  Happy coincidence but seems a little too haphazard as a reason to adopt.  I prefer the computational simplicity argument.

```