How to emulate ulp/1 evaluable function in Prolog

52 views Asked by At

I find myself using the Java function Math.ulp() from time
to time. It has an implementation based on unpacking
a float number, and doing some bit shuffling. How would one

bootstrap ulp() from ISO core standard arithmetic
functions only in Prolog? Here are some test cases:

?- X is -pi, 'Math':ulp(X, Y).
X = -3.141592653589793, Y = 4.440892098500626E-16.

?- 'Math':ulp(1.0E10, X).
X = 1.9073486328125E-6.

Edit 28.10.2022:
I was able to bootstrap the function in SWI-Prolog, as follows,
agrees on the two examples, for positive floating point values only:

ulp(X, Y) :- Y is nexttoward(X, 1.7976931348623157E+308) - X.

?- X is pi, ulp(X, Y).
X = 3.141592653589793,
Y = 4.440892098500626e-16.

?- ulp(1.0E10, X).
X = 1.9073486328125e-6.

But many Prolog systems don't have nexttoward/2.
So I am again left with a bootstrapping problem.

1

There are 1 answers

0
Rúben Dias On

After having a look at this code:
https://github.com/jcoreio/ulp/blob/master/lib/index.js

I tried this Prolog realization, for positive floating point values only:

nextup(X, R) :- 
    Y is X*(1+epsilon),
    C is (X+Y)/2,
    (X < C, C < Y -> R=C; R=Y).

ulp2(X, Y) :- nextup(X, H), Y is H - X.

Seems to be ok:

?- between(1, 1000000, N), X is float(N+2^52), ulp(X,A), ulp2(X,B), A=\=B.
false.