[R] convolve bug?
Bill Simpson
wsi at gcal.ac.uk
Mon Nov 22 12:28:35 CET 1999
Hi Martin,
> Yudi> I agree with Bill that convolve() should mean convolution
> Yudi> operation. So the default 'conj' should be set to F (Fourier
> Yudi> transform of a convolution is a product of the transfroms), and
> Yudi> the zero padding is on the right.
>
> I tend to agree.... see below
>
> Yudi> E.g., target: (2,2,3,3,4)*(1,1,2) = (2 4 9 10 13 10 8 )
>
> Yudi> convolve(c(2,2,3,3,4),c(2,1,1),type='o')
> Yudi> #[1] 2 4 9 10 13 10 8
> Yudi> convolve(c(2,2,3,3,4),c(1,1,2),conj=F,type='o')
> Yudi> #[1] 10 8 2 4 9 10 13 # almost
> Yudi> x _ c(2,2,3,3,4,0,0) # zero padding
> Yudi> y _ c(1,1,2,0,0,0,0)
> Yudi> aa_ fft(fft(x) * fft(y), inv = TRUE)
> Yudi> Re(aa)/length(aa)
> Yudi> #[1] 2 4 9 10 13 10 8 # wanted
> (there are indeed several ways to get this result, using
> combinations of Conj(), rev() and/or 0- padding...
I would strongly suggest that R uses the "standard" way of doing it--as
described in the linear systems and digital signal processing books.
The standard way of doing linear (aperiodic) convolution using fft:
Bracewell(1978, p.32) example:
x={2 2 3 3 4}, h={1 1 2}, x*h= {2 4 9 10 13 10 8} [* is convolution]
length: m n m+n-1
zero padded versions for linear convolution:
x={ 2 2 3 3 4 0 0}, h={1 1 2 0 0 0 0}
add n-1 zeros, add m-1 zeros
Then linear convolution is: ifft(fft(x)*fft(h))
> Yudi> I would suggest that the 'conj' option not be provided; when
> Yudi> conj=F, the type='f' option gives meaningless answer:
> ?? Contradiction:
> Above you say that conj=F should be the *default* ...
Yudi is right the second time: the conj option should NOT be there.
Instead, there should be TWO functions:
convolve does: fft(fft(a)*fft(b), inv=TRUE)
crosscorr does: fft(fft(a)*fft(Conj(b)), inv=TRUE)
This behaviour is fixed, not alterable.
> I agree that at least convolve(x,y)
> should really give what everyone expects..
Here is what I expect linear convolution to do:
myconvolve<-function (x,h)
{
nx <- length(x)
nh <- length(h)
#zero pad
if(nx>nh)
{
x <- c(x,rep(0, nh-1))
h<-c(h,rep(0,nx-1))
}
else
{
h <- c(h,rep(0, nx-1))
x<-c(x,rep(0,nh-1))
}
x <- fft(fft(x) * fft(h), inv = TRUE)
Re(x)/length(x)
#I am not sure about this, the R IFFT is weird
}
I am sure you R gurus can make this better.
I don't know how this works if x and h are 2D, say.
> One way to achieve this would be a new type,
> e.g. "regular" , "default" or "polynomial".
>
> And we would change the *default*
> - from type = "circular" to type = "regular" (or whatever we call it).
I think a nice pairing of terms is "circular" and "linear". I don't know
what the present "filter" is at all--I thought it was "linear", since I
think of linear convolution as filtering.
> - from conj = TRUE to conj = type != "circular"
> (conj defaulting to FALSE when type="open", ..)
>
> or do you think conj should default to FALSE even for circular?
NO, the structure of the code should be changed as I suggested above, so
that conj is gone as an argument. What "circular" should do is just
eliminate the zero-padding:
myconvolve2<-function (x,h)
{
#no padding, circular convolution
nx <- length(x)
nh <- length(h)
x <- fft(fft(x) * fft(h), inv = TRUE)
Re(x)/(nx)
}
> (I must admit not having seen a definition of a circular convolution in a
> text book..)
See Oppenheim &Schafer Discrete-time signal processing, 2nd ed p. 548 sec
8.2.5
> Yes, I'm waiting for further propositions, and I agree the defaults should
> be changed.
Great, I have presented my arguments above.
Bill
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
More information about the R-help
mailing list