octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Sorting complex values


From: Daniel J Sebald
Subject: Re: Sorting complex values
Date: Sat, 27 Sep 2014 13:43:21 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.24) Gecko/20111108 Fedora/3.1.16-1.fc14 Thunderbird/3.1.16

On 09/27/2014 12:44 PM, Rik wrote:
All,

Could someone check the following under Matlab, just for confirmation?

x = [ [1 -1 i -i].' [1 -1 i -i]' ]
angle (x)

Under Octave, this gives

octave:48>  x = [ [1 -1 i -i].' [1 -1 i -i]' ]
x =

    1 + 0i   1 - 0i
   -1 + 0i  -1 - 0i
    0 + 1i   0 - 1i
   -0 - 1i  -0 + 1i

octave:49>  angle (x)
ans =

    0.00000  -0.00000
    3.14159  -3.14159
    1.57080  -1.57080
   -1.57080   1.57080

The issue is the second line where -1 + 0i has a different phase angle then
-1 - 0i.  Thus -1 can appear either first or last in the list produced by
sort() depending on the phase angle.

octave:50>  sort (x)
ans =

   -0 - 1i  -1 - 0i
    1 + 0i   0 - 1i
    0 + 1i   1 - 0i
   -1 + 0i  -0 + 1i

This is a little odd.  One would expect the sorted list to be the same
which is indeed what Matlab does.

The question is whether we want to do anything about this, or should we
just relegate it to being a quirk?

The actual comparison code is a macro in liboctave/util/oct-cmplx.h

#define DEF_COMPLEXR_COMP(OP, OPS) \
template<class T>  \
inline bool operator OP (const std::complex<T>&  a, const std::complex<T>&  b) \
{ \
   FLOAT_TRUNCATE const T ax = std::abs (a); \
   FLOAT_TRUNCATE const T bx = std::abs (b); \
   if (ax == bx) \
     { \
       FLOAT_TRUNCATE const T ay = std::arg (a); \
       FLOAT_TRUNCATE const T by = std::arg (b); \
       return ay OP by; \
     } \
   else \
     return ax OPS bx; \
} \

The std::arg for a C++ complex value internally calls atan2.

In terms of frequency of occurrence, I'd say it's not exactly easy to
generate this situation, but it also isn't particularly hard.  At the
interpreter level, Octave rationalizes '-0i' to '+0i' which makes it
unlikely for user-generated input.

[-1-0i, i]
  -1 + 0i   0 + 1i

But it is easy to get the -0 with either complex() or by taking the conjugate.

complex (-1, -0)
ans = -1 - 0i

[-1+0i, i]'
ans =

   -1 - 0i
    0 - 1i

Should we fix this?

Maybe.

First, complex numbers aren't an ordered field, so sorting is fraught with peculiarities. It's not really -1 being at a particular point in the order, it's a number (-1) whose magnitude is the same as three others and appearing at a perhaps arbitrary location. Swap around the order in which the magnitude 1 numbers are input and it might come out with a different order output.

The one thing that concerns me a bit is that -1 - 0i produces an angle of -pi. Typically when one speaks of argument (going from the complex number to the argument and not vice versa) it is the principle argument, having a range whose lower limit is open, i.e., (-pi,pi]. Often in phase diagrams, the phase is unwrapped so that pi may be remapped to ..., -3pi, -pi, pi, 3pi, ... but that is a secondary use. So even though atan(-1,-0) might produce -pi, maybe anything with -0 as the imaginary component should be set equal to pi for the argument.

Dan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]