From fed2769aa2f0f882c17f4efd524e72a67a19b4e1 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Sat, 29 Aug 2026 03:25:15 +0800 Subject: [PATCH 1/3] Respect custom hyperspherical distance integration bounds --- .../abstract_hypersphere_subset_distribution.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py b/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py index 0ae1b395e6..e493ccd409 100644 --- a/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py +++ b/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py @@ -339,8 +339,10 @@ def hellinger_distance(pdf1, pdf2): ) ) - distance_integral = self.__class__.integrate_fun_over_domain( - fangles_hellinger, self.dim + distance_integral = ( + AbstractHypersphereSubsetDistribution.integrate_fun_over_domain_part( + fangles_hellinger, integration_boundaries + ) ) return sqrt(0.5 * distance_integral) @@ -365,8 +367,10 @@ def total_variation_distance(pdf1, pdf2): ) ) - distance_integral = self.__class__.integrate_fun_over_domain( - fangles_total_variation, self.dim + distance_integral = ( + AbstractHypersphereSubsetDistribution.integrate_fun_over_domain_part( + fangles_total_variation, integration_boundaries + ) ) return 0.5 * distance_integral @@ -500,4 +504,4 @@ def compute_unit_hypersphere_surface(dim: Union[int, int32, int64]) -> float: surface_area = 2.0 * pi**2 else: surface_area = 2.0 * pi ** ((dim + 1) / 2) / gamma((dim + 1) / 2) - return surface_area + return surface_area \ No newline at end of file From 6e367197487b578afb0aedd3408b9ade0ac9edf0 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Sat, 29 Aug 2026 03:25:22 +0800 Subject: [PATCH 2/3] Add regression for custom hyperspherical distance bounds --- ..._hypersphere_subset_distance_validation.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/distributions/test_hypersphere_subset_distance_validation.py b/tests/distributions/test_hypersphere_subset_distance_validation.py index 6e05d0b905..f6685ce00d 100644 --- a/tests/distributions/test_hypersphere_subset_distance_validation.py +++ b/tests/distributions/test_hypersphere_subset_distance_validation.py @@ -1,5 +1,8 @@ import unittest +import pyrecest.backend +from pyrecest.backend import array, pi +from pyrecest.distributions import VonMisesFisherDistribution from pyrecest.distributions.hypersphere_subset.hyperspherical_uniform_distribution import ( HypersphericalUniformDistribution, ) @@ -20,6 +23,29 @@ def test_total_variation_distance_rejects_dimension_mismatch(self): with self.assertRaisesRegex(ValueError, "different number of dimensions"): dist.total_variation_distance_numerical(other) + @unittest.skipIf( + pyrecest.backend.__backend_name__ == "jax", + "Numerical hyperspherical integration is not supported on JAX.", + ) + def test_distances_respect_custom_integration_boundaries(self): + dist = VonMisesFisherDistribution(array([1.0, 0.0]), 2.0) + other = VonMisesFisherDistribution(array([0.0, 1.0]), 1.0) + partial_boundaries = array([[0.0, pi / 2.0]]) + + for distance_name in ( + "hellinger_distance_numerical", + "total_variation_distance_numerical", + ): + with self.subTest(distance=distance_name): + distance = getattr(dist, distance_name) + full_distance = float(distance(other)) + partial_distance = float( + distance(other, integration_boundaries=partial_boundaries) + ) + + self.assertGreater(partial_distance, 0.0) + self.assertLess(partial_distance, full_distance) + if __name__ == "__main__": unittest.main() From c4777d290f6494d439986b83a1e5d054de8bee43 Mon Sep 17 00:00:00 2001 From: Florian Pfaff <6773539+FlorianPfaff@users.noreply.github.com> Date: Sat, 29 Aug 2026 03:27:12 +0800 Subject: [PATCH 3/3] Restore trailing newline in hypersphere distribution source --- .../abstract_hypersphere_subset_distribution.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py b/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py index e493ccd409..28416bcf8e 100644 --- a/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py +++ b/src/pyrecest/distributions/hypersphere_subset/abstract_hypersphere_subset_distribution.py @@ -504,4 +504,4 @@ def compute_unit_hypersphere_surface(dim: Union[int, int32, int64]) -> float: surface_area = 2.0 * pi**2 else: surface_area = 2.0 * pi ** ((dim + 1) / 2) / gamma((dim + 1) / 2) - return surface_area \ No newline at end of file + return surface_area