From a39bd69ca44806c5bef888ab90232e8bd77dfbe7 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 9 Aug 2020 19:27:54 +0100 Subject: [PATCH] compiler: Implement numpy.rint() using llvm.round() --- artiq/compiler/math_fns.py | 16 ++++++++++++++-- artiq/test/coredevice/test_numpy.py | 6 +++--- 2 files changed, 17 insertions(+), 5 deletions(-) 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]]))