summaryrefslogtreecommitdiff
path: root/macros/cplxpair.sci
diff options
context:
space:
mode:
authorAbinash Singh2024-08-08 16:31:44 +0530
committerAbinash Singh2024-08-08 16:33:51 +0530
commit1a3caa688450fd49135a1777418c7370e15bb72d (patch)
tree99447e3e11591651bbb160855fece4e7d82ffc77 /macros/cplxpair.sci
parentf8ae45ed71b709b3308a472ca00d641d6ba0fda3 (diff)
downloadFOSSEE-Signal-Processing-Toolbox-1a3caa688450fd49135a1777418c7370e15bb72d.tar.gz
FOSSEE-Signal-Processing-Toolbox-1a3caa688450fd49135a1777418c7370e15bb72d.tar.bz2
FOSSEE-Signal-Processing-Toolbox-1a3caa688450fd49135a1777418c7370e15bb72d.zip
Imlemented by Abinash Singh During FOSSEE Semester Long Fellowship 2024
Diffstat (limited to 'macros/cplxpair.sci')
-rw-r--r--macros/cplxpair.sci107
1 files changed, 107 insertions, 0 deletions
diff --git a/macros/cplxpair.sci b/macros/cplxpair.sci
new file mode 100644
index 0000000..16fceac
--- /dev/null
+++ b/macros/cplxpair.sci
@@ -0,0 +1,107 @@
+/*Description
+ Sort the numbers z into complex conjugate pairs ordered by increasing real part.
+ The negative imaginary complex numbers are placed first within each pair. All real numbers (those with abs (imag (z) / z) < tol) are placed after the complex pairs.
+ and the resulting tolerance for a given complex pair is 100 * eps (abs (z(i))).
+ Signal an error if some complex numbers could not be paired. Signal an error if all complex numbers are not exact conjugates (to within tol).
+ Note that there is no defined order for pairs with identical real parts but differing imaginary parts
+Calling Sequence
+ cplxpair (z)
+ cplxpair (z, tol)
+ cplxpair (z, tol, dim)
+Parameters:
+ z is a matrix or vector.
+ tol is a weighting factor which determines the tolerance of matching. The default value is 100.
+ By default the complex pairs are sorted along the first non-singleton dimension of z. If dim is specified, then the complex pairs are sorted along this dimension.
+Dependencies: ipermute
+Example:
+ The following code
+ [ cplxpair(exp(2*%i*%pi*[0:4]'/5)), exp(2*%i*%pi*[3; 2; 4; 1; 0]/5) ]
+ Produces the following output
+ ans =
+ -0.80902 - 0.58779i -0.80902 - 0.58779i
+ -0.80902 + 0.58779i -0.80902 + 0.58779i
+ 0.30902 - 0.95106i 0.30902 - 0.95106i
+ 0.30902 + 0.95106i 0.30902 + 0.95106i
+ 1.00000 + 0.00000i 1.00000 + 0.00000i
+*/
+function zsort = cplxpair (z, tol, dim)
+ if (nargin < 1)
+ error("Invalid inputs");
+ end
+ // default double
+ realmin = 2.2251e-308
+ if (isempty (z))
+ zsort = zeros (size (z,1) , size (z,2));
+ return;
+ end
+ if (nargin < 2 || isempty (tol))
+ tol = 100* %eps;
+ elseif (~ isscalar (tol) || tol < 0 || tol >= 1)
+ error ("cplxpair: TOL must be a scalar number in the range 0 <= TOL < 1");
+ end
+ nd = ndims (z);
+ if (nargin < 3)
+ // Find the first singleton dimension.
+ sz = size (z);
+ dim = find (sz > 1, 1);
+ if isempty(dim)
+ dim = 1;
+ end
+ else
+ dim = floor (dim);
+ if (dim < 1 || dim > nd)
+ error ("cplxpair: invalid dimension DIM");
+ end
+ end
+ // Move dimension to analyze to first position, and convert to a 2-D matrix.
+ perm = [dim:nd, 1:dim-1];
+ z = permute (z, perm);
+ sz = size (z);
+ n = sz(1);
+ m = prod (sz) / n;
+ z = matrix (z, n, m);
+ // Sort the sequence in terms of increasing real values.
+ [temp, idx] = gsort (real (z), 1 , "i");
+ z = z(idx + n * ones (n, 1) * [0:m-1]);
+ // Put the purely real values at the end of the returned list.
+ [idxi, idxj] = find (abs (imag (z)) ./ (abs (z) + realmin) <= tol);
+ // Force values detected to be real within tolerance to actually be real.
+ z(idxi + n*(idxj-1)) = real (z(idxi + n*(idxj-1)));
+ //if idxi and idxj are not scalers
+ if ~isscalar(idxi) then
+ v = ones(size(idxi,1),size(idxi,2));
+ else
+ v = 1 ;
+ end
+ q = sparse ([idxi' idxj'], v, [n m]);
+ nr = sum (q, 1);
+ [temp, idx] = gsort (q, 'r','i');
+ midx = idx + size (idx,1) * ones (size (idx,1), 1) * [0:size(idx,2)-1];
+ z = z(midx);
+ zsort = z;
+ // For each remaining z, place the value and its conjugate at the start of
+ // the returned list, and remove them from further consideration.
+ for j = 1:m
+ p = n - nr(j);
+ for i = 1:2:p
+ if (i+1 > p)
+ error ("cplxpair: could not pair all complex numbers");
+ end
+ [v, idx] = min (abs (z(i+1:p,j) - conj (z(i,j))));
+ if (v >= tol * abs (z(i,j)))
+ error ("cplxpair: could not pair all complex numbers");
+ end
+ // For pairs, select the one with positive imaginary part and use it and
+ // it's conjugate, but list the negative imaginary pair first.
+ if (imag (z(i,j)) > 0)
+ zsort([i, i+1],j) = [conj(z(i,j)), z(i,j)];
+ else
+ zsort([i, i+1],j) = [conj(z(idx+i,j)), z(idx+i,j)];
+ end
+ z(idx+i,j) = z(i+1,j);
+ end
+ end
+ // Reshape the output matrix.
+ zsort = ipermute (matrix (zsort, sz), perm);
+endfunction
+