Skip to content

Instantly share code, notes, and snippets.

@robotsorcerer
Last active October 19, 2019 16:24
Show Gist options
  • Save robotsorcerer/75f7850b768fc9b74fcd3edfed96e997 to your computer and use it in GitHub Desktop.
Save robotsorcerer/75f7850b768fc9b74fcd3edfed96e997 to your computer and use it in GitHub Desktop.
import numpy as np
"""
For details, see
[1] https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF
[2] https://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html?highlight=round#numpy.around
Thanks to fesetround from ctypes. We can manually set the rounding mode
"""
import ctypes, sys
ROUND_TONEAREST = 0x0000
ROUND_DOWNWARD = 0x0400
ROUND_UPWARD = 0x0800
ROUND_TOWARDZERO = 0x0c00
if (sys.platform).lower() == 'darwin': # MAC
libc = ctypes.CDLL('libc.dylib')
elif sys.platform.lower() == 'linux': # Linux
libc = ctypes.CDLL('libm.so.6')
else:
print("Windows not supported")
def rounding(x):
if not isinstance(x, np.ndarray): # scalar
w, f = str(x).split(".")
if not w.startswith('-'): # +ve number
if f.startswith('5'): # midpoint
libc.fesetround(ROUND_UPWARD)
else:
libc.fesetround(ROUND_TONEAREST)
if w.startswith('-'):
if f.startswith('5'):
libc.fesetround(ROUND_DOWNWARD)
else:
libc.fesetround(ROUND_TONEAREST)
res = np.round(x)
else:
orig_shape = x.shape
if x.ndim > 1:
x = x.flatten()
res = []
for elem in x:
w, f = str(elem).split(".")
if not w.startswith('-'): # -ve number
if f.startswith('5'): # # midpoint
libc.fesetround(ROUND_UPWARD)
else:
libc.fesetround(ROUND_TONEAREST)
if w.startswith('-'):
if f.startswith('5'):
libc.fesetround(ROUND_DOWNWARD)
else:
libc.fesetround(ROUND_TONEAREST)
res.append(np.round(elem))
res = np.array(res).reshape(orig_shape)
return res
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment