View Raw SPL
/*****************************************************************************
* *
* CPLXPAIR.SPL Copyright (C) 2003-2015 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Orders complex values by complex conjugates *
* *
* Revisions: 15 Oct 2003 RRR Creation *
* 12 Jun 2015 RRR conjugate sorting, negative first *
* *
*****************************************************************************/
#if @HELP_CPLXPAIR
CPLXPAIR
Purpose: Groups complex values by conjugate pairs.
Syntax: CPLXPAIR(z, tol)
z - A series, the complex values.
tol - Optional. A real, the tolerance to determine a purely
real value. Defaults to 100 * eps.
Returns: A series, the ordered paired complex conjugate values.
Example:
W1: 1..6
W2: roots(w1)
W3: cplxpair(w2)
W2 == {0.551685 + 1.253349i,
0.551685 - 1.253349i,
-1.491798 + 0.000000i,
-0.805786 + 1.222905i,
-0.805786 - 1.222905i}
W3 == {-0.805786 - 1.222905i,
-0.805786 + 1.222905i,
0.551685 - 1.253349i,
0.551685 + 1.253349i,
-1.491798 + 0.000000i}
W1 represents the polynomial:
y(x) = x^5 + 2x^4 + 3x^3 + 4x^2 + 5x + 6
W2 contains the roots of y(x).
W3 sorts the roots in ascending order with the purely real
root at the end of the list.
Remarks:
CPLXPAIR groups complex conjugate pairs of complex numbers
in ascending order. The value with a negative imaginary
part precedes the paired value with a positive imaginary part.
Purely real values are placed at the end of the list.
The tolerance tol specifies the threshold of the absolute
value of the imaginary part below which the value is
considered purely real.
An error occurs if the values cannot be paired.
See Also:
Cartesian
Imaginary
Real
Sort
#endif
/* return complex pairs */
ITERATE cplxpair(z, tol)
{
local y, q, idx, n, i;
if (argc < 1 || argc > 2)
{
error("(z, n) = cplxpair(z [, tol]);");
}
if (argc < 2) tol = 100*eps;
y = zeros(size(z));
if (length(z) == 0) return({});
// sort in ascending order
idx = grade(real(z), 1);
z = z[idx];
// purely real values at end of list
idx = find(mag(imag(z)) / (mag(z)+realmin) < tol);
n = length(z) - length(idx);
if (length(idx) > 0)
{
y[n+1..length(z)] = z[idx];
z[idx] = {};
}
// put remaining values and conjugates at the start of list
if (n > 0)
{
loop (i = 1..2..n)
{
if (i+1 > n)
{
error("cplxpair - could not pair all complex numbers");
}
(v, idx) = min(mag(z[i+1..n] - conj(z[i])));
if (v > tol)
{
error ("cplxpair - could not pair all complex numbers");
}
if (imag(z[i]) < 0)
{
y[{i, i+1}] = z[{i, idx+i}];
}
else
{
y[{i, i+1}] = z[{idx+i, i}];
}
z[idx+i] = z[i+1];
}
}
return(y, n);
}