View Raw SPL
/*****************************************************************************
* *
* ORTH.SPL Copyright (C) 2001 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Computes orthonormal basis series using SVD *
* *
* Revisions: 9 Jul 2001 RRR Creation *
* *
*****************************************************************************/
#include
#if @HELP_ORTH
ORTH
Purpose: Computes an orthonormal basis of an array using SVD
Syntax: ORTH(a)
a - input array
Returns: An orthonormal array of n columns where n == rank(a)
Example:
W1: {{1, 3},
{2, 2},
{3, -1}}
W2: orth(w1)
W2 contains the array:
{{-0.666667, -0.447214},
{-0.666667, 0.000000},
{-0.333333, 0.894427}}
Since W2 is an orthonormal basis for W1,
col(w2, 1)' *^ col(w2, 1) == {1} // orthonormal
col(w2, 1)' *^ col(w2, 2) == {-1.665335E-016} // orthogonal
w2' *^ w2 == {{1, 0}, // identity
{0, 1}}
Now construct a new series that is a linear combination
of the original series:
W3: 2*col(w1, 1) - 5*col(w1, 2)
W3 == {-13, -6, 11}
W3 can also be expressed as a linear combination of W2, the
orthonormal basis:
a1 = w3' *^ col(w2, 1)
a2 = w3' *^ col(w2, 2)
W4: a1 * col(w2, 1) + a2 * col(w2, 1)
a1 == {9.0}
a2 == {15.652476}
W4 == {-13, -6, 11}
Remarks:
ORTH uses SVD to compute the orthonormal basis. The number
of output columns is limited to the RANK of the input
array.
See Also:
Norm
Rank
SVD
#endif
/* find orthonormal basis using SVD */
orth(a)
{
local u, w, v, rank, nc, nr, tol;
(nr, nc) = size(a);
/* check if empty */
if (nr == 0) return(a);
if (not(isarray(a))) a = {a};
/* find u, orthogonal matrix via svd */
(u, w, v) = svd(a);
/* find number of output columns by computing rank */
tol = maxval(nr, nc) * w[1] * eps;
rank = sum(w > tol);
/* extract columns */
return(u[.., 1..rank]);
}