Thank you for the Fourier implementation in the newest release! Stan defines the fft
u\in\mathbb{C}^N of a complex vector v\in\mathbb{C}^N as
Numpy instead defines it as
These are identical up to the difference in summation (over all indices for numpy and only over “time” indices less than “frequency” indices in Stan). Of course, not everything needs to follow the same conventions as numpy, but I just wanted to understand the summation convention in Stan because it differs from previous definitions I’ve seen, e.g. on wikipedia.
The results also seem to differ when comparing test data.
// test_fft.stan
data {
int n;
vector[n] x;
}
generated quantities {
complex_vector[n] y = fft(x);
}
# test_fft.py
import cmdstanpy
import numpy as np
np.random.seed(0)
model = cmdstanpy.CmdStanModel(stan_file="test_fft.stan")
n = 3
x = np.random.normal(0, 1, n)
fit = model.sample({"n": n, "x": x}, fixed_param=True, iter_warmup=0, iter_sampling=1)
stan_fft, = fit.stan_variable("y")
np_fft = np.fft.fft(x)
for label, fft in [("stan", stan_fft), ("np", np_fft)]:
print(label)
print("real", np.round(fft.real, 3))
print("imag", np.round(fft.imag, 3))
print()
cmdstanpy.show_versions()
# output
stan
real [3.143 0. 1.075]
imag [ 0.501 1.075 -0.501]
np
real [3.143 1.075 1.075]
imag [ 0. 0.501 -0.501]
INSTALLED VERSIONS
---------------------
python: 3.10.0 (default, Jan 15 2022, 13:32:36) [Clang 12.0.5 (clang-1205.0.22.9)]
python-bits: 64
OS: Darwin
OS-release: 21.6.0
machine: arm64
processor: arm
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: ('en_US', 'UTF-8')
cmdstan_folder: /Users/till/.cmdstan/cmdstan-2.30.1
cmdstan: (2, 30)
cmdstanpy: 1.0.4
pandas: 1.4.3
xarray: None
tdqm: None
numpy: 1.22.1
ujson: 5.4.0
Do you know why the values differ? As the signal is real, I would’ve expected the zero-frequency term to have zero imaginary part (as numpy does).