View Raw SPL
/*****************************************************************************
* *
* FDECONV.SPL Copyright (C) 2002-2007 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Deconvolves two series using FFTs *
* *
* Revisions: 28 Aug 2002 RRR Creation *
* 1 Dec 2006 RRR ITERATE for simple column iteration *
* 6 Aug 2007 RRR complex input check *
* *
*****************************************************************************/
#if @HELP_FDECONV
FDECONV
Purpose: Deconvolves two series using FFTs.
Syntax: (q, r) = FDECONV(b, a)
b - A series.
a - A series.
Returns: A series such that b = conv(a, q) + r
Example:
a = {0, 3, 2, 3};
x = {1, 2, 1};
b = conv(a, x);
(q, r) = fdeconv(b, a);
b == {0, 3, 8, 10, 8, 3}
q == {1, 2, 1}
r == {0, 0, 0, 0, 0, 0}
a = gnorm(1000,.01)
x = gsin(1000,.001,3)
b = conv(x, a)
q = fdeconv(b, a)
q recovers the 3 Hertz sinewave.
Remarks:
FDECONV is appropriate for recovering a series from a convolution
process. FDECONV uses the FFT to compute the deconvolution with:
real(ifft(fft(b) / fft(a)))
If the denominator series a contains a zero, the FFT quotient
value is replaced by DEFAULT_MATH_VALUE.
See DECONV for a time domain implementation that also calculates
the polynomial quotient.
See Also:
Conv
Deconv
Fconv
#endif
/* fft based deconvolution */
ITERATE fdeconv(b, a)
{
local la, lb, r, s, af, bf, flen;
lb = length(b);
la = length(a);
flen = 2 ^ (nextpow2(max(lb, la)) - 1);
/* use a factor of 3 to avoid denominator zeros */
flen *= 3;
/* divide FFTs */
bf = fft(b, flen);
af = fft(a, flen);
s = ifft(bf / af);
/* check if result should be purely real */
if (not(iscomplex(a)) && not(iscomplex(b)))
{
s = real(s);
}
/* proper lengths */
s = extract(s, 1, lb - la + 1);
setdeltax(s, deltax(b));
if (outargc > 1)
{
/* get remainder */
r = b - fconv(s, a);
return(s, r);
}
else
{
return(s);
}
}