Skip to content

Commit 29d3bb3

Browse files
committed
Further improve bin1d_vec (1): Re-organize + make tolerance depend on dtype
* outsource `tol` from if condition * reorder some operations/checks * reorder/group terms in idx calculation to honor floating point arithmetics * revise/add comments
1 parent d4e905e commit 29d3bb3

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

csep/utils/calc.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ def discretize(data, bin_edges, right_continuous=False):
5151
x_new = bin_edges[idx]
5252
return x_new
5353

54+
def _get_tolerance(v):
55+
"""Determine a numerical tolerance due to limited precision of floating-point values.
56+
57+
In other words, returns a maximum possible difference that can be considered negligible.
58+
Only relevant for floating-point values.
59+
"""
60+
if issubclass(v.dtype.type, numpy.floating):
61+
return numpy.abs(v) * numpy.finfo(v.dtype).eps
62+
return 0 # assuming it's an int
63+
5464
def bin1d_vec(p, bins, tol=None, right_continuous=False):
5565
"""Efficient implementation of binning routine on 1D Cartesian Grid.
5666
@@ -71,26 +81,24 @@ def bin1d_vec(p, bins, tol=None, right_continuous=False):
7181
"""
7282
bins = numpy.array(bins)
7383
p = numpy.array(p)
84+
7485
a0 = numpy.min(bins)
75-
# if user supplies only a single bin, do 2 things: 1) fix right continuous to true, and use of h is arbitrary
7686
if bins.size == 1:
87+
# for a single bin, set `right_continuous` to true; h is now arbitrary
7788
right_continuous = True
78-
h = 1
89+
h = bins[0] # (just take over dtype)
7990
else:
8091
h = bins[1] - bins[0]
8192

82-
a0_tol = numpy.abs(a0) * numpy.finfo(numpy.float64).eps
83-
h_tol = a0_tol # must be based on *involved* numbers
84-
p_tol = numpy.abs(p) * numpy.finfo(numpy.float64).eps
85-
86-
# absolute tolerance
87-
if tol is None:
88-
idx = numpy.floor((p + (p_tol + a0_tol) - a0) / (h - h_tol))
89-
else:
90-
idx = numpy.floor((p + (tol + a0_tol) - a0) / (h - h_tol))
9193
if h < 0:
9294
raise ValueError("grid spacing must be positive and monotonically increasing.")
93-
# account for floating point uncertainties by considering extreme case
95+
96+
# account for floating point precision
97+
a0_tol = _get_tolerance(a0)
98+
h_tol = a0_tol # must be based on *involved* numbers
99+
p_tol = tol or _get_tolerance(p)
100+
101+
idx = numpy.floor((p - a0 + p_tol + a0_tol) / (h - h_tol))
94102

95103
if right_continuous:
96104
# set upper bin index to last

0 commit comments

Comments
 (0)