|
|
|
|
The helical coordinate |
Quadratic convergence means that the square of the error
at one iteration is proportional to the error at the next iteration
Another interesting feature of the Newton iteration is that all iterations (except possibly the initial guess) are above the ultimate square root. This is obvious from equation (17).
We can insert spectral functions in the Newton square-root iteration,
for example
and
.
Where the first guess
happens to match
,
it will match
at all iterations.
The Newton iteration is
| (18) |
Now we are ready for the algorithm:
Compute the right side of (19)
by polynomial division forwards and backwards and then add 1.
Then abandon negative lags and take half of the zero lag.
Now you have
.
Multiply out (convolve) the denominator
,
and you have the desired result
.
Iterate as long as you wish.
(Parenthetically, for those people familiar with the idea
of minimum phase (if not, see FGDP or PVI),
we show that
is minimum phase:
Both sides of (19) are positive, as noted earlier.
Both terms on the right are positive.
Since the Newton iteration always overestimates,
the 1 dominates the rightmost term.
After masking off the negative powers of
(and half the zero power),
the right side of (19) adds two wavelets.
The 1/2 is wholly real,
and hence its real part always dominates the real part of the rightmost term.
Thus (after masking negative powers) the wavelet on
the right side of (19) has a positive real part,
so the phase cannot loop about the origin.
This wavelet multiplies
to give the final wavelet
and the product of two minimum-phase wavelets is minimum phase.)
The input of the program is the spectrum
and the output is the factor
,
a function with the spectrum
.
I mention here that in later chapters of this book,
the factor
is known as the inverse Prediction-Error Filter (PEF).
In the Wilson-Burg code below,
and
are
-transform polynomials
but their lead coefficients are extracted off,
so for example,
is broken into the two parts a0 and aa.
float wilson_factor(int niter /* number of iterations */,
float s0 /* zero-lag auto-correlation */,
sf_filter ss /* input auto-correlation */,
sf_filter aa /* output factor */,
bool verb /* verbosity flag */,
float tol /* tolerance */)
/*< Factor >*/
{
float eps;
int i, iter;
for(i=0; i < n2; i++) au[i] = 0.;
au[n-1] = s0;
b[0] = 1.; /* initialize */
for(i=0; i < ss->nh; i++) { /* symmetrize input auto */
au[n-1+ss->lag[i]] = ss->flt[i];
au[n-1-ss->lag[i]] = ss->flt[i];
}
sf_helicon_init( aa); /* multiply polynoms */
sf_polydiv_init( n2, aa); /* divide polynoms */
for(iter=0; iter < niter; iter++) {
sf_polydiv_lop(false,false, n2, n2, au, bb); /* S/A */
sf_polydiv_lop(true, false, n2, n2, cc, bb); /* S/(AA') */
eps = 0.;
for(i=1; i < n; i++) { /* b = plusside(1+cc) */
b[i] = 0.5*(cc[n-1+i] + cc[n-1-i]) / cc[n-1];
if (fabs(b[i]) > eps) eps = fabs(b[i]);
}
if (verb) sf_warning("wilson %d %f",iter,eps);
if (eps < tol) break;
sf_helicon_lop( false, false, n, n, b, c); /* c = A b */
/* put on helix */
for(i=0; i < aa->nh; i++) aa->flt[i] = c[aa->lag[i]];
}
return sqrtf(cc[n-1]);
}
|
|
|
|
|
The helical coordinate |