Fesetround in njit function

I’m playing with Interval Arithmetic (e.g. see Validated Numerics by Tucker).

Naturally wanted to use numba for speed.

Vanilla Python function does what expected. First print:

(0.09999999999999999, 0.1)

second print with numba.njit produces something unexpected:

(0.09999999999999999, 0.09999999999999999)

adding mathematically insignificant + 1 - 1 restores expected behavior. (see comment in code)

It looks like somewhere in the numba/llvm belly repeating `x/y’ gets optimized away into a single computation.

Which for my purpose breaks intended sequence of execution. Is there a way to control this sort of optimization in numba.njit?


from numba import njit
from ctypes import cdll, c_int

fesetround = cdll.ucrtbased.fesetround
fesetround.restype = c_int
fesetround.argtypes = [c_int]

FE_DOWN = 0x0100
FE_UP = 0x0200
FE_NEAR = 0x0

def test_div(x, y):
    a = x/ y

    # un-comment to get expected behavior
    b = x/ y # + 1 - 1

    return a, b

print("py:", test_div(1, 10))
print("nb:", njit(test_div)(1, 10))

Been playing with equivalent C:

#include <fenv.h>
#include <stdio.h>

int main() {
  double x = 1, y = 10;

  double a = x / y;
  double b = x / y;

  printf("%g %g\n", a, b);
  return 0;

compiling with -O0 produces expected
clang main.c -o main -lm -Wall -g -O0
0.1 0.0999999

compiling with -O1 produces un-expected or rather un-desired:
clang main.c -o main -lm -Wall -g -O1
0.1 0.1

In C it does appear to be some sort of optimization induced result. Oh and adding +1-1 does not fool the c compiler.