diff --git a/artiq/compiler/math_fns.py b/artiq/compiler/math_fns.py index 3dfb0c580..e29c3625b 100644 --- a/artiq/compiler/math_fns.py +++ b/artiq/compiler/math_fns.py @@ -15,8 +15,20 @@ unary_fp_intrinsics = [(name, "llvm." + name + ".f64") for name in [ "floor", "ceil", "trunc", - "rint", -]] +]] + [ + # numpy.rint() seems to (NumPy 1.19.0, Python 3.8.5, Linux x86_64) + # implement round-to-even, but unfortunately, rust-lang/libm only + # provides round(), which always rounds away from zero. + # + # As there is no equivalent of the latter in NumPy (nor any other + # basic rounding function), expose round() as numpy.rint anyway, + # even if the rounding modes don't match up, so there is some way + # to do rounding on the core device. (numpy.round() has entirely + # different semantics; it rounds to a configurable number of + # decimals.) + ("rint", "llvm.round.f64"), +] + #: float -> float numpy.* math functions lowered to runtime calls. unary_fp_runtime_calls = [ diff --git a/artiq/test/coredevice/test_numpy.py b/artiq/test/coredevice/test_numpy.py index 7cc906087..715aedaea 100644 --- a/artiq/test/coredevice/test_numpy.py +++ b/artiq/test/coredevice/test_numpy.py @@ -90,6 +90,6 @@ class CompareHostDeviceTest(ExperimentCase): ] for name in names: op = "numpy.{}(a)".format(name) - print(op) - self._test_unaryop(op, 0.5) - self._test_unaryop(op, numpy.array([[0.3, 0.4], [0.5, 0.6]])) + # Avoid 0.5, as numpy.rint's rounding mode currently doesn't match. + self._test_unaryop(op, 0.51) + self._test_unaryop(op, numpy.array([[0.3, 0.4], [0.51, 0.6]]))