Skip to content

feat: implement Chirp Z-Transform (CZT) and zoom_fft#32

Merged
polvalente merged 6 commits into
elixir-nx:mainfrom
thomaspmurphy:feat/chirp-z-transform
Jun 30, 2026
Merged

feat: implement Chirp Z-Transform (CZT) and zoom_fft#32
polvalente merged 6 commits into
elixir-nx:mainfrom
thomaspmurphy:feat/chirp-z-transform

Conversation

@thomaspmurphy

@thomaspmurphy thomaspmurphy commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Adds NxSignal.czt/2 (Bluestein's algorithm, $O((N+M)log(N+M))$ ) and NxSignal.zoom_fft/4 for evaluating the z-transform on an arbitrary spiral contour or zoomed frequency band. Includes tests and a Livebook guide.

Adds `NxSignal.czt/2` (Bluestein's algorithm, O((N+M)log(N+M))) and
`NxSignal.zoom_fft/4` for evaluating the z-transform on an arbitrary
spiral contour or zoomed frequency band. Includes tests and a Livebook
guide.

@polvalente polvalente left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I haven't read the guide yet, but there are some minor adjustments for the implementation!

Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex
Preserve input precision via Nx.Type.to_complex/to_real, add axis option
with vectorize-based batching, fix doctest assertions, simplify a^-n term.
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment thread lib/nx_signal.ex Outdated
Comment on lines +763 to +767
iex> NxSignal.czt(Nx.tensor([1.0, 0.0, 0.0, 0.0])) |> Nx.real() |> Nx.round()
#Nx.Tensor<
f32[4]
[1.0, 1.0, 1.0, 1.0]
>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
iex> NxSignal.czt(Nx.tensor([1.0, 0.0, 0.0, 0.0])) |> Nx.real() |> Nx.round()
#Nx.Tensor<
f32[4]
[1.0, 1.0, 1.0, 1.0]
>
iex> NxSignal.czt(Nx.tensor([1.0, 0.0, 0.0, 0.0]))
#Nx.Tensor<
f32[4]
[1.0, 1.0, 1.0, 1.0]
>

Assert on the regular output here. Nx.round doesn't have precision, so anything between 0.5 and 1.5 would round to 1

@thomaspmurphy thomaspmurphy Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm the output type is c64[4], not f32[4]. It also has floating-point noise from Bluestein's (~6×10⁻⁸), so the suggested expected output would fail on both type and values. Possible alternative that avoids Nx.round entirely?

iex> NxSignal.czt(Nx.tensor([1.0, 2.0, 3.0, 4.0]), output_length: 1)
#Nx.Tensor<
  c64[1]
  [10.0+0.0i]
>

This evaluates the z-transform at a single point (z=1, sum of all samples) which gives an exact complex result. What do you think?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can assert on the actual result type and value. It's fine if the doctest is not "nice and round"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, okay

Comment thread lib/nx_signal.ex Outdated
Comment thread test/nx_signal_test.exs
Comment thread test/nx_signal_test.exs Outdated
Comment thread test/nx_signal_test.exs Outdated
Comment thread guides/chirp_z.livemd Outdated
Comment thread guides/chirp_z.livemd Outdated
Comment thread guides/chirp_z.livemd Outdated
Comment thread lib/nx_signal.ex Outdated
@thomaspmurphy
thomaspmurphy requested a review from polvalente June 19, 2026 10:30
@polvalente
polvalente merged commit 83952cd into elixir-nx:main Jun 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants