My use case is frequency demodulation using the method of Coats and Randall, with the link being one of many from a web search. They use the Hilbert transform for this purpose.

When I use ifft in MATLAB on a complex vector, the resulting vector is ~2x the length of the input vector.

In the MATLAB case the complex vector does not have the symmetry of having the positive and negative frequencies present. So what I think is happening is that MATLAB adds in the negative frequencies and then performs the ifft from the call to the FFTW library. Using this hypothesis I wrote the following code to do what I think MATLAB is doing:

# sf is the complex frequency vector obtained via rfft
# In this case it is assumed that the amplitude has been normalized by multiplying by 2 (except the DC component and the Nyquist frequency if the length is even.
nsf = length(sf)
if iseven(nsf)
sfd = Vector{ComplexF64}(undef, 2nsf-2)
sfd[1] = sf[1]
sfd[2:nsf-1] = sf[2:nsf-1] ./ 2
sdf[nsf] = sf[nsf]
sfd[nsf+1:end] = sfd[nsf-1:-1:2]
else
sfd = Vector{ComplexF64}(undef, 2nsf-1)
sfd[1] = sf[1]
sfd[2:nsf] = sf[2:nsf] ./ 2
sfd[nsf+1:end] = sfd[nsf:-1:2]
end
sc = ifft(sfd).*n # complex time from hilbert transform

Doing this I get a result that is different from Matlab. I am wondering if anyone has insight into this.

Thanks for the challenge of making a MWE. It turns out that some of my thinking was wrong. This is what I should have been doing:

Transform to frequency domain

Set negative frequency components to zero

Multiply positive frequency components by 2 (do not change zero frequency component and take care with the Nyquist frequency component)

Transform back to time domain

Take real part of the analytic signal

Ergo, you have the original signal.

As an example

using FFTW
# Create signal
dt = 0.2
t = 0:dt:1
y = sin.(2*pi*t)
df = 1/t[end]
yf = fft(y)
# Make signal one sided like rfft
n = length(t)
np = div(n, 2) + 1
yf[np+1:end] = zeros(ComplexF64, n-np)
# Put energy lost from zeroing -ve frequency back in
if iseven(n)
yf[2:np-1] = 2*yf[2:np-1]
else
yf[2:np] = 2*yf[2:np]
end
# Inverse FFT
ynew = ifft(yf)
[y ynew] # compare y with real part of ynew