From 7ed6bf090129906021f0c3c4aaa2f7e24086e210 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:05:57 +0800 Subject: [PATCH 1/2] Validate hypertoroidal Fourier coefficient counts --- src/pyrecest/filters/hypertoroidal_fourier_filter.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pyrecest/filters/hypertoroidal_fourier_filter.py b/src/pyrecest/filters/hypertoroidal_fourier_filter.py index a198df740e..9e045b3f01 100644 --- a/src/pyrecest/filters/hypertoroidal_fourier_filter.py +++ b/src/pyrecest/filters/hypertoroidal_fourier_filter.py @@ -20,6 +20,7 @@ ) from pyrecest.distributions.hypertorus.hypertoroidal_fourier_distribution import ( HypertoroidalFourierDistribution, + _normalize_coefficient_shape, ) from .abstract_filter import AbstractFilter @@ -56,9 +57,11 @@ def __init__(self, n_coefficients, transformation="sqrt"): "HypertoroidalFourierFilter is not supported on the " f"{pyrecest.backend.__backend_name__} backend." ) - if isinstance(n_coefficients, int): - n_coefficients = (n_coefficients,) - n_coefficients = tuple(int(n) for n in n_coefficients) + n_coefficients = _normalize_coefficient_shape( + n_coefficients, + "n_coefficients", + require_odd=True, + ) dim = len(n_coefficients) # Build a uniform HFD directly (only the DC component is non-zero) From 0002c8686e23d3dae92b68d801e978df43491d00 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:06:08 +0800 Subject: [PATCH 2/2] Add Fourier coefficient validation regression tests --- ...l_fourier_filter_coefficient_validation.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/filters/test_hypertoroidal_fourier_filter_coefficient_validation.py diff --git a/tests/filters/test_hypertoroidal_fourier_filter_coefficient_validation.py b/tests/filters/test_hypertoroidal_fourier_filter_coefficient_validation.py new file mode 100644 index 0000000000..d64d062f4a --- /dev/null +++ b/tests/filters/test_hypertoroidal_fourier_filter_coefficient_validation.py @@ -0,0 +1,39 @@ +import unittest + +import numpy as np + +import pyrecest.backend +from pyrecest.filters.hypertoroidal_fourier_filter import HypertoroidalFourierFilter + + +@unittest.skipIf( + pyrecest.backend.__backend_name__ in ("jax", "pytorch"), + reason="HypertoroidalFourierFilter is not supported on this backend", +) +class TestHypertoroidalFourierFilterCoefficientValidation(unittest.TestCase): + def test_accepts_numpy_integer_scalar(self): + fourier_filter = HypertoroidalFourierFilter(np.int64(11)) + + self.assertEqual(fourier_filter.filter_state.coeff_mat.shape, (11,)) + + def test_rejects_values_that_would_be_silently_reinterpreted(self): + invalid_values = ( + True, + "11", + (), + (11.5,), + (11.0,), + ) + + for value in invalid_values: + with self.subTest(value=value): + with self.assertRaises((TypeError, ValueError)): + HypertoroidalFourierFilter(value) + + def test_rejects_nonpositive_or_even_coefficient_counts(self): + invalid_values = (0, -1, 10, (11, 0), (11, 12)) + + for value in invalid_values: + with self.subTest(value=value): + with self.assertRaisesRegex(ValueError, "n_coefficients"): + HypertoroidalFourierFilter(value)