Skip to content

Commit 76031a0

Browse files
committed
BF: account for float rouding in 64 bit (u)ints
Input / output of int64 -> uint64 and uint64 -> int64 need to go through floating point types as they are stored and loaded. If the best floating point type is not capable of 64 bits of integer precision, there will be rounding error; we need to take this into account.
1 parent a10b141 commit 76031a0

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

nibabel/tests/test_round_trip.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def check_params(in_arr, in_type, out_type):
3838
return arr, arr_dash, slope, inter
3939

4040

41-
LOGe2 = np.log(best_float()(2))
41+
BFT = best_float()
42+
LOGe2 = np.log(BFT(2))
4243

4344

4445
def big_bad_ulp(arr):
@@ -59,8 +60,7 @@ def big_bad_ulp(arr):
5960
"""
6061
# Assumes array is floating point
6162
arr = np.asarray(arr)
62-
floater = best_float()
63-
working_arr = np.abs(arr.astype(floater))
63+
working_arr = np.abs(arr.astype(BFT))
6464
# Log2 for numpy < 1.3
6565
l2 = np.log(working_arr) / LOGe2
6666
fl2 = np.floor(l2)
@@ -119,7 +119,15 @@ def check_arr(test_id, V_in, in_type, out_type, scaling_type):
119119
rel_err = np.abs(top / arr)
120120
abs_err = np.abs(top)
121121
if slope == 1: # integers output, offset only scaling
122-
exp_abs_err = np.zeros_like(abs_err)
122+
if (set((in_type, out_type)) == set((np.int64, np.uint64)) and
123+
type_info(BFT)['nmant'] < 63):
124+
# We'll need to go through lower precision floats
125+
A = arr.astype(BFT)
126+
Ai = A - inter
127+
ulps = [big_bad_ulp(A), big_bad_ulp(Ai)]
128+
exp_abs_err = np.max(ulps, axis=0)
129+
else: # we don't have to go through floats - no error !
130+
exp_abs_err = np.zeros_like(abs_err)
123131
rel_thresh = 0
124132
else:
125133
# Error from integer rounding

0 commit comments

Comments
 (0)