diff --git a/CHANGES.rst b/CHANGES.rst index b807b6a7..23ab1a29 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -18,6 +18,10 @@ Changes ------- - Python >= 3.7 and numpy >= 1.16 are required for python extensions [#291] +Enhancements +------------ +- Warn about loss of precision for float32 calculations involving small ``theta`` in ``DDtheta_mocks`` and large ``mu`` in ``DDsmu_mocks`` [#299] + 2.5.0 (2022-12-23) ================ diff --git a/Corrfunc/mocks/DDsmu_mocks.py b/Corrfunc/mocks/DDsmu_mocks.py index 7e3c37cc..2d141187 100644 --- a/Corrfunc/mocks/DDsmu_mocks.py +++ b/Corrfunc/mocks/DDsmu_mocks.py @@ -8,6 +8,7 @@ from __future__ import (division, print_function, absolute_import, unicode_literals) +import warnings __author__ = ('Manodeep Sinha', 'Nick Hand') __all__ = ('DDsmu_mocks', ) @@ -296,6 +297,12 @@ def DDsmu_mocks(autocorr, cosmology, nthreads, mu_max, nmu_bins, binfile, integer_isa = translate_isa_string_to_enum(isa) sbinfile, delete_after_use = return_file_with_rbins(binfile) + + warn_large_mu(mu_max, + # RA and DEC are checked to be the same dtype + dtype=RA1.dtype, + ) + with sys_pipes(): extn_results = DDsmu_extn(autocorr, cosmology, nthreads, mu_max, nmu_bins, sbinfile, @@ -344,6 +351,27 @@ def DDsmu_mocks(autocorr, cosmology, nthreads, mu_max, nmu_bins, binfile, else: return results, api_time + +def warn_large_mu(mu_max, dtype): + ''' + Small theta values (large mu) underfloat float32. Warn the user. + Context: https://github.com/manodeep/Corrfunc/issues/296 (see also #297) + ''' + if dtype.itemsize > 4: + return + + if mu_max >= 0.9800666: # cos(0.2) + warnings.warn(""" +Be aware that small angular pair separations (mu near 1) will suffer from loss +of floating-point precision, as the input data is in float32 precision or +lower. In float32, the loss of precision is 1% in mu at separations of 0.2 +degrees, and larger at smaller separations. +For more information, see: +https://github.com/manodeep/Corrfunc/issues/296 (see also #297) +""" + ) + + if __name__ == '__main__': import doctest doctest.testmod() diff --git a/Corrfunc/mocks/DDtheta_mocks.py b/Corrfunc/mocks/DDtheta_mocks.py index 1ac29d9d..d4b144af 100644 --- a/Corrfunc/mocks/DDtheta_mocks.py +++ b/Corrfunc/mocks/DDtheta_mocks.py @@ -10,6 +10,7 @@ from __future__ import (division, print_function, absolute_import, unicode_literals) +import warnings __author__ = ('Manodeep Sinha', 'Kris Akira Stern') __all__ = ('DDtheta_mocks', 'find_fastest_DDtheta_mocks_bin_refs') @@ -313,6 +314,11 @@ def DDtheta_mocks(autocorr, nthreads, binfile, integer_isa = translate_isa_string_to_enum(isa) rbinfile, delete_after_use = return_file_with_rbins(binfile) + + warn_small_theta(rbinfile, + RA1.dtype, # RA and DEC are checked to be the same dtype + ) + with sys_pipes(): extn_results = DDtheta_mocks_extn(autocorr, nthreads, rbinfile, RA1, DEC1, @@ -644,6 +650,42 @@ def find_fastest_DDtheta_mocks_bin_refs(autocorr, nthreads, binfile, return ret +def warn_small_theta(thetabinfile, dtype): + ''' + Small theta values underfloat float32. Warn the user. + Context: https://github.com/manodeep/Corrfunc/issues/296 (see also #297) + ''' + if dtype.itemsize > 4: + return + + import numpy as np + try: + bins = np.loadtxt(thetabinfile) + except RuntimeError: + warnings.warn(""" +Could not load binfile "{}". Be aware that small angular pair separations +will suffer from loss of floating-point precision, as the input data is in +float32 precision or lower. The loss of precision is 0.5% in theta at +separations of 0.2 degrees, and larger at smaller separations. +For more information, see: +https://github.com/manodeep/Corrfunc/issues/296 (see also #297) +""".format(thetabinfile) + ) + return + + if bins.min() <= 0.2: + warnings.warn(""" +A binning with a minimum angular separation of 0.2 degrees or less was +requested, and the input data is in float32 precision or lower. Be aware that +small angular pair separations will suffer from loss of floating-point +precision. In float32, the loss of precision is 0.5% in theta at separations of +0.2 degrees, and larger at smaller separations. +For more information, see: +https://github.com/manodeep/Corrfunc/issues/296 (see also #297) +""" + ) + + if __name__ == '__main__': import doctest